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.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.github/workflows/ruby.yml +72 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +65 -30
  6. data/.rubocop_todo.yml +49 -165
  7. data/.simplecov +5 -2
  8. data/CHANGELOG.md +64 -0
  9. data/ChangeLog.0 +19 -19
  10. data/INSTALL.md +26 -16
  11. data/README.md +31 -35
  12. data/Rakefile +18 -16
  13. data/alexandria-book-collection-manager.gemspec +35 -29
  14. data/doc/FAQ +2 -2
  15. data/doc/dependency_decisions.yml +22 -3
  16. data/lib/alexandria/about.rb +1 -1
  17. data/lib/alexandria/book_providers/bl_provider.rb +88 -0
  18. data/lib/alexandria/book_providers/douban.rb +2 -2
  19. data/lib/alexandria/book_providers/loc_provider.rb +38 -0
  20. data/lib/alexandria/book_providers/pseudomarc.rb +61 -71
  21. data/lib/alexandria/book_providers/sbn_provider.rb +108 -0
  22. data/lib/alexandria/book_providers/{thalia.rb → thalia_provider.rb} +37 -74
  23. data/lib/alexandria/book_providers/web.rb +2 -2
  24. data/lib/alexandria/book_providers/worldcat.rb +34 -38
  25. data/lib/alexandria/book_providers/z3950_provider.rb +199 -0
  26. data/lib/alexandria/book_providers.rb +48 -65
  27. data/lib/alexandria/default_preferences.rb +2 -1
  28. data/lib/alexandria/execution_queue.rb +13 -12
  29. data/lib/alexandria/export_library.rb +21 -22
  30. data/lib/alexandria/image_fetcher.rb +25 -0
  31. data/lib/alexandria/import_library.rb +46 -70
  32. data/lib/alexandria/import_library_csv.rb +16 -16
  33. data/lib/alexandria/library_sort_order.rb +3 -1
  34. data/lib/alexandria/library_store.rb +19 -20
  35. data/lib/alexandria/logging.rb +5 -9
  36. data/lib/alexandria/models/book.rb +15 -2
  37. data/lib/alexandria/models/library.rb +31 -35
  38. data/lib/alexandria/net.rb +1 -2
  39. data/lib/alexandria/preferences.rb +27 -33
  40. data/lib/alexandria/scanners/cue_cat.rb +6 -6
  41. data/lib/alexandria/scanners/keyboard.rb +1 -1
  42. data/lib/alexandria/scanners.rb +2 -2
  43. data/lib/alexandria/smart_library.rb +22 -26
  44. data/lib/alexandria/ui/about_dialog.rb +1 -1
  45. data/lib/alexandria/ui/acquire_dialog.rb +15 -19
  46. data/lib/alexandria/ui/alert_dialog.rb +36 -19
  47. data/lib/alexandria/ui/bad_isbns_dialog.rb +13 -9
  48. data/lib/alexandria/ui/barcode_animation.rb +6 -6
  49. data/lib/alexandria/ui/book_properties_dialog.rb +2 -3
  50. data/lib/alexandria/ui/book_properties_dialog_base.rb +35 -137
  51. data/lib/alexandria/ui/calendar_popup.rb +58 -0
  52. data/lib/alexandria/ui/callbacks.rb +144 -123
  53. data/lib/alexandria/ui/completion_models.rb +2 -6
  54. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -1
  55. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +2 -2
  56. data/lib/alexandria/ui/error_dialog.rb +1 -1
  57. data/lib/alexandria/ui/export_dialog.rb +19 -18
  58. data/lib/alexandria/ui/icons.rb +34 -40
  59. data/lib/alexandria/ui/iconview_tooltips.rb +40 -53
  60. data/lib/alexandria/ui/import_dialog.rb +49 -48
  61. data/lib/alexandria/ui/init.rb +14 -12
  62. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +2 -2
  63. data/lib/alexandria/ui/libraries_combo.rb +10 -9
  64. data/lib/alexandria/ui/listview.rb +6 -7
  65. data/lib/alexandria/ui/main_app.rb +2 -2
  66. data/lib/alexandria/ui/multi_drag_treeview.rb +5 -7
  67. data/lib/alexandria/ui/new_book_dialog.rb +63 -65
  68. data/lib/alexandria/ui/new_book_dialog_manual.rb +1 -1
  69. data/lib/alexandria/ui/new_provider_dialog.rb +12 -11
  70. data/lib/alexandria/ui/new_smart_library_dialog.rb +39 -27
  71. data/lib/alexandria/ui/preferences_dialog.rb +25 -84
  72. data/lib/alexandria/ui/provider_preferences_base_dialog.rb +10 -6
  73. data/lib/alexandria/ui/provider_preferences_dialog.rb +5 -5
  74. data/lib/alexandria/ui/really_delete_dialog.rb +2 -2
  75. data/lib/alexandria/ui/sidepane_manager.rb +38 -38
  76. data/lib/alexandria/ui/skip_entry_dialog.rb +3 -2
  77. data/lib/alexandria/ui/smart_library_properties_dialog.rb +35 -36
  78. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +61 -244
  79. data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
  80. data/lib/alexandria/ui/sound.rb +4 -6
  81. data/lib/alexandria/ui/ui_manager.rb +80 -83
  82. data/lib/alexandria/ui.rb +7 -7
  83. data/lib/alexandria/version.rb +2 -2
  84. data/lib/alexandria/web_themes.rb +15 -15
  85. data/lib/alexandria.rb +2 -2
  86. data/po/cs.po +947 -865
  87. data/po/cy.po +913 -864
  88. data/po/de.po +961 -865
  89. data/po/el.po +956 -861
  90. data/po/es.po +952 -857
  91. data/po/fr.po +950 -865
  92. data/po/ga.po +866 -819
  93. data/po/gl.po +946 -861
  94. data/po/it.po +945 -858
  95. data/po/ja.po +921 -836
  96. data/po/mk.po +953 -858
  97. data/po/nb.po +932 -847
  98. data/po/nl.po +955 -849
  99. data/po/pl.po +999 -963
  100. data/po/pt.po +946 -850
  101. data/po/pt_BR.po +944 -859
  102. data/po/ru.po +959 -868
  103. data/po/sk.po +950 -863
  104. data/po/sv.po +944 -859
  105. data/po/uk.po +925 -846
  106. data/po/zh_TW.po +926 -841
  107. data/schemas/alexandria.schemas +1 -1
  108. data/share/alexandria/glade/main_app__builder.glade +6 -21
  109. data/share/gnome/help/alexandria/C/adding-books.xml +3 -4
  110. data/share/gnome/help/alexandria/C/introduction.xml +0 -16
  111. data/share/gnome/help/alexandria/C/searching.xml +1 -4
  112. data/share/gnome/help/alexandria/C/settings.xml +0 -30
  113. data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
  114. data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
  115. data/share/gnome/help/alexandria/fr/alexandria.xml +5 -160
  116. data/share/gnome/help/alexandria/ja/adding-books.xml +1 -1
  117. data/share/gnome/help/alexandria/ja/introduction.xml +0 -15
  118. data/share/gnome/help/alexandria/ja/searching.xml +3 -7
  119. data/share/gnome/help/alexandria/ja/settings.xml +0 -27
  120. data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
  121. data/spec/alexandria/book_providers/bl_provider_spec.rb +13 -0
  122. data/spec/alexandria/book_providers/loc_provider_spec.rb +17 -0
  123. data/spec/alexandria/book_providers/sbn_provider_spec.rb +13 -0
  124. data/spec/alexandria/book_providers/thalia_provider_spec.rb +119 -0
  125. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
  126. data/spec/alexandria/book_providers_spec.rb +0 -154
  127. data/spec/alexandria/console_spec.rb +0 -5
  128. data/spec/alexandria/export_library_spec.rb +27 -38
  129. data/spec/alexandria/library_spec.rb +76 -46
  130. data/spec/alexandria/preferences_spec.rb +29 -3
  131. data/spec/alexandria/scanners/cue_cat_spec.rb +1 -1
  132. data/spec/alexandria/ui/about_dialog_spec.rb +1 -1
  133. data/spec/alexandria/ui/acquire_dialog_spec.rb +1 -1
  134. data/spec/alexandria/ui/alert_dialog_spec.rb +1 -1
  135. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +1 -1
  136. data/spec/alexandria/ui/book_properties_dialog_spec.rb +47 -5
  137. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +1 -1
  138. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +1 -1
  139. data/spec/alexandria/ui/error_dialog_spec.rb +1 -1
  140. data/spec/alexandria/ui/export_dialog_spec.rb +25 -4
  141. data/spec/alexandria/ui/icons_spec.rb +26 -0
  142. data/spec/alexandria/ui/iconview_spec.rb +1 -1
  143. data/spec/alexandria/ui/import_dialog_spec.rb +35 -3
  144. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +1 -1
  145. data/spec/alexandria/ui/main_app_spec.rb +1 -1
  146. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +39 -3
  147. data/spec/alexandria/ui/new_provider_dialog_spec.rb +19 -3
  148. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +28 -3
  149. data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
  150. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +23 -8
  151. data/spec/alexandria/ui/really_delete_dialog_spec.rb +1 -1
  152. data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
  153. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +1 -1
  154. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +37 -6
  155. data/spec/alexandria/ui/ui_manager_spec.rb +116 -2
  156. data/spec/data/libraries/0.6.2/My Library/9780571147168.yaml +2 -0
  157. data/spec/end_to_end/basic_run_spec.rb +3 -8
  158. data/spec/fixtures/cover.jpg +0 -0
  159. data/spec/spec_helper.rb +47 -3
  160. data/tasks/spec.rake +3 -5
  161. data/util/rake/fileinstall.rb +16 -15
  162. data/util/rake/omfgenerate.rb +1 -1
  163. metadata +141 -52
  164. data/.travis.yml +0 -39
  165. data/lib/alexandria/book_providers/adlibris.rb +0 -196
  166. data/lib/alexandria/book_providers/amazon_aws.rb +0 -252
  167. data/lib/alexandria/book_providers/amazon_ecs_util.rb +0 -388
  168. data/lib/alexandria/book_providers/barnes_and_noble.rb +0 -209
  169. data/lib/alexandria/book_providers/proxis.rb +0 -175
  170. data/lib/alexandria/book_providers/siciliano.rb +0 -257
  171. data/lib/alexandria/book_providers/z3950.rb +0 -415
  172. data/spec/alexandria/ui/ui_utilities_spec.rb +0 -62
  173. 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
@@ -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
- puts "Already playing #{effect}." if $DEBUG
42
+ log.debug { "Already playing #{effect}." }
43
43
  else
44
- puts "Not playing. Starting #{effect}." if $DEBUG
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
- if $DEBUG
80
- puts "ERROR loop.quit"
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 = SidePaneManager.new @library_listview, self
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", &method(:on_toolbar_filter_entry_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", &method(:on_criterion_combobox_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
- @toolbar_view_as.signal_connect("changed", &method(:on_toolbar_view_as_changed))
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
- BookProviders.each do |provider|
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
- ["ui/MainMenubar/ViewMenu/OnlineInformation/",
189
- "ui/BookPopup/OnlineInformation/",
190
- "ui/NoBookPopup/OnlineInformation/"].each do |path|
191
- log.debug { "Adding #{name} to #{path}" }
192
- @uimanager.add_ui(mid, path, name, name,
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", &method(:on_window_state_event))
228
- @main_app.signal_connect("destroy", &method(:on_window_destroy))
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.popup(nil, nil, event.button, event.time)
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
- if event_is_right_click event
375
- widget.grab_focus
383
+ event_is_right_click event or return
376
384
 
377
- if (path = widget.get_path_at_pos(event.x.to_i, event.y.to_i))
378
- obj, path =
379
- widget.is_a?(Gtk::TreeView) ? [widget.selection, path.first] : [widget, path]
385
+ widget.grab_focus
380
386
 
381
- unless obj.path_is_selected?(path)
382
- log.debug { "Select #{path}" }
383
- widget.unselect_all
384
- obj.select_path(path)
385
- end
386
- else
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
- menu = selected_books.empty? ? @nobook_popup : @book_popup
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
- "%d unrated",
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
- "or @library_popup:#{@library_popup.has_focus?}"
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
- select_this_book = proc do |bk, view|
527
- @filtered_model.refilter
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
- if caller.is_a?(UndoManager)
542
+ case caller
543
+ when UndoManager
556
544
  @actiongroup["Undo"].sensitive = caller.can_undo?
557
545
  @actiongroup["Redo"].sensitive = caller.can_redo?
558
- elsif caller.is_a?(Library)
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
- " in library ''#{library.name}'"
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 = icon.tag(Icons::FAVORITE_TAG) if rating == Book::MAX_RATING_STARS
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 /^MoveIn/.match?(action.name)
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
- ["ui/MainMenubar/EditMenu/Move/",
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
- "#{@iconview.model.inspect} #{@listview.model.inspect}"
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 != 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 !@library_separator_iter.nil? && @libraries.all_smart_libraries.empty?
1151
- @library_listview.model.remove(@library_separator_iter)
1152
- @library_separator_iter = nil
1153
- end
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 view_path_to_model_path(view, path)
1194
- path = view.model.convert_path_to_child_path(path)
1195
- @filtered_model.convert_path_to_child_path(path) if path
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
- puts "==========================" if $DEBUG
40
- log.info { "Starting MainApp..." }
41
- puts "==========================" if $DEBUG
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
- puts "====================================" if $DEBUG
47
- log.info { "Starting Gtk..." }
48
- puts "====================================" if $DEBUG
46
+ log.debug { "====================================" }
47
+ log.info { "Starting Gtk" }
48
+ log.debug { "====================================" }
49
49
  Gtk.main
50
50
  end
51
51
 
@@ -5,7 +5,7 @@
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
7
  module Alexandria
8
- VERSION = "0.7.5"
8
+ VERSION = "0.7.9"
9
9
  DATA_VERSION = "0.6.3"
10
- DISPLAY_VERSION = "0.7.5"
10
+ DISPLAY_VERSION = VERSION
11
11
  end
@@ -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 /^\./.match?(file)
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
- raise "#{helper_file} not found" unless File.exist?(helper_file)
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
- Alexandria.log.level = Logger::DEBUG if $DEBUG
32
- Alexandria.log.debug { "Initializing Alexandria..." }
31
+ log.level = Logger::DEBUG if $DEBUG
32
+ log.debug { "Initializing Alexandria" }
33
33
  end
34
34
 
35
35
  def self.main