alexandria-book-collection-manager 0.7.5 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +9 -0
- data/.github/workflows/ruby.yml +72 -0
- data/.gitignore +4 -1
- data/.rubocop.yml +65 -30
- data/.rubocop_todo.yml +49 -165
- data/.simplecov +5 -2
- data/CHANGELOG.md +64 -0
- data/ChangeLog.0 +19 -19
- data/INSTALL.md +26 -16
- data/README.md +31 -35
- data/Rakefile +18 -16
- data/alexandria-book-collection-manager.gemspec +35 -29
- data/doc/FAQ +2 -2
- data/doc/dependency_decisions.yml +22 -3
- data/lib/alexandria/about.rb +1 -1
- data/lib/alexandria/book_providers/bl_provider.rb +88 -0
- data/lib/alexandria/book_providers/douban.rb +2 -2
- data/lib/alexandria/book_providers/loc_provider.rb +38 -0
- data/lib/alexandria/book_providers/pseudomarc.rb +61 -71
- data/lib/alexandria/book_providers/sbn_provider.rb +108 -0
- data/lib/alexandria/book_providers/{thalia.rb → thalia_provider.rb} +37 -74
- data/lib/alexandria/book_providers/web.rb +2 -2
- data/lib/alexandria/book_providers/worldcat.rb +34 -38
- data/lib/alexandria/book_providers/z3950_provider.rb +199 -0
- data/lib/alexandria/book_providers.rb +48 -65
- data/lib/alexandria/default_preferences.rb +2 -1
- data/lib/alexandria/execution_queue.rb +13 -12
- data/lib/alexandria/export_library.rb +21 -22
- data/lib/alexandria/image_fetcher.rb +25 -0
- data/lib/alexandria/import_library.rb +46 -70
- data/lib/alexandria/import_library_csv.rb +16 -16
- data/lib/alexandria/library_sort_order.rb +3 -1
- data/lib/alexandria/library_store.rb +19 -20
- data/lib/alexandria/logging.rb +5 -9
- data/lib/alexandria/models/book.rb +15 -2
- data/lib/alexandria/models/library.rb +31 -35
- data/lib/alexandria/net.rb +1 -2
- data/lib/alexandria/preferences.rb +27 -33
- data/lib/alexandria/scanners/cue_cat.rb +6 -6
- data/lib/alexandria/scanners/keyboard.rb +1 -1
- data/lib/alexandria/scanners.rb +2 -2
- data/lib/alexandria/smart_library.rb +22 -26
- data/lib/alexandria/ui/about_dialog.rb +1 -1
- data/lib/alexandria/ui/acquire_dialog.rb +15 -19
- data/lib/alexandria/ui/alert_dialog.rb +36 -19
- data/lib/alexandria/ui/bad_isbns_dialog.rb +13 -9
- data/lib/alexandria/ui/barcode_animation.rb +6 -6
- data/lib/alexandria/ui/book_properties_dialog.rb +2 -3
- data/lib/alexandria/ui/book_properties_dialog_base.rb +35 -137
- data/lib/alexandria/ui/calendar_popup.rb +58 -0
- data/lib/alexandria/ui/callbacks.rb +144 -123
- data/lib/alexandria/ui/completion_models.rb +2 -6
- data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -1
- data/lib/alexandria/ui/conflict_while_copying_dialog.rb +2 -2
- data/lib/alexandria/ui/error_dialog.rb +1 -1
- data/lib/alexandria/ui/export_dialog.rb +19 -18
- data/lib/alexandria/ui/icons.rb +34 -40
- data/lib/alexandria/ui/iconview_tooltips.rb +40 -53
- data/lib/alexandria/ui/import_dialog.rb +49 -48
- data/lib/alexandria/ui/init.rb +14 -12
- data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +2 -2
- data/lib/alexandria/ui/libraries_combo.rb +10 -9
- data/lib/alexandria/ui/listview.rb +6 -7
- data/lib/alexandria/ui/main_app.rb +2 -2
- data/lib/alexandria/ui/multi_drag_treeview.rb +5 -7
- data/lib/alexandria/ui/new_book_dialog.rb +63 -65
- data/lib/alexandria/ui/new_book_dialog_manual.rb +1 -1
- data/lib/alexandria/ui/new_provider_dialog.rb +12 -11
- data/lib/alexandria/ui/new_smart_library_dialog.rb +39 -27
- data/lib/alexandria/ui/preferences_dialog.rb +25 -84
- data/lib/alexandria/ui/provider_preferences_base_dialog.rb +10 -6
- data/lib/alexandria/ui/provider_preferences_dialog.rb +5 -5
- data/lib/alexandria/ui/really_delete_dialog.rb +2 -2
- data/lib/alexandria/ui/sidepane_manager.rb +38 -38
- data/lib/alexandria/ui/skip_entry_dialog.rb +3 -2
- data/lib/alexandria/ui/smart_library_properties_dialog.rb +35 -36
- data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +61 -244
- data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
- data/lib/alexandria/ui/sound.rb +4 -6
- data/lib/alexandria/ui/ui_manager.rb +80 -83
- data/lib/alexandria/ui.rb +7 -7
- data/lib/alexandria/version.rb +2 -2
- data/lib/alexandria/web_themes.rb +15 -15
- data/lib/alexandria.rb +2 -2
- data/po/cs.po +947 -865
- data/po/cy.po +913 -864
- data/po/de.po +961 -865
- data/po/el.po +956 -861
- data/po/es.po +952 -857
- data/po/fr.po +950 -865
- data/po/ga.po +866 -819
- data/po/gl.po +946 -861
- data/po/it.po +945 -858
- data/po/ja.po +921 -836
- data/po/mk.po +953 -858
- data/po/nb.po +932 -847
- data/po/nl.po +955 -849
- data/po/pl.po +999 -963
- data/po/pt.po +946 -850
- data/po/pt_BR.po +944 -859
- data/po/ru.po +959 -868
- data/po/sk.po +950 -863
- data/po/sv.po +944 -859
- data/po/uk.po +925 -846
- data/po/zh_TW.po +926 -841
- data/schemas/alexandria.schemas +1 -1
- data/share/alexandria/glade/main_app__builder.glade +6 -21
- data/share/gnome/help/alexandria/C/adding-books.xml +3 -4
- data/share/gnome/help/alexandria/C/introduction.xml +0 -16
- data/share/gnome/help/alexandria/C/searching.xml +1 -4
- data/share/gnome/help/alexandria/C/settings.xml +0 -30
- data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
- data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
- data/share/gnome/help/alexandria/fr/alexandria.xml +5 -160
- data/share/gnome/help/alexandria/ja/adding-books.xml +1 -1
- data/share/gnome/help/alexandria/ja/introduction.xml +0 -15
- data/share/gnome/help/alexandria/ja/searching.xml +3 -7
- data/share/gnome/help/alexandria/ja/settings.xml +0 -27
- data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
- data/spec/alexandria/book_providers/bl_provider_spec.rb +13 -0
- data/spec/alexandria/book_providers/loc_provider_spec.rb +17 -0
- data/spec/alexandria/book_providers/sbn_provider_spec.rb +13 -0
- data/spec/alexandria/book_providers/thalia_provider_spec.rb +119 -0
- data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
- data/spec/alexandria/book_providers_spec.rb +0 -154
- data/spec/alexandria/console_spec.rb +0 -5
- data/spec/alexandria/export_library_spec.rb +27 -38
- data/spec/alexandria/library_spec.rb +76 -46
- data/spec/alexandria/preferences_spec.rb +29 -3
- data/spec/alexandria/scanners/cue_cat_spec.rb +1 -1
- data/spec/alexandria/ui/about_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/acquire_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/alert_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/book_properties_dialog_spec.rb +47 -5
- data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/error_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/export_dialog_spec.rb +25 -4
- data/spec/alexandria/ui/icons_spec.rb +26 -0
- data/spec/alexandria/ui/iconview_spec.rb +1 -1
- data/spec/alexandria/ui/import_dialog_spec.rb +35 -3
- data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/main_app_spec.rb +1 -1
- data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +39 -3
- data/spec/alexandria/ui/new_provider_dialog_spec.rb +19 -3
- data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +28 -3
- data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
- data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +23 -8
- data/spec/alexandria/ui/really_delete_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
- data/spec/alexandria/ui/skip_entry_dialog_spec.rb +1 -1
- data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +37 -6
- data/spec/alexandria/ui/ui_manager_spec.rb +116 -2
- data/spec/data/libraries/0.6.2/My Library/9780571147168.yaml +2 -0
- data/spec/end_to_end/basic_run_spec.rb +3 -8
- data/spec/fixtures/cover.jpg +0 -0
- data/spec/spec_helper.rb +47 -3
- data/tasks/spec.rake +3 -5
- data/util/rake/fileinstall.rb +16 -15
- data/util/rake/omfgenerate.rb +1 -1
- metadata +141 -52
- data/.travis.yml +0 -39
- data/lib/alexandria/book_providers/adlibris.rb +0 -196
- data/lib/alexandria/book_providers/amazon_aws.rb +0 -252
- data/lib/alexandria/book_providers/amazon_ecs_util.rb +0 -388
- data/lib/alexandria/book_providers/barnes_and_noble.rb +0 -209
- data/lib/alexandria/book_providers/proxis.rb +0 -175
- data/lib/alexandria/book_providers/siciliano.rb +0 -257
- data/lib/alexandria/book_providers/z3950.rb +0 -415
- data/spec/alexandria/ui/ui_utilities_spec.rb +0 -62
- data/spec/alexandria/utilities_spec.rb +0 -52
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This file is part of Alexandria.
|
4
|
+
#
|
5
|
+
# See the file README.md for authorship and licensing information.
|
6
|
+
|
7
|
+
module Alexandria
|
8
|
+
module UI
|
9
|
+
class SmartLibraryRuleBox
|
10
|
+
attr_accessor :rule_box,
|
11
|
+
:left_operand_combo, :operator_combo,
|
12
|
+
:value_entry, :date_entry, :entry_label,
|
13
|
+
:add_button, :remove_button
|
14
|
+
|
15
|
+
def initialize(parent)
|
16
|
+
@parent = parent
|
17
|
+
|
18
|
+
self.rule_box = Gtk::Box.new :horizontal
|
19
|
+
rule_box.spacing = 8
|
20
|
+
|
21
|
+
self.left_operand_combo = Gtk::ComboBoxText.new
|
22
|
+
self.operator_combo = Gtk::ComboBoxText.new
|
23
|
+
|
24
|
+
self.value_entry = Gtk::Entry.new
|
25
|
+
|
26
|
+
self.date_entry = Gtk::Entry.new.tap do |entry|
|
27
|
+
entry.primary_icon_name = Gtk::Stock::EDIT
|
28
|
+
|
29
|
+
entry.primary_icon_activatable = true
|
30
|
+
entry.signal_connect("icon-press") do |widget, primary, icon|
|
31
|
+
@parent.handle_date_icon_press(widget, primary, icon)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
self.entry_label = Gtk::Label.new("")
|
36
|
+
|
37
|
+
self.add_button = Gtk::Button.new(label: "").tap do |widget|
|
38
|
+
widget.remove(widget.children.first)
|
39
|
+
widget << Gtk::Image.new(stock: Gtk::Stock::ADD,
|
40
|
+
size: Gtk::IconSize::BUTTON)
|
41
|
+
|
42
|
+
widget.signal_connect("clicked") { @parent.handle_add_rule_clicked }
|
43
|
+
end
|
44
|
+
|
45
|
+
self.remove_button = Gtk::Button.new(label: "")
|
46
|
+
remove_button.remove(remove_button.children.first)
|
47
|
+
remove_button << Gtk::Image.new(stock: Gtk::Stock::REMOVE,
|
48
|
+
size: Gtk::IconSize::BUTTON)
|
49
|
+
|
50
|
+
remove_button.signal_connect("clicked") do |_button|
|
51
|
+
@parent.handle_remove_rule_clicked(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
operands.each do |operand|
|
55
|
+
left_operand_combo.append_text(operand.name)
|
56
|
+
end
|
57
|
+
|
58
|
+
operator_combo.signal_connect("changed") do
|
59
|
+
handle_operator_changed
|
60
|
+
end
|
61
|
+
|
62
|
+
left_operand_combo.signal_connect("changed") do
|
63
|
+
handle_left_operand_changed
|
64
|
+
end
|
65
|
+
|
66
|
+
rule_box.pack_start(left_operand_combo, expand: false, fill: false)
|
67
|
+
rule_box.pack_start(operator_combo, expand: false, fill: false)
|
68
|
+
rule_box.pack_start(value_entry)
|
69
|
+
rule_box.pack_start(date_entry)
|
70
|
+
rule_box.pack_start(entry_label, expand: false, fill: false)
|
71
|
+
rule_box.pack_end(remove_button, expand: false, fill: false)
|
72
|
+
rule_box.pack_end(add_button, expand: false, fill: false)
|
73
|
+
|
74
|
+
value_entry.visible = date_entry.visible = entry_label.visible = false
|
75
|
+
end
|
76
|
+
|
77
|
+
def operands
|
78
|
+
SmartLibrary::Rule::Operands::LEFT
|
79
|
+
end
|
80
|
+
|
81
|
+
def handle_operator_changed
|
82
|
+
operand = operands[left_operand_combo.active]
|
83
|
+
operations = SmartLibrary::Rule.operations_for_operand(operand)
|
84
|
+
operation = operations[operator_combo.active]
|
85
|
+
|
86
|
+
value_entry.visible = date_entry.visible = entry_label.visible = false
|
87
|
+
right_operand = operation.last
|
88
|
+
unless right_operand.nil?
|
89
|
+
entry = case right_operand.klass.name
|
90
|
+
when "Time"
|
91
|
+
date_entry
|
92
|
+
else
|
93
|
+
value_entry
|
94
|
+
end
|
95
|
+
entry.visible = true
|
96
|
+
unless right_operand.name.nil?
|
97
|
+
entry_label.text = right_operand.name
|
98
|
+
entry_label.visible = true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
@parent.apply_smart_rule_for_rule_box(rule_box, operand, operation)
|
103
|
+
end
|
104
|
+
|
105
|
+
def handle_left_operand_changed
|
106
|
+
operand = operands[left_operand_combo.active]
|
107
|
+
operator_combo.freeze_notify do
|
108
|
+
operator_combo.remove_all
|
109
|
+
operations = SmartLibrary::Rule.operations_for_operand(operand)
|
110
|
+
operations.each do |operation|
|
111
|
+
operator = operation.first
|
112
|
+
operator_combo.append_text(operator.name)
|
113
|
+
end
|
114
|
+
operator_combo.active = 0
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/alexandria/ui/sound.rb
CHANGED
@@ -39,9 +39,9 @@ module Alexandria
|
|
39
39
|
def play(effect)
|
40
40
|
file = File.join(@sounds_dir, "#{effect}.ogg")
|
41
41
|
if @playing
|
42
|
-
|
42
|
+
log.debug { "Already playing #{effect}." }
|
43
43
|
else
|
44
|
-
|
44
|
+
log.debug { "Not playing. Starting #{effect}." }
|
45
45
|
@filesrc.location = file
|
46
46
|
start_playback
|
47
47
|
end
|
@@ -76,10 +76,8 @@ module Alexandria
|
|
76
76
|
when Gst::MessageType::EOS
|
77
77
|
stop_playback
|
78
78
|
when Gst::MessageType::ERROR
|
79
|
-
|
80
|
-
|
81
|
-
p message.parse
|
82
|
-
end
|
79
|
+
log.debug { "ERROR loop.quit" }
|
80
|
+
log.debug { message.parse.inspect }
|
83
81
|
stop_playback
|
84
82
|
end
|
85
83
|
true
|
@@ -15,6 +15,7 @@ module Alexandria
|
|
15
15
|
attr_accessor :main_app, :actiongroup, :appbar, :prefs, :listview, :iconview,
|
16
16
|
:listview_model, :iconview_model, :filtered_model
|
17
17
|
attr_reader :model
|
18
|
+
|
18
19
|
include Logging
|
19
20
|
include GetText
|
20
21
|
GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
|
@@ -74,7 +75,7 @@ module Alexandria
|
|
74
75
|
@iconview_model = Gtk::TreeModelSort.new(@filtered_model)
|
75
76
|
@listview_manager = ListViewManager.new @listview, self
|
76
77
|
@iconview_manager = IconViewManager.new @iconview, self
|
77
|
-
@sidepane_manager =
|
78
|
+
@sidepane_manager = SidepaneManager.new @library_listview, self
|
78
79
|
@library_listview = @sidepane_manager.library_listview
|
79
80
|
@listview_manager.setup_listview_columns_visibility
|
80
81
|
@listview_manager.setup_listview_columns_width
|
@@ -122,7 +123,9 @@ module Alexandria
|
|
122
123
|
|
123
124
|
def setup_toolbar_filter_entry
|
124
125
|
@filter_entry = Gtk::Entry.new
|
125
|
-
@filter_entry.signal_connect("changed"
|
126
|
+
@filter_entry.signal_connect("changed") do |entry|
|
127
|
+
on_toolbar_filter_entry_changed(entry)
|
128
|
+
end
|
126
129
|
@toolitem = Gtk::ToolItem.new
|
127
130
|
@toolitem.expand = true
|
128
131
|
@toolitem.border_width = 5
|
@@ -148,7 +151,7 @@ module Alexandria
|
|
148
151
|
cb.append_text(item)
|
149
152
|
end
|
150
153
|
cb.active = 0
|
151
|
-
cb.signal_connect("changed"
|
154
|
+
cb.signal_connect("changed") { |combo| on_criterion_combobox_changed(combo) }
|
152
155
|
|
153
156
|
# Put the combo box in a event box because it is not currently
|
154
157
|
# possible assign a tooltip to a combo box.
|
@@ -166,8 +169,9 @@ module Alexandria
|
|
166
169
|
@toolbar_view_as.append_text(_("View as Icons"))
|
167
170
|
@toolbar_view_as.append_text(_("View as List"))
|
168
171
|
@toolbar_view_as.active = 0
|
169
|
-
@toolbar_view_as_signal_hid =
|
170
|
-
|
172
|
+
@toolbar_view_as_signal_hid = @toolbar_view_as.signal_connect("changed") do |combo|
|
173
|
+
on_toolbar_view_as_changed(combo)
|
174
|
+
end
|
171
175
|
|
172
176
|
# Put the combo box in a event box because it is not currently
|
173
177
|
# possible assign a tooltip to a combo box.
|
@@ -183,15 +187,16 @@ module Alexandria
|
|
183
187
|
def setup_book_providers
|
184
188
|
log.debug { "setup_book_providers" }
|
185
189
|
mid = @uimanager.new_merge_id
|
186
|
-
|
190
|
+
ui_paths = ["ui/MainMenubar/ViewMenu/OnlineInformation/",
|
191
|
+
"ui/BookPopup/OnlineInformation/",
|
192
|
+
"ui/NoBookPopup/OnlineInformation/"]
|
193
|
+
BookProviders.list.each do |provider|
|
187
194
|
name = provider.action_name
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
:menuitem, false)
|
194
|
-
end
|
195
|
+
ui_paths.each do |path|
|
196
|
+
log.debug { "Adding #{name} to #{path}" }
|
197
|
+
@uimanager.add_ui(mid, path, name, name,
|
198
|
+
:menuitem, false)
|
199
|
+
end
|
195
200
|
end
|
196
201
|
end
|
197
202
|
|
@@ -224,8 +229,12 @@ module Alexandria
|
|
224
229
|
|
225
230
|
def setup_window_events
|
226
231
|
log.debug { "setup_window_events" }
|
227
|
-
@main_app.signal_connect("window-state-event",
|
228
|
-
|
232
|
+
@main_app.signal_connect("window-state-event") do |window, event|
|
233
|
+
on_window_state_event(window, event)
|
234
|
+
end
|
235
|
+
@main_app.signal_connect("destroy") do |window|
|
236
|
+
on_window_destroy(window)
|
237
|
+
end
|
229
238
|
end
|
230
239
|
|
231
240
|
def setup_active_model
|
@@ -341,7 +350,7 @@ module Alexandria
|
|
341
350
|
sensitize_library selected_library if library_already_selected
|
342
351
|
|
343
352
|
GLib::Idle.add do
|
344
|
-
menu.
|
353
|
+
menu.popup_at_pointer(event)
|
345
354
|
false
|
346
355
|
end
|
347
356
|
|
@@ -371,25 +380,25 @@ module Alexandria
|
|
371
380
|
|
372
381
|
def on_books_button_press_event(widget, event)
|
373
382
|
log.debug { "books_button_press_event" }
|
374
|
-
|
375
|
-
widget.grab_focus
|
383
|
+
event_is_right_click event or return
|
376
384
|
|
377
|
-
|
378
|
-
obj, path =
|
379
|
-
widget.is_a?(Gtk::TreeView) ? [widget.selection, path.first] : [widget, path]
|
385
|
+
widget.grab_focus
|
380
386
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
+
if (path = widget.get_path_at_pos(event.x.to_i, event.y.to_i))
|
388
|
+
obj, path =
|
389
|
+
widget.is_a?(Gtk::TreeView) ? [widget.selection, path.first] : [widget, path]
|
390
|
+
|
391
|
+
unless obj.path_is_selected?(path)
|
392
|
+
log.debug { "Select #{path}" }
|
387
393
|
widget.unselect_all
|
394
|
+
obj.select_path(path)
|
388
395
|
end
|
389
|
-
|
390
|
-
|
391
|
-
menu.popup(nil, nil, event.button, event.time)
|
396
|
+
else
|
397
|
+
widget.unselect_all
|
392
398
|
end
|
399
|
+
|
400
|
+
menu = selected_books.empty? ? @nobook_popup : @book_popup
|
401
|
+
menu.popup_at_pointer(event)
|
393
402
|
end
|
394
403
|
|
395
404
|
def get_library_selection_text(library)
|
@@ -409,7 +418,7 @@ module Alexandria
|
|
409
418
|
library.length), library.name, library.length)
|
410
419
|
else
|
411
420
|
format(n_("Library '%s' selected, %d book, " \
|
412
|
-
|
421
|
+
"%d unrated",
|
413
422
|
"Library '%s' selected, %d books, " \
|
414
423
|
"%d unrated",
|
415
424
|
library.length), library.name, library.length, n_unrated)
|
@@ -446,7 +455,7 @@ module Alexandria
|
|
446
455
|
log.debug { "#{@library_listview} : #{@library_popup} : #{@listview}" }
|
447
456
|
log.debug do
|
448
457
|
"@library_listview: #{@library_listview.has_focus?} " \
|
449
|
-
|
458
|
+
"or @library_popup:#{@library_popup.has_focus?}"
|
450
459
|
end
|
451
460
|
log.debug { "@library_listview does *NOT* have focus" }
|
452
461
|
log.debug { "Books are empty: #{books.empty?}" }
|
@@ -475,7 +484,7 @@ module Alexandria
|
|
475
484
|
b = books.first
|
476
485
|
# FIXME: Clean up endless negation in this logic
|
477
486
|
no_urls = true
|
478
|
-
BookProviders.each do |provider|
|
487
|
+
BookProviders.list.each do |provider|
|
479
488
|
has_no_url = true
|
480
489
|
begin
|
481
490
|
has_no_url = (b.isbn.nil? || b.isbn.strip.empty? || provider.url(b).nil?)
|
@@ -523,42 +532,21 @@ module Alexandria
|
|
523
532
|
end
|
524
533
|
|
525
534
|
def select_a_book(book)
|
526
|
-
|
527
|
-
|
528
|
-
iter = iter_from_book bk
|
529
|
-
next unless iter
|
530
|
-
|
531
|
-
path = iter.path
|
532
|
-
next unless view.model
|
533
|
-
|
534
|
-
path = view_path_to_model_path(view, path)
|
535
|
-
log.debug { "Path for #{bk.ident} is #{path}" }
|
536
|
-
selection = view.respond_to?(:selection) ? @listview.selection : @iconview
|
537
|
-
selection.unselect_all
|
538
|
-
selection.select_path(path)
|
539
|
-
end
|
540
|
-
begin
|
541
|
-
log.debug { "select_a_book: listview" }
|
542
|
-
select_this_book.call(book, @listview)
|
543
|
-
log.debug { "select_a_book: listview" }
|
544
|
-
select_this_book.call(book, @iconview)
|
545
|
-
rescue StandardError => ex
|
546
|
-
trace = ex.backtrace.join("\n> ")
|
547
|
-
log.warn { "Failed to automatically select book: #{ex.message} #{trace}" }
|
548
|
-
end
|
549
|
-
# TODO: Figure out why this frequently selects the wrong book!
|
535
|
+
select_book_in_view(book, @listview)
|
536
|
+
select_book_in_view(book, @iconview)
|
550
537
|
end
|
551
538
|
|
552
539
|
def update(*ary)
|
553
540
|
log.debug { "on_update #{ary}" }
|
554
541
|
caller = ary.first
|
555
|
-
|
542
|
+
case caller
|
543
|
+
when UndoManager
|
556
544
|
@actiongroup["Undo"].sensitive = caller.can_undo?
|
557
545
|
@actiongroup["Redo"].sensitive = caller.can_redo?
|
558
|
-
|
546
|
+
when Library
|
559
547
|
handle_update_caller_library ary unless caller.updating?
|
560
548
|
else
|
561
|
-
raise "unrecognized update event"
|
549
|
+
raise _("unrecognized update event")
|
562
550
|
end
|
563
551
|
end
|
564
552
|
|
@@ -584,8 +572,6 @@ module Alexandria
|
|
584
572
|
end
|
585
573
|
end
|
586
574
|
|
587
|
-
# private
|
588
|
-
|
589
575
|
def open_web_browser(url)
|
590
576
|
if url.nil?
|
591
577
|
log.warn("Attempt to open browser with nil url")
|
@@ -605,7 +591,7 @@ module Alexandria
|
|
605
591
|
end
|
606
592
|
|
607
593
|
def load_libraries
|
608
|
-
log.info { "Loading libraries..." }
|
594
|
+
log.info { _("Loading libraries...") }
|
609
595
|
@completion_models = CompletionModels.instance
|
610
596
|
if @libraries
|
611
597
|
detach_old_libraries
|
@@ -669,7 +655,7 @@ module Alexandria
|
|
669
655
|
|
670
656
|
log.debug do
|
671
657
|
"Trying to add #{book.title}, #{cover_uri}" \
|
672
|
-
|
658
|
+
" in library ''#{library.name}'"
|
673
659
|
end
|
674
660
|
library.save_cover(book, cover_uri) unless cover_uri.nil?
|
675
661
|
library << book
|
@@ -750,7 +736,7 @@ module Alexandria
|
|
750
736
|
new_height = [ICON_HEIGHT, icon.height].min
|
751
737
|
icon = cache_scaled_icon(icon, new_width, new_height)
|
752
738
|
end
|
753
|
-
icon =
|
739
|
+
icon = Icons.tag_icon(icon, Icons::FAVORITE_TAG) if rating == Book::MAX_RATING_STARS
|
754
740
|
iter[Columns::COVER_ICON] = icon
|
755
741
|
log.debug { "Full iter: " + (0..15).map { |num| iter[num].inspect }.join(", ") }
|
756
742
|
end
|
@@ -889,9 +875,8 @@ module Alexandria
|
|
889
875
|
end
|
890
876
|
|
891
877
|
def iter_from_ident(ident)
|
892
|
-
log.debug { ident.to_s }
|
893
878
|
iter = @model.iter_first
|
894
|
-
ok = true
|
879
|
+
ok = true if iter
|
895
880
|
while ok
|
896
881
|
return iter if iter[Columns::IDENT] == ident
|
897
882
|
|
@@ -901,7 +886,6 @@ module Alexandria
|
|
901
886
|
end
|
902
887
|
|
903
888
|
def iter_from_book(book)
|
904
|
-
log.debug { book.to_s }
|
905
889
|
iter_from_ident(book.ident)
|
906
890
|
end
|
907
891
|
|
@@ -971,7 +955,7 @@ module Alexandria
|
|
971
955
|
end
|
972
956
|
|
973
957
|
def restore_preferences
|
974
|
-
log.debug { "Restoring preferences
|
958
|
+
log.debug { "Restoring preferences" }
|
975
959
|
if @prefs.maximized
|
976
960
|
@main_app.maximize
|
977
961
|
else
|
@@ -1045,7 +1029,7 @@ module Alexandria
|
|
1045
1029
|
|
1046
1030
|
def setup_move_actions
|
1047
1031
|
@actiongroup.actions.each do |action|
|
1048
|
-
next unless
|
1032
|
+
next unless action.name.start_with?("MoveIn")
|
1049
1033
|
|
1050
1034
|
@actiongroup.remove_action(action)
|
1051
1035
|
end
|
@@ -1060,10 +1044,11 @@ module Alexandria
|
|
1060
1044
|
@actiongroup.add_actions(actions)
|
1061
1045
|
@uimanager.remove_ui(@move_mid) if @move_mid
|
1062
1046
|
@move_mid = @uimanager.new_merge_id
|
1047
|
+
ui_paths = ["ui/MainMenubar/EditMenu/Move/",
|
1048
|
+
"ui/BookPopup/Move/"]
|
1063
1049
|
@libraries.all_regular_libraries.each do |library|
|
1064
1050
|
name = library.action_name
|
1065
|
-
|
1066
|
-
"ui/BookPopup/Move/"].each do |path|
|
1051
|
+
ui_paths.each do |path|
|
1067
1052
|
@uimanager.add_ui(@move_mid, path, name, name,
|
1068
1053
|
:menuitem, false)
|
1069
1054
|
end
|
@@ -1084,7 +1069,7 @@ module Alexandria
|
|
1084
1069
|
# added by Cathal Mc Ginley, 23 Oct 2007
|
1085
1070
|
log.debug do
|
1086
1071
|
"library_sort_order #{@notebook.page}: " \
|
1087
|
-
|
1072
|
+
"#{@iconview.model.inspect} #{@listview.model.inspect}"
|
1088
1073
|
end
|
1089
1074
|
result, sort_column, sort_order = current_view.model.sort_column_id
|
1090
1075
|
if result
|
@@ -1110,10 +1095,10 @@ module Alexandria
|
|
1110
1095
|
def get_previous_selected_library(library)
|
1111
1096
|
log.debug { "get_previous_selected_library: #{library}" }
|
1112
1097
|
@previous_selected_library = selected_library
|
1113
|
-
if @previous_selected_library
|
1114
|
-
select_library(library)
|
1115
|
-
else
|
1098
|
+
if @previous_selected_library == library
|
1116
1099
|
@previous_selected_library = nil
|
1100
|
+
else
|
1101
|
+
select_library(library)
|
1117
1102
|
end
|
1118
1103
|
end
|
1119
1104
|
|
@@ -1147,10 +1132,10 @@ module Alexandria
|
|
1147
1132
|
end
|
1148
1133
|
|
1149
1134
|
def remove_library_separator
|
1150
|
-
if
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1135
|
+
return if @library_separator_iter.nil? || @libraries.all_smart_libraries.any?
|
1136
|
+
|
1137
|
+
@library_listview.model.remove(@library_separator_iter)
|
1138
|
+
@library_separator_iter = nil
|
1154
1139
|
end
|
1155
1140
|
|
1156
1141
|
def undoable_undelete(library, books = nil)
|
@@ -1190,9 +1175,21 @@ module Alexandria
|
|
1190
1175
|
|
1191
1176
|
private
|
1192
1177
|
|
1193
|
-
def
|
1194
|
-
|
1195
|
-
|
1178
|
+
def select_book_in_view(book, view)
|
1179
|
+
return unless view.model
|
1180
|
+
|
1181
|
+
@filtered_model.refilter
|
1182
|
+
iter = iter_from_book(book) or return
|
1183
|
+
path = iter.path
|
1184
|
+
path = view_path_to_model_path(view, path)
|
1185
|
+
selection = view.respond_to?(:selection) ? view.selection : view
|
1186
|
+
selection.unselect_all
|
1187
|
+
selection.select_path(path) if path
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def view_path_to_model_path(view, view_path)
|
1191
|
+
filter_path = view.model.convert_path_to_child_path(view_path)
|
1192
|
+
@filtered_model.convert_path_to_child_path(filter_path) if filter_path
|
1196
1193
|
end
|
1197
1194
|
end
|
1198
1195
|
end
|
data/lib/alexandria/ui.rb
CHANGED
@@ -31,21 +31,21 @@ module Alexandria
|
|
31
31
|
module UI
|
32
32
|
include Logging
|
33
33
|
def self.init_icons
|
34
|
-
log.info { "Initializing Icons
|
34
|
+
log.info { "Initializing Icons" }
|
35
35
|
Icons.init
|
36
36
|
end
|
37
37
|
|
38
38
|
def self.start_main_app
|
39
|
-
|
40
|
-
log.info { "Starting MainApp
|
41
|
-
|
39
|
+
log.debug { "==========================" }
|
40
|
+
log.info { "Starting MainApp" }
|
41
|
+
log.debug { "==========================" }
|
42
42
|
MainApp.instance
|
43
43
|
end
|
44
44
|
|
45
45
|
def self.start_gtk
|
46
|
-
|
47
|
-
log.info { "Starting Gtk
|
48
|
-
|
46
|
+
log.debug { "====================================" }
|
47
|
+
log.info { "Starting Gtk" }
|
48
|
+
log.debug { "====================================" }
|
49
49
|
Gtk.main
|
50
50
|
end
|
51
51
|
|
data/lib/alexandria/version.rb
CHANGED
@@ -22,6 +22,17 @@ module Alexandria
|
|
22
22
|
class WebTheme
|
23
23
|
attr_reader :name, :css_file, :preview_file, :pixmaps_directory
|
24
24
|
|
25
|
+
def initialize(css_file, preview_file, pixmaps_directory)
|
26
|
+
@name = File.basename(css_file, ".css").capitalize
|
27
|
+
@css_file = css_file
|
28
|
+
@preview_file = preview_file
|
29
|
+
@pixmaps_directory = pixmaps_directory
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_pixmaps?
|
33
|
+
File.exist?(@pixmaps_directory)
|
34
|
+
end
|
35
|
+
|
25
36
|
def self.all
|
26
37
|
themes_dir = [
|
27
38
|
# System dir
|
@@ -33,18 +44,12 @@ module Alexandria
|
|
33
44
|
themes_dir.map { |x| load(x) }.flatten
|
34
45
|
end
|
35
46
|
|
36
|
-
def has_pixmaps?
|
37
|
-
File.exist?(@pixmaps_directory)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
47
|
def self.load(themes_dir)
|
43
48
|
themes = []
|
44
49
|
if File.exist?(themes_dir)
|
45
50
|
Dir.entries(themes_dir).each do |file|
|
46
51
|
# ignore hidden files
|
47
|
-
next if
|
52
|
+
next if file.start_with?(".")
|
48
53
|
|
49
54
|
# ignore non-directories
|
50
55
|
path = File.join(themes_dir, file)
|
@@ -55,7 +60,9 @@ module Alexandria
|
|
55
60
|
css_file = File.join(path, file + ".css")
|
56
61
|
preview_file = File.join(path, "preview.jpg")
|
57
62
|
[css_file, preview_file].each do |helper_file|
|
58
|
-
|
63
|
+
unless File.exist?(helper_file)
|
64
|
+
raise format(_("File %<file>s not found"), file: helper_file)
|
65
|
+
end
|
59
66
|
end
|
60
67
|
themes << WebTheme.new(css_file, preview_file,
|
61
68
|
File.join(path, file, "pixmaps"))
|
@@ -65,12 +72,5 @@ module Alexandria
|
|
65
72
|
end
|
66
73
|
themes
|
67
74
|
end
|
68
|
-
|
69
|
-
def initialize(css_file, preview_file, pixmaps_directory)
|
70
|
-
@name = File.basename(css_file, ".css").capitalize
|
71
|
-
@css_file = css_file
|
72
|
-
@preview_file = preview_file
|
73
|
-
@pixmaps_directory = pixmaps_directory
|
74
|
-
end
|
75
75
|
end
|
76
76
|
end
|
data/lib/alexandria.rb
CHANGED
@@ -28,8 +28,8 @@ module Alexandria
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.set_log_level
|
31
|
-
|
32
|
-
|
31
|
+
log.level = Logger::DEBUG if $DEBUG
|
32
|
+
log.debug { "Initializing Alexandria" }
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.main
|