alexandria-book-collection-manager 0.6.9 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +34 -30
  4. data/.rubocop_todo.yml +139 -54
  5. data/CHANGELOG.md +10 -0
  6. data/Gemfile +1 -0
  7. data/Rakefile +10 -11
  8. data/alexandria-book-collection-manager.gemspec +3 -2
  9. data/bin/alexandria +1 -1
  10. data/lib/alexandria.rb +3 -6
  11. data/lib/alexandria/about.rb +9 -9
  12. data/lib/alexandria/book_providers.rb +12 -12
  13. data/lib/alexandria/book_providers/adlibris.rb +14 -18
  14. data/lib/alexandria/book_providers/amazon_aws.rb +17 -31
  15. data/lib/alexandria/book_providers/amazon_ecs_util.rb +5 -6
  16. data/lib/alexandria/book_providers/barnes_and_noble.rb +51 -76
  17. data/lib/alexandria/book_providers/bol_it.rb +12 -12
  18. data/lib/alexandria/book_providers/deastore.rb +27 -31
  19. data/lib/alexandria/book_providers/douban.rb +9 -13
  20. data/lib/alexandria/book_providers/ibs_it.rb +10 -10
  21. data/lib/alexandria/book_providers/mcu.rb +12 -18
  22. data/lib/alexandria/book_providers/proxis.rb +14 -22
  23. data/lib/alexandria/book_providers/pseudomarc.rb +8 -18
  24. data/lib/alexandria/book_providers/renaud.rb +16 -16
  25. data/lib/alexandria/book_providers/siciliano.rb +25 -38
  26. data/lib/alexandria/book_providers/thalia.rb +13 -16
  27. data/lib/alexandria/book_providers/webster_it.rb +14 -18
  28. data/lib/alexandria/book_providers/worldcat.rb +21 -25
  29. data/lib/alexandria/book_providers/z3950.rb +19 -23
  30. data/lib/alexandria/config.rb +2 -2
  31. data/lib/alexandria/execution_queue.rb +3 -1
  32. data/lib/alexandria/export_library.rb +19 -22
  33. data/lib/alexandria/import_library.rb +14 -18
  34. data/lib/alexandria/import_library_csv.rb +12 -30
  35. data/lib/alexandria/models/book.rb +7 -9
  36. data/lib/alexandria/models/library.rb +44 -44
  37. data/lib/alexandria/net.rb +1 -1
  38. data/lib/alexandria/preferences.rb +12 -57
  39. data/lib/alexandria/scanners.rb +10 -6
  40. data/lib/alexandria/scanners/cuecat.rb +2 -2
  41. data/lib/alexandria/smart_library.rb +12 -12
  42. data/lib/alexandria/ui.rb +5 -2
  43. data/lib/alexandria/ui/callbacks.rb +106 -65
  44. data/lib/alexandria/ui/completion_models.rb +55 -51
  45. data/lib/alexandria/ui/dialogs/about_dialog.rb +1 -1
  46. data/lib/alexandria/ui/dialogs/acquire_dialog.rb +25 -51
  47. data/lib/alexandria/ui/dialogs/alert_dialog.rb +13 -11
  48. data/lib/alexandria/ui/dialogs/bad_isbns_dialog.rb +2 -2
  49. data/lib/alexandria/ui/dialogs/barcode_animation.rb +39 -23
  50. data/lib/alexandria/ui/dialogs/book_properties_dialog.rb +16 -21
  51. data/lib/alexandria/ui/dialogs/book_properties_dialog_base.rb +23 -24
  52. data/lib/alexandria/ui/dialogs/export_dialog.rb +46 -45
  53. data/lib/alexandria/ui/dialogs/import_dialog.rb +26 -35
  54. data/lib/alexandria/ui/dialogs/misc_dialogs.rb +11 -11
  55. data/lib/alexandria/ui/dialogs/new_book_dialog.rb +47 -59
  56. data/lib/alexandria/ui/dialogs/new_book_dialog_manual.rb +14 -13
  57. data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +12 -11
  58. data/lib/alexandria/ui/dialogs/preferences_dialog.rb +37 -43
  59. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog.rb +9 -8
  60. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog_base.rb +47 -53
  61. data/lib/alexandria/ui/dndable.rb +5 -4
  62. data/lib/alexandria/ui/icons.rb +19 -19
  63. data/lib/alexandria/ui/iconview.rb +7 -12
  64. data/lib/alexandria/ui/iconview_tooltips.rb +22 -109
  65. data/lib/alexandria/ui/init.rb +7 -15
  66. data/lib/alexandria/ui/libraries_combo.rb +54 -48
  67. data/lib/alexandria/ui/listview.rb +30 -85
  68. data/lib/alexandria/ui/multi_drag_treeview.rb +110 -107
  69. data/lib/alexandria/ui/sidepane.rb +23 -25
  70. data/lib/alexandria/ui/sound.rb +18 -27
  71. data/lib/alexandria/ui/ui_manager.rb +126 -204
  72. data/lib/alexandria/undo_manager.rb +2 -2
  73. data/lib/alexandria/version.rb +4 -4
  74. data/spec/alexandria/book_providers_spec.rb +7 -4
  75. data/spec/alexandria/library_spec.rb +13 -16
  76. data/spec/alexandria/scanners/cuecat_spec.rb +1 -2
  77. data/spec/alexandria/ui/dialogs_spec.rb +5 -1
  78. data/spec/alexandria/ui/main_app_spec.rb +3 -3
  79. data/{lib/alexandria/utils.rb → spec/alexandria/ui/sound_spec.rb} +6 -11
  80. data/spec/alexandria/ui/ui_utilities_spec.rb +3 -3
  81. data/spec/spec_helper.rb +2 -2
  82. data/util/rake/fileinstall.rb +17 -33
  83. data/util/rake/gettextgenerate.rb +2 -4
  84. data/util/rake/omfgenerate.rb +1 -3
  85. metadata +23 -11
  86. data/lib/alexandria/ui/gtk_thread_help.rb +0 -89
@@ -1,6 +1,6 @@
1
1
  # Copyright (C) 2008 Joseph Method
2
2
  # Copyright (C) 2008,2009 Cathal Mc Ginley
3
- # Copyright (C) 2011,2014,2015 Matijs van Zuijlen
3
+ # Copyright (C) 2011, 2014-2016 Matijs van Zuijlen
4
4
  #
5
5
  # Alexandria is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License as
@@ -35,7 +35,7 @@ module Alexandria
35
35
  x = (@libraries.all_libraries + Library.deleted_libraries).find do |library|
36
36
  library.name == new_text.strip
37
37
  end
38
- x and x.name != @parent.selected_library.name
38
+ x && (x.name != @parent.selected_library.name)
39
39
  end
40
40
 
41
41
  # if new_text is invalid utf-8, returns true
@@ -97,7 +97,7 @@ module Alexandria
97
97
  end
98
98
 
99
99
  def setup_sidepane
100
- @library_listview.model = Gtk::ListStore.new(Gdk::Pixbuf,
100
+ @library_listview.model = Gtk::ListStore.new(GdkPixbuf::Pixbuf,
101
101
  String,
102
102
  TrueClass,
103
103
  TrueClass)
@@ -113,7 +113,7 @@ module Alexandria
113
113
  cell.pixbuf = iter[0]
114
114
  end
115
115
  renderer = Gtk::CellRendererText.new
116
- renderer.ellipsize = Pango::ELLIPSIZE_END if Pango.ellipsizable?
116
+ renderer.ellipsize = Pango::ELLIPSIZE_END
117
117
  column.pack_start(renderer, true)
118
118
  column.set_cell_data_func(renderer) do |_col, cell, _model, iter|
119
119
  # log.debug { "sidepane: editable #{cell}, #{iter} #{iter[1]}: #{iter[2]}" }
@@ -124,9 +124,9 @@ module Alexandria
124
124
  renderer.signal_connect('edited', &method(:on_edited_library))
125
125
  @library_listview.append_column(column)
126
126
 
127
- @library_listview.set_row_separator_func do |_model, iter|
127
+ @library_listview.set_row_separator_func do |model, iter|
128
128
  # log.debug { "library_listview row_separator #{iter}" }
129
- iter[3]
129
+ model.get_value(iter, 3)
130
130
  end
131
131
 
132
132
  @library_listview.selection.signal_connect('changed') do
@@ -135,9 +135,7 @@ module Alexandria
135
135
  @parent.refresh_books
136
136
  end
137
137
 
138
- @library_listview.enable_model_drag_dest(
139
- BOOKS_TARGET_TABLE,
140
- Gdk::DragContext::ACTION_MOVE)
138
+ @library_listview.enable_model_drag_dest(BOOKS_TARGET_TABLE, :move)
141
139
 
142
140
  @library_listview.signal_connect('drag-motion') do |_widget, drag_context, x, y, time, _data|
143
141
  log.debug { 'drag-motion' }
@@ -151,7 +149,7 @@ module Alexandria
151
149
  path = nil
152
150
  else
153
151
  iter = @library_listview.model.get_iter(path)
154
- if iter[3] # separator?
152
+ if iter[3] # separator?
155
153
  path = nil
156
154
  else
157
155
  library = @libraries.all_libraries.find do |lib|
@@ -162,22 +160,19 @@ module Alexandria
162
160
  end
163
161
  end
164
162
 
165
- @library_listview.set_drag_dest_row(
166
- path,
167
- Gtk::TreeView::DROP_INTO_OR_AFTER)
163
+ @library_listview.set_drag_dest_row(path, :into_or_after)
168
164
 
169
- drag_context.drag_status(
170
- !path.nil? ? drag_context.suggested_action : 0,
171
- time)
165
+ Gdk.drag_status(drag_context,
166
+ !path.nil? ? drag_context.suggested_action : 0,
167
+ time)
172
168
  end
173
169
 
174
170
  @library_listview.signal_connect('drag-drop') do |widget, drag_context, _x, _y, time, _data|
175
171
  log.debug { 'drag-drop' }
176
172
 
177
- Gtk::Drag.get_data(widget,
178
- drag_context,
179
- drag_context.targets.first,
180
- time)
173
+ widget.drag_get_data(drag_context,
174
+ drag_context.targets.first,
175
+ time)
181
176
  true
182
177
  end
183
178
 
@@ -185,11 +180,13 @@ module Alexandria
185
180
  log.debug { 'drag-data-received' }
186
181
 
187
182
  success = false
188
- if selection_data.type == Gdk::Selection::TYPE_STRING
189
- path, =
183
+ # FIXME: Ruby-GNOME2 should make comparison work without needing to
184
+ # call #name.
185
+ if selection_data.data_type.name == Gdk::Selection::TYPE_STRING.name
186
+ success, path =
190
187
  @library_listview.get_dest_row_at_pos(x, y)
191
188
 
192
- if path
189
+ if success
193
190
  iter = @library_listview.model.get_iter(path)
194
191
  library = @libraries.all_libraries.find do |lib|
195
192
  lib.name == iter[1]
@@ -199,9 +196,10 @@ module Alexandria
199
196
  end
200
197
  end
201
198
  begin
202
- Gtk::Drag.finish(drag_context, success, false, 0) # ,time)
199
+ drag_context.finish(success: success, delete: false)
203
200
  rescue => ex
204
- log.error { "Gtk::Drag.finish failed: #{ex}" }
201
+ log.error { "drag_context.finish failed: #{ex}" }
202
+ raise
205
203
  end
206
204
  end
207
205
  end
@@ -31,14 +31,17 @@ module Alexandria
31
31
  @ogg_vorbis_pipeline = Gst::Pipeline.new
32
32
  set_up_pipeline
33
33
  @playing = false
34
- set_up_glib_loop
34
+ set_up_bus_watch
35
35
  end
36
36
 
37
37
  def play(effect)
38
38
  file = File.join(@sounds_dir, "#{effect}.ogg")
39
39
  unless @playing
40
+ puts "Not playing. Starting #{effect}." if $DEBUG
40
41
  @filesrc.location = file
41
42
  start_playback
43
+ else
44
+ puts "Already playing #{effect}." if $DEBUG
42
45
  end
43
46
  end
44
47
 
@@ -57,50 +60,38 @@ module Alexandria
57
60
  # have multiple src pads (for audio/video muxed streams)
58
61
 
59
62
  demuxer.signal_connect('pad-added') do |_parser, ogg_src_pad|
60
- vorbis_sink_pad = decoder.get_pad('sink')
63
+ vorbis_sink_pad = decoder.sinkpads.first
61
64
  ogg_src_pad.link(vorbis_sink_pad)
62
65
  end
63
66
 
64
67
  decoder >> converter >> audiosink
65
68
  end
66
69
 
67
- def set_up_glib_loop
68
- unless @loop
69
- @loop = GLib::MainLoop.new(nil, false)
70
-
71
- @bus = @ogg_vorbis_pipeline.bus
72
- @bus.add_watch do |_bus, message|
73
- case message.type
74
- when Gst::Message::EOS
75
- @playing = false
76
- @loop.quit
77
- when Gst::Message::ERROR
78
- if $DEBUG
79
- puts 'ERROR loop.quit'
80
- p message.parse
81
- end
82
- @playing = false
83
- @loop.quit
70
+ def set_up_bus_watch
71
+ @bus = @ogg_vorbis_pipeline.bus
72
+ @bus.add_watch do |_bus, message|
73
+ case message.type
74
+ when Gst::MessageType::EOS
75
+ stop_playback
76
+ when Gst::MessageType::ERROR
77
+ if $DEBUG
78
+ puts 'ERROR loop.quit'
79
+ p message.parse
84
80
  end
85
- true
81
+ stop_playback
86
82
  end
83
+ true
87
84
  end
88
85
  end
89
86
 
90
87
  def start_playback
91
88
  @playing = true
92
89
  @ogg_vorbis_pipeline.play
93
- begin
94
- @loop.run
95
- rescue Interrupt
96
- ensure
97
- @ogg_vorbis_pipeline.stop
98
- @playing = false
99
- end
100
90
  end
101
91
 
102
92
  def stop_playback
103
93
  @ogg_vorbis_pipeline.stop
94
+ @playing = false
104
95
  end
105
96
  end
106
97
  end
@@ -1,6 +1,6 @@
1
1
  # Copyright (C) 2004-2006 Laurent Sansonetti
2
2
  # Copyright (C) 2008 Joseph Method
3
- # Copyright (C) 2011 Matijs van Zuijlen
3
+ # Copyright (C) 2011, 2016 Matijs van Zuijlen
4
4
  #
5
5
  # Alexandria is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License as
@@ -38,7 +38,7 @@ module Alexandria
38
38
  MAX_RATING_STARS = 5
39
39
 
40
40
  def initialize(parent)
41
- super('main_app__builder.glade', widget_names)
41
+ super('main_app__builder.glade', widget_names)
42
42
  @parent = parent
43
43
 
44
44
  @library_separator_iter = nil
@@ -60,7 +60,6 @@ module Alexandria
60
60
  setup_accel_group
61
61
  setup_popups
62
62
  setup_window_events
63
- setup_dialog_hooks
64
63
  setup_books_iconview_sorting
65
64
  on_books_selection_changed
66
65
  restore_preferences
@@ -89,8 +88,8 @@ module Alexandria
89
88
  end
90
89
 
91
90
  def setup_dependents
92
- @listview_model = Gtk::TreeModelSort.new(@filtered_model)
93
- @iconview_model = Gtk::TreeModelSort.new(@filtered_model)
91
+ @listview_model = Gtk::TreeModelSort.new(model: @filtered_model)
92
+ @iconview_model = Gtk::TreeModelSort.new(model: @filtered_model)
94
93
  @listview_manager = ListViewManager.new @listview, self
95
94
  @iconview_manager = IconViewManager.new @iconview, self
96
95
  @sidepane_manager = SidePaneManager.new @library_listview, self
@@ -115,29 +114,29 @@ module Alexandria
115
114
  add_main_toolbar_items
116
115
  @toolbar = @uimanager.get_widget('/MainToolbar')
117
116
  @toolbar.show_arrow = true
118
- @toolbar.insert(-1, Gtk::SeparatorToolItem.new)
117
+ @toolbar.insert(Gtk::SeparatorToolItem.new, -1)
119
118
  setup_toolbar_combobox
120
119
  setup_toolbar_filter_entry
121
- @toolbar.insert(-1, Gtk::SeparatorToolItem.new)
120
+ @toolbar.insert(Gtk::SeparatorToolItem.new, -1)
122
121
  setup_toolbar_viewas
123
122
  @toolbar.show_all
124
123
  @actiongroup['Undo'].sensitive = @actiongroup['Redo'].sensitive = false
125
124
  UndoManager.instance.add_observer(self)
126
- @vbox1.add(@toolbar, position: 1, expand: false, fill: false)
125
+ @vbox1.add(@toolbar, position: 1, expand: false, fill: false)
127
126
  end
128
127
 
129
128
  def add_main_toolbar_items
130
129
  mid = @uimanager.new_merge_id
131
130
  @uimanager.add_ui(mid, 'ui/', 'MainToolbar', 'MainToolbar',
132
- Gtk::UIManager::TOOLBAR, false)
131
+ :toolbar, false)
133
132
  @uimanager.add_ui(mid, 'ui/MainToolbar/', 'New', 'New',
134
- Gtk::UIManager::TOOLITEM, false)
133
+ :toolitem, false)
135
134
  @uimanager.add_ui(mid, 'ui/MainToolbar/', 'AddBook', 'AddBook',
136
- Gtk::UIManager::TOOLITEM, false)
135
+ :toolitem, false)
137
136
  # @uimanager.add_ui(mid, "ui/MainToolbar/", "sep", "sep",
138
- # Gtk::UIManager::SEPARATOR, false)
137
+ # :separator, false)
139
138
  # @uimanager.add_ui(mid, "ui/MainToolbar/", "Refresh", "Refresh",
140
- # Gtk::UIManager::TOOLITEM, false)
139
+ # :toolitem, false)
141
140
  end
142
141
 
143
142
  def setup_toolbar_filter_entry
@@ -146,19 +145,16 @@ module Alexandria
146
145
  @toolitem = Gtk::ToolItem.new
147
146
  @toolitem.expand = true
148
147
  @toolitem.border_width = 5
149
- @tooltips.set_tip(@filter_entry,
150
- _('Type here the search criterion'), nil)
148
+ @filter_entry.set_tooltip_text _('Type here the search criterion')
151
149
  @toolitem << @filter_entry
152
- @toolbar.insert(-1, @toolitem)
150
+ @toolbar.insert(@toolitem, -1)
153
151
  end
154
152
 
155
153
  def setup_toolbar_combobox
156
- @tooltips = Gtk::Tooltips.new
157
-
158
- cb = Gtk::ComboBox.new
159
- cb.set_row_separator_func do |_model, iter|
154
+ cb = Gtk::ComboBoxText.new
155
+ cb.set_row_separator_func do |model, iter|
160
156
  # log.debug { "row_separator" }
161
- iter[0] == '-'
157
+ model.get_value(iter, 0) == '-'
162
158
  end
163
159
  [_('Match everything'),
164
160
  '-',
@@ -167,8 +163,7 @@ module Alexandria
167
163
  _('ISBN contains'),
168
164
  _('Publisher contains'),
169
165
  _('Notes contain'),
170
- _('Tags contain')
171
- ].each do |item|
166
+ _('Tags contain')].each do |item|
172
167
  cb.append_text(item)
173
168
  end
174
169
  cb.active = 0
@@ -181,12 +176,12 @@ module Alexandria
181
176
  @toolitem = Gtk::ToolItem.new
182
177
  @toolitem.border_width = 5
183
178
  @toolitem << eb
184
- @toolbar.insert(-1, @toolitem)
185
- @tooltips.set_tip(eb, _('Change the search type'), nil)
179
+ @toolbar.insert(@toolitem, -1)
180
+ eb.set_tooltip_text _('Change the search type')
186
181
  end
187
182
 
188
183
  def setup_toolbar_viewas
189
- @toolbar_view_as = Gtk::ComboBox.new
184
+ @toolbar_view_as = Gtk::ComboBoxText.new
190
185
  @toolbar_view_as.append_text(_('View as Icons'))
191
186
  @toolbar_view_as.append_text(_('View as List'))
192
187
  @toolbar_view_as.active = 0
@@ -200,8 +195,8 @@ module Alexandria
200
195
  @toolitem = Gtk::ToolItem.new
201
196
  @toolitem.border_width = 5
202
197
  @toolitem << eb
203
- @toolbar.insert(-1, @toolitem)
204
- @tooltips.set_tip(eb, _('Choose how to show books'), nil)
198
+ @toolbar.insert(@toolitem, -1)
199
+ eb.set_tooltip_text _('Choose how to show books')
205
200
  end
206
201
 
207
202
  def setup_book_providers
@@ -214,7 +209,7 @@ module Alexandria
214
209
  'ui/NoBookPopup/OnlineInformation/'].each do |path|
215
210
  log.debug { "Adding #{name} to #{path}" }
216
211
  @uimanager.add_ui(mid, path, name, name,
217
- Gtk::UIManager::MENUITEM, false)
212
+ :menuitem, false)
218
213
  end
219
214
  end
220
215
  end
@@ -234,19 +229,7 @@ module Alexandria
234
229
 
235
230
  def setup_menus
236
231
  @menubar = @uimanager.get_widget('/MainMenubar')
237
- @vbox1.add(@menubar, position: 0, expand: false, fill: false)
238
- end
239
-
240
- def setup_dialog_hooks
241
- log.debug { 'setup_dialog_hooks' }
242
- Gtk::AboutDialog.set_url_hook do |_about, link|
243
- log.debug { 'set_url_hook' }
244
- open_web_browser(link)
245
- end
246
- Gtk::AboutDialog.set_email_hook do |_about, link|
247
- log.debug { 'set_email_hook' }
248
- open_email_client('mailto:' + link)
249
- end
232
+ @vbox1.add(@menubar, position: 0, expand: false, fill: false)
250
233
  end
251
234
 
252
235
  def setup_popups
@@ -269,8 +252,8 @@ module Alexandria
269
252
  # The active model.
270
253
 
271
254
  list = [
272
- Gdk::Pixbuf, # COVER_LIST
273
- Gdk::Pixbuf, # COVER_ICON
255
+ GdkPixbuf::Pixbuf, # COVER_LIST
256
+ GdkPixbuf::Pixbuf, # COVER_ICON
274
257
  String, # TITLE
275
258
  String, # TITLE_REDUCED
276
259
  String, # AUTHORS
@@ -301,12 +284,12 @@ module Alexandria
301
284
  else
302
285
  data = case @filter_books_mode
303
286
  when 0 then
304
- (iter[Columns::TITLE] or '') +
305
- (iter[Columns::AUTHORS] or '') +
306
- (iter[Columns::ISBN] or '') +
307
- (iter[Columns::PUBLISHER] or '') +
308
- (iter[Columns::NOTES] or '') +
309
- (iter[Columns::TAGS] or '')
287
+ (iter[Columns::TITLE] || '') +
288
+ (iter[Columns::AUTHORS] || '') +
289
+ (iter[Columns::ISBN] || '') +
290
+ (iter[Columns::PUBLISHER] || '') +
291
+ (iter[Columns::NOTES] || '') +
292
+ (iter[Columns::TAGS] || '')
310
293
  when 2 then iter[Columns::TITLE]
311
294
  when 3 then iter[Columns::AUTHORS]
312
295
  when 4 then iter[Columns::ISBN]
@@ -314,7 +297,7 @@ module Alexandria
314
297
  when 6 then iter[Columns::NOTES]
315
298
  when 7 then iter[Columns::TAGS]
316
299
  end
317
- !data.nil? and data.downcase.include?(filter.downcase)
300
+ !data.nil? && data.downcase.include?(filter.downcase)
318
301
  end
319
302
  end
320
303
 
@@ -344,7 +327,7 @@ module Alexandria
344
327
  sensitize_library selected_library
345
328
 
346
329
  if widget.is_a?(Gtk::TreeView)
347
- Gtk.idle_add do
330
+ GLib::Idle.add do
348
331
  # cur_path, focus_col = widget.cursor
349
332
 
350
333
  widget.focus = true
@@ -377,13 +360,13 @@ module Alexandria
377
360
  if library_already_selected
378
361
  sensitize_library selected_library
379
362
 
380
- Gtk.idle_add do
363
+ GLib::Idle.add do
381
364
  menu.popup(nil, nil, event.button, event.time)
382
365
  # @clicking_on_sidepane = false
383
366
  false
384
367
  end
385
368
  else
386
- Gtk.idle_add do
369
+ GLib::Idle.add do
387
370
  menu.popup(nil, nil, event.button, event.time)
388
371
  # @clicking_on_sidepane = false
389
372
 
@@ -410,7 +393,7 @@ module Alexandria
410
393
  end
411
394
 
412
395
  def event_is_right_click(event)
413
- event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 3
396
+ (event.event_type == :button_press) && (event.button == 3)
414
397
  end
415
398
 
416
399
  def on_books_button_press_event(widget, event)
@@ -430,7 +413,7 @@ module Alexandria
430
413
  widget.unselect_all
431
414
  end
432
415
 
433
- menu = (selected_books.empty?) ? @nobook_popup : @book_popup
416
+ menu = selected_books.empty? ? @nobook_popup : @book_popup
434
417
  menu.popup(nil, nil, event.button, event.time)
435
418
  end
436
419
  end
@@ -447,7 +430,7 @@ module Alexandria
447
430
  "Library '%s' selected, %d unrated books",
448
431
  library.length) % [library.name,
449
432
  library.length]
450
- elsif n_unrated == 0
433
+ elsif n_unrated.zero?
451
434
  n_("Library '%s' selected, %d book",
452
435
  "Library '%s' selected, %d books",
453
436
  library.length) % [library.name,
@@ -487,7 +470,7 @@ module Alexandria
487
470
  # selection = @library_listview.selection.selected ? @library_listview.selection.selected.has_focus? : false
488
471
 
489
472
  # Focus is the wrong idiom here.
490
- unless @clicking_on_sidepane or (@main_app.focus == @library_listview)
473
+ unless @clicking_on_sidepane || (@main_app.focus == @library_listview)
491
474
  # unless @main_app.focus == @library_listview
492
475
 
493
476
  log.debug { "Currently focused widget: #{@main_app.focus.inspect}" }
@@ -521,7 +504,7 @@ module Alexandria
521
504
  BookProviders.each do |provider|
522
505
  has_no_url = true
523
506
  begin
524
- has_no_url = (b.isbn.nil? or b.isbn.strip.empty? or provider.url(b).nil?)
507
+ has_no_url = (b.isbn.nil? || b.isbn.strip.empty? || provider.url(b).nil?)
525
508
  rescue => ex
526
509
  log.warn { "Error determining URL from #{provider.name}; #{ex.message}" }
527
510
  end
@@ -536,16 +519,16 @@ module Alexandria
536
519
  @clicking_on_sidepane = false
537
520
  end
538
521
 
539
- def on_switch_page
522
+ def on_switch_page(_notebook, _page, page_num)
540
523
  log.debug { 'on_switch_page' }
541
- @actiongroup['ArrangeIcons'].sensitive = @notebook.page == 0
524
+ @actiongroup['ArrangeIcons'].sensitive = page_num.zero?
542
525
  on_books_selection_changed
543
526
  end
544
527
 
545
528
  def on_focus(widget, _event_focus)
546
- if @clicking_on_sidepane or widget == @library_listview
529
+ if @clicking_on_sidepane || (widget == @library_listview)
547
530
  log.debug { 'on_focus: @library_listview' }
548
- Gtk.idle_add do
531
+ GLib::Idle.add do
549
532
  %w(OnlineInformation SelectAll DeselectAll).each do |action|
550
533
  @actiongroup[action].sensitive = false
551
534
  end
@@ -559,7 +542,7 @@ module Alexandria
559
542
  end
560
543
 
561
544
  def determine_delete_option
562
- sensitive = (@libraries.all_regular_libraries.length > 1 or selected_library.is_a?(SmartLibrary))
545
+ sensitive = (@libraries.all_regular_libraries.length > 1 || selected_library.is_a?(SmartLibrary))
563
546
  sensitive
564
547
  end
565
548
 
@@ -572,15 +555,10 @@ module Alexandria
572
555
  select_this_book = proc do |bk, view|
573
556
  @filtered_model.refilter
574
557
  iter = iter_from_book bk
575
- unless iter
576
- next
577
- end
558
+ next unless iter
578
559
  path = iter.path
579
- unless view.model
580
- next
581
- end
582
- path = view.model.convert_path_to_child_path(path)
583
- path = @filtered_model.convert_path_to_child_path(path)
560
+ next unless view.model
561
+ path = view_path_to_model_path(view, path)
584
562
  log.debug { "Path for #{bk.ident} is #{path}" }
585
563
  selection = view.respond_to?(:selection) ? @listview.selection : @iconview
586
564
  selection.unselect_all
@@ -606,9 +584,7 @@ module Alexandria
606
584
  @actiongroup['Redo'].sensitive = caller.can_redo?
607
585
  elsif caller.is_a?(Library)
608
586
  unless caller.updating?
609
- Gtk.queue do
610
- handle_update_caller_library ary
611
- end
587
+ handle_update_caller_library ary
612
588
  end
613
589
  else
614
590
  raise 'unrecognized update event'
@@ -625,9 +601,7 @@ module Alexandria
625
601
  append_book(book)
626
602
  when Library::BOOK_UPDATED
627
603
  iter = iter_from_ident(book.saved_ident)
628
- if iter
629
- fill_iter_with_book(iter, book)
630
- end
604
+ fill_iter_with_book(iter, book) if iter
631
605
  when Library::BOOK_REMOVED
632
606
  @model.remove(iter_from_book(book))
633
607
  end
@@ -646,41 +620,7 @@ module Alexandria
646
620
  log.warn('Attempt to open browser with nil url')
647
621
  return
648
622
  end
649
- if (cmd = Preferences.instance.www_browser)
650
- launch_command = cmd
651
- if cmd.downcase.index('%u')
652
- launch_command = cmd.gsub(/%U/i, "\"" + url + "\"")
653
- else
654
- launch_command = cmd + " \"" + url + "\""
655
- end
656
- Thread.new { system(launch_command) }
657
- else
658
- ErrorDialog.new(@main_app,
659
- _('Unable to launch the web browser'),
660
- _('Check out that a web browser is ' \
661
- 'configured as default (Desktop ' \
662
- 'Preferences -> Advanced -> Preferred ' \
663
- 'Applications) and try again.'))
664
- end
665
- end
666
-
667
- def open_email_client(url)
668
- if (cmd = Preferences.instance.email_client)
669
- launch_command = cmd
670
- if cmd.downcase.index('%u')
671
- launch_command = cmd.gsub(/%u/i, "\"" + url + "\"")
672
- else
673
- launch_command = cmd + " \"" + url + "\""
674
- end
675
- Thread.new { system(launch_command) }
676
- else
677
- ErrorDialog.new(@main_app,
678
- _('Unable to launch the mail reader'),
679
- _('Check out that a mail reader is ' \
680
- 'configured as default (Desktop ' \
681
- 'Preferences -> Advanced -> Preferred ' \
682
- 'Applications) and try again.'))
683
- end
623
+ Gtk.show_uri url
684
624
  end
685
625
 
686
626
  def detach_old_libraries
@@ -719,7 +659,7 @@ module Alexandria
719
659
  # entries.\n" )
720
660
 
721
661
  @libraries.ruined_books.each { |bi|
722
- new_message += "\n#{bi[1] or bi[1].inspect}"
662
+ new_message += "\n#{bi[1] || bi[1].inspect}"
723
663
  }
724
664
  recovery_dialog = Gtk::MessageDialog.new(@main_app, Gtk::Dialog::MODAL,
725
665
  Gtk::MessageDialog::WARNING,
@@ -727,17 +667,17 @@ module Alexandria
727
667
  new_message).show
728
668
  recovery_dialog.signal_connect('response') do |_dialog, response_type|
729
669
  recovery_dialog.destroy
730
- if response_type == Gtk::Dialog::RESPONSE_OK
670
+ if response_type == :ok
731
671
  # progress indicator...
732
672
  @progressbar.fraction = 0
733
- @appbar.children.first.visible = true # show the progress bar
673
+ @appbar.children.first.visible = true # show the progress bar
734
674
 
735
675
  total_book_count = @libraries.ruined_books.size
736
676
  fraction_per_book = 1.0 / total_book_count
737
677
  prog_percentage = 0
738
678
 
739
679
  @libraries.ruined_books.reverse!
740
- Gtk.idle_add do
680
+ GLib::Idle.add do
741
681
  ruined_book = @libraries.ruined_books.pop
742
682
  if ruined_book
743
683
  book, isbn, library = ruined_book
@@ -746,7 +686,7 @@ module Alexandria
746
686
  book = book_rslt[0]
747
687
  cover_uri = book_rslt[1]
748
688
 
749
- # TODO if the book was saved okay, make sure the old
689
+ # TODO: if the book was saved okay, make sure the old
750
690
  # empty yaml file doesn't stick around esp if doing
751
691
  # isbn-10 --> isbn-13 conversion...
752
692
  if isbn.size == 10
@@ -818,18 +758,18 @@ module Alexandria
818
758
  iter[Columns::PUBLISHER] = book.publisher
819
759
  iter[Columns::PUBLISH_DATE] = book.publishing_year.to_s
820
760
  iter[Columns::EDITION] = book.edition
821
- iter[Columns::NOTES] = (book.notes or '')
822
- iter[Columns::LOANED_TO] = (book.loaned_to or '')
823
- rating = (book.rating or Book::DEFAULT_RATING)
761
+ iter[Columns::NOTES] = (book.notes || '')
762
+ iter[Columns::LOANED_TO] = (book.loaned_to || '')
763
+ rating = (book.rating || Book::DEFAULT_RATING)
824
764
  iter[Columns::RATING] = MAX_RATING_STARS - rating # ascending order is the default
825
765
  iter[Columns::OWN] = book.own?
826
766
  iter[Columns::REDD] = book.redd?
827
767
  iter[Columns::WANT] = book.want?
828
- if book.tags
829
- iter[Columns::TAGS] = book.tags.join(',')
830
- else
831
- iter[Columns::TAGS] = ''
832
- end
768
+ iter[Columns::TAGS] = if book.tags
769
+ book.tags.join(',')
770
+ else
771
+ ''
772
+ end
833
773
 
834
774
  icon = Icons.cover(selected_library, book)
835
775
  log.debug { "Setting icon #{icon} for book #{book.title}" }
@@ -916,45 +856,38 @@ module Alexandria
916
856
  @iconview.freeze
917
857
  @listview.freeze # NEW / bdewey
918
858
  @progressbar.fraction = 0
919
- @appbar.children.first.visible = true # show the progress bar
859
+ @appbar.children.first.visible = true # show the progress bar
920
860
  set_status_label(_("Loading '%s'...") % library.name)
921
861
  total = library.length
922
862
  log.debug { "library #{library.name} length #{library.length}" }
923
863
  n = 0
924
864
 
925
- Gtk.idle_add do
865
+ GLib::Idle.add do
926
866
  block_return = true
927
867
  book = library[n]
928
868
  if book
929
- Gtk.queue do
930
- begin
931
- append_book(book)
932
- rescue => ex
933
- trace = ex.backtrace.join("\n > ")
934
- log.error { "append_books failed #{ex.message} #{trace}" }
935
- end
936
- # convert to percents
937
- coeff = total / 100.0
938
- percent = n / coeff
939
- fraction = percent / 100
940
- log.debug { "#index #{n} percent #{percent} fraction #{fraction}" }
941
- @progressbar.fraction = fraction
942
- n += 1
869
+ begin
870
+ append_book(book)
871
+ rescue => ex
872
+ trace = ex.backtrace.join("\n > ")
873
+ log.error { "append_books failed #{ex.message} #{trace}" }
943
874
  end
875
+ fraction = n * 1.0 / total
876
+ log.debug { "#index #{n} fraction #{fraction}" }
877
+ @progressbar.fraction = fraction
878
+ n += 1
944
879
  else
945
- Gtk.queue do
946
- @iconview.unfreeze
947
- @listview.unfreeze # NEW / bdewey
948
- @filtered_model.refilter
949
- @listview.columns_autosize
950
- @progressbar.fraction = 1
951
- # Hide the progress bar.
952
- @appbar.children.first.visible = false
953
- # Refresh the status bar.
954
- on_books_selection_changed
955
- @library_listview.set_sensitive(true)
956
- block_return = false
957
- end
880
+ @iconview.unfreeze
881
+ @listview.unfreeze # NEW / bdewey
882
+ @filtered_model.refilter
883
+ @listview.columns_autosize
884
+ @progressbar.fraction = 1
885
+ # Hide the progress bar.
886
+ @appbar.children.first.visible = false
887
+ # Refresh the status bar.
888
+ on_books_selection_changed
889
+ @library_listview.set_sensitive(true)
890
+ block_return = false
958
891
  end
959
892
 
960
893
  block_return
@@ -989,57 +922,44 @@ module Alexandria
989
922
  end
990
923
 
991
924
  def iter_from_ident(ident)
992
- log.debug { "#{ident}" }
925
+ log.debug { ident.to_s }
993
926
  iter = @model.iter_first
994
927
  ok = true
995
928
  while ok
996
- if iter[Columns::IDENT] == ident
997
- return iter
998
- end
929
+ return iter if iter[Columns::IDENT] == ident
999
930
  ok = iter.next!
1000
931
  end
1001
932
  nil
1002
933
  end
1003
934
 
1004
935
  def iter_from_book(book)
1005
- log.debug { "#{book}" }
936
+ log.debug { book.to_s }
1006
937
  iter_from_ident(book.ident)
1007
938
  end
1008
939
 
1009
940
  def collate_selected_books(page)
1010
- a = []
941
+ result = []
1011
942
  library = selected_library
1012
- view = page == 0 ? @iconview : @listview
1013
- selection = page == 0 ? @iconview : @listview.selection
1014
-
1015
- selection.selected_each do |_the_view, path|
1016
- # don't use the_view which is passed in by this block
1017
- # as it doesn't consider the filtering for some reason
1018
- # see bug #24568
1019
- unless view.model
1020
- next
943
+
944
+ if page.zero?
945
+ result = @iconview.selected_items.map do |path|
946
+ path = view_path_to_model_path(@iconview, path)
947
+ book_from_iter(library, @model.get_iter(path))
1021
948
  end
1022
- path = view.model.convert_path_to_child_path(path)
1023
- if path
1024
- path = @filtered_model.convert_path_to_child_path(path)
1025
- # FIX this sometimes returns a nil path for iconview...
1026
- if path
1027
- iter = @model.get_iter(path)
1028
- if iter
1029
- a << book_from_iter(library, iter)
1030
- end
1031
- end
1032
- # This used to cause a crash when manually adding the first
1033
- # book to a Library displayed in an Iconview
1034
- # TODO find root cause of this
949
+ else
950
+ selection = @listview.selection
951
+ rows, _model = selection.selected_rows
952
+ result = rows.map do |path|
953
+ path = view_path_to_model_path(@listview, path)
954
+ book_from_iter(library, @model.get_iter(path))
1035
955
  end
1036
956
  end
1037
- a
957
+
958
+ result
1038
959
  end
1039
960
 
1040
961
  def selected_books
1041
- a = collate_selected_books(@notebook.page)
1042
- selected = a.select { |x| !x.nil? }
962
+ selected = collate_selected_books(@notebook.page).compact
1043
963
  log.debug { "Selected books = #{selected.inspect}" }
1044
964
  selected
1045
965
  end
@@ -1054,9 +974,7 @@ module Alexandria
1054
974
  # Disable the selected library in the move libraries actions.
1055
975
  @libraries.all_regular_libraries.each do |i_library|
1056
976
  action = @actiongroup[i_library.action_name]
1057
- if action
1058
- action.sensitive = i_library != library
1059
- end
977
+ action.sensitive = i_library != library if action
1060
978
  end
1061
979
  sensitize_library library
1062
980
  end
@@ -1064,7 +982,7 @@ module Alexandria
1064
982
  def sensitize_library(library)
1065
983
  smart = library.is_a?(SmartLibrary)
1066
984
  log.debug { "sensitize_library: smartlibrary = #{smart}" }
1067
- Gtk.idle_add do
985
+ GLib::Idle.add do
1068
986
  @actiongroup['AddBook'].sensitive = !smart
1069
987
  @actiongroup['AddBookManual'].sensitive = !smart
1070
988
  @actiongroup['Properties'].sensitive = smart
@@ -1132,7 +1050,7 @@ module Alexandria
1132
1050
  @prefs.selected_library = selected_library.name
1133
1051
  cols_width = {}
1134
1052
  @listview.columns.each do |c|
1135
- cols_width[c.title] = [c.widget.size_request.first, c.width].max
1053
+ cols_width[c.title] = c.width
1136
1054
  end
1137
1055
  @prefs.cols_width = '{' + cols_width.to_a.map do |t, v|
1138
1056
  '"' + t + '": ' + v.to_s
@@ -1149,7 +1067,7 @@ module Alexandria
1149
1067
 
1150
1068
  def move_selected_books_to_library(library)
1151
1069
  books = selected_books.select do |book|
1152
- !library.include?(book) or
1070
+ !library.include?(book) ||
1153
1071
  ConflictWhileCopyingDialog.new(@main_app,
1154
1072
  library,
1155
1073
  book).replace?
@@ -1159,7 +1077,7 @@ module Alexandria
1159
1077
 
1160
1078
  def setup_move_actions
1161
1079
  @actiongroup.actions.each do |action|
1162
- next unless /^MoveIn/.match(action.name)
1080
+ next unless /^MoveIn/ =~ action.name
1163
1081
  @actiongroup.remove_action(action)
1164
1082
  end
1165
1083
  actions = []
@@ -1178,7 +1096,7 @@ module Alexandria
1178
1096
  ['ui/MainMenubar/EditMenu/Move/',
1179
1097
  'ui/BookPopup/Move/'].each do |path|
1180
1098
  @uimanager.add_ui(@move_mid, path, name, name,
1181
- Gtk::UIManager::MENUITEM, false)
1099
+ :menuitem, false)
1182
1100
  end
1183
1101
  end
1184
1102
  end
@@ -1196,11 +1114,8 @@ module Alexandria
1196
1114
  def library_sort_order
1197
1115
  # added by Cathal Mc Ginley, 23 Oct 2007
1198
1116
  log.debug { "library_sort_order #{@notebook.page}: #{@iconview.model.inspect} #{@listview.model.inspect}" }
1199
- sorted_on = current_view.model.sort_column_id
1200
- if sorted_on
1201
- sort_column = sorted_on[0]
1202
- sort_order = sorted_on[1]
1203
-
1117
+ result, sort_column, sort_order = current_view.model.sort_column_id
1118
+ if result
1204
1119
  column_ids_to_attributes = { 2 => :title,
1205
1120
  4 => :authors,
1206
1121
  5 => :isbn,
@@ -1212,8 +1127,8 @@ module Alexandria
1212
1127
  14 => :want,
1213
1128
  9 => :rating }
1214
1129
 
1215
- sort_attribute = column_ids_to_attributes[sort_column]
1216
- ascending = (sort_order == Gtk::SORT_ASCENDING)
1130
+ sort_attribute = column_ids_to_attributes.fetch sort_column
1131
+ ascending = (sort_order == :ascending)
1217
1132
  LibrarySortOrder.new(sort_attribute, ascending)
1218
1133
  else
1219
1134
  LibrarySortOrder::Unsorted.new
@@ -1260,7 +1175,7 @@ module Alexandria
1260
1175
  end
1261
1176
 
1262
1177
  def remove_library_separator
1263
- if !@library_separator_iter.nil? and @libraries.all_smart_libraries.empty?
1178
+ if !@library_separator_iter.nil? && @libraries.all_smart_libraries.empty?
1264
1179
  @library_listview.model.remove(@library_separator_iter)
1265
1180
  @library_separator_iter = nil
1266
1181
  end
@@ -1291,14 +1206,21 @@ module Alexandria
1291
1206
  ICONS_SORTS = [
1292
1207
  Columns::TITLE, Columns::AUTHORS, Columns::ISBN,
1293
1208
  Columns::PUBLISHER, Columns::EDITION, Columns::RATING, Columns::REDD, Columns::OWN, Columns::WANT
1294
- ]
1209
+ ].freeze
1295
1210
 
1296
1211
  def setup_books_iconview_sorting
1297
- sort_order = @prefs.reverse_icons ? Gtk::SORT_DESCENDING : Gtk::SORT_ASCENDING
1212
+ sort_order = @prefs.reverse_icons ? :descending : :ascending
1298
1213
  mode = ICONS_SORTS[@prefs.arrange_icons_mode]
1299
1214
  @iconview_model.set_sort_column_id(mode, sort_order)
1300
1215
  @filtered_model.refilter # force redraw
1301
1216
  end
1217
+
1218
+ private
1219
+
1220
+ def view_path_to_model_path(view, path)
1221
+ path = view.model.convert_path_to_child_path(path)
1222
+ @filtered_model.convert_path_to_child_path(path) if path
1223
+ end
1302
1224
  end
1303
1225
  end
1304
1226
  end