Module: Alexandria::UI::Callbacks

Includes:
Logging
Defined in:
lib/alexandria/ui/callbacks.rb

Instance Method Summary collapse

Methods included from Logging

included, #log

Instance Method Details

#connect_signalsObject



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/alexandria/ui/callbacks.rb', line 300

def connect_signals
  # rubocop:disable LineLength
  standard_actions = [
    ['LibraryMenu', nil, _('_Library')],
    ['New', Gtk::Stock::NEW, _('_New Library'), '<control>L', _('Create a new library'), method(:on_new)],
    ['NewSmart', nil, _('New _Smart Library...'), '<control><shift>L', _('Create a new smart library'), method(:on_new_smart)],
    ['AddBook', Gtk::Stock::ADD, _('_Add Book...'), '<control>N', _('Add a new book from the Internet'), method(:on_add_book)],
    ['AddBookManual', nil, _('Add Book _Manually...'), '<control><shift>N', _('Add a new book manually'), method(:on_add_book_manual)],
    ['Import', nil, _('_Import...'), '<control>I', _('Import a library'), method(:on_import)],
    ['Export', nil, _('_Export...'), '<control><shift>E', _('Export the selected library'), method(:on_export)],
    ['Acquire', nil, _('A_cquire from Scanner...'), '<control><shift>S', _('Acquire books from a scanner'), method(:on_acquire)],
    ['Properties', Gtk::Stock::PROPERTIES, _('_Properties'), nil, _('Edit the properties of the selected book'), method(:on_properties)],
    ['Quit', Gtk::Stock::QUIT, _('_Quit'), '<control>Q', _('Quit the program'), method(:on_quit)],
    ['EditMenu', nil, _('_Edit')],
    ['Undo', Gtk::Stock::UNDO, _('_Undo'), '<control>Z', _('Undo the last action'), method(:on_undo)],
    ['Redo', Gtk::Stock::REDO, _('_Redo'), '<control><shift>Z', _('Redo the undone action'), method(:on_redo)],
    ['SelectAll', nil, _('_Select All'), '<control>A', _('Select all visible books'), method(:on_select_all)],
    ['DeselectAll', nil, _('Dese_lect All'), '<control><shift>A', _('Deselect everything'), method(:on_deselect_all)],
    ['SetRating', nil, _('My _Rating')],
    ['SetRating0', nil, _('None'), nil, nil, proc { on_set_rating[0].call }],
    ['SetRating1', nil, _('One Star'), nil, nil, proc { on_set_rating[1].call }],
    ['SetRating2', nil, _('Two Stars'), nil, nil, proc { on_set_rating[2].call }],
    ['SetRating3', nil, _('Three Stars'), nil, nil, proc { on_set_rating[3].call }],
    ['SetRating4', nil, _('Four Stars'), nil, nil, proc { on_set_rating[4].call }],
    ['SetRating5', nil, _('Five Stars'), nil, nil, proc { on_set_rating[5].call }],
    ['Move', nil, _('_Move')],
    ['Rename', nil, _('_Rename'), nil, nil, method(:on_rename)],
    ['Delete', Gtk::Stock::DELETE, _('_Delete'), 'Delete', _('Delete the selected books or library'), method(:on_delete)],
    ['Search', Gtk::Stock::FIND, _('_Search'), '<control>F', _('Filter books'), method(:on_search)],
    ['ClearSearchResult', Gtk::Stock::CLEAR, _('_Clear Results'), '<control><alt>B', _('Clear the search results'), method(:on_clear_search_results)],
    ['Preferences', Gtk::Stock::PREFERENCES, _('_Preferences'), '<control>O', _("Change Alexandria's settings"), method(:on_preferences)],
    ['ViewMenu', nil, _('_View')],
    ['ArrangeIcons', nil, _('Arran_ge Icons')],
    ['OnlineInformation', nil, _('Display Online _Information')],

    ['HelpMenu', nil, _('_Help')],
    ['SubmitBugReport', Gtk::Stock::EDIT, _('Submit _Bug Report'), nil, _('Submit a bug report to the developers'), method(:on_submit_bug_report)],
    ['Help', Gtk::Stock::HELP, _('Contents'), 'F1', _("View Alexandria's manual"), method(:on_help)],
    ['About', Gtk::Stock::ABOUT, _('_About'), nil, _('Show information about Alexandria'), method(:on_about)],
  ]
  # rubocop:enable LineLength

  toggle_actions = [
    ['Sidepane', nil, _('Side _Pane'), 'F9', nil, method(:on_view_sidepane), true],
    ['Toolbar', nil, _('_Toolbar'), nil, nil, method(:on_view_toolbar), true],
    ['Statusbar', nil, _('_Statusbar'), nil, nil, method(:on_view_statusbar), true],
    ['ReversedOrder', nil, _('Re_versed Order'), nil, nil, method(:on_reverse_order)],
  ]

  view_as_actions = [
    ['AsIcons', nil, _('View as _Icons'), nil, nil, 0],
    ['AsList', nil, _('View as _List'), nil, nil, 1]
  ]

  arrange_icons_actions = [
    ['ByTitle', nil, _('By _Title'), nil, nil, 0],
    ['ByAuthors', nil, _('By _Authors'), nil, nil, 1],
    ['ByISBN', nil, _('By _ISBN'), nil, nil, 2],
    ['ByPublisher', nil, _('By _Publisher'), nil, nil, 3],
    ['ByEdition', nil, _('By _Binding'), nil, nil, 4],
    ['ByRating', nil, _('By _Rating'), nil, nil, 5]
  ]
  providers_actions = BookProviders.map do |provider|
    [provider.action_name, Gtk::Stock::JUMP_TO,
     _('At _%s') % provider.fullname, nil, nil,
     proc { open_web_browser(provider.url(selected_books.first)) }]
  end

  log.debug { 'Adding actions to @actiongroup' }

  @actiongroup = Gtk::ActionGroup.new('actions')

  standard_actions.each do |name, stock_id, label, accelerator, tooltip, callback|
    action = Gtk::Action.new(name, label: label, tooltip: tooltip, stock_id: stock_id)
    @actiongroup.add_action_with_accel(action, accelerator)
    action.signal_connect('activate', &callback) if callback
  end

  providers_actions.each do |name, stock_id, label, accelerator, tooltip, callback|
    action = Gtk::Action.new(name, label: label, tooltip: tooltip, stock_id: stock_id)
    @actiongroup.add_action_with_accel(action, accelerator)
    action.signal_connect('activate', &callback) if callback
  end

  toggle_actions.each do |name, stock_id, label, accelerator, tooltip, callback, is_active|
    action = Gtk::ToggleAction.new(name, label: label, tooltip: tooltip, stock_id: stock_id)
    action.set_active is_active
    @actiongroup.add_action_with_accel(action, accelerator)
    action.signal_connect('toggled', &callback) if callback
  end

  group = nil
  first_action = nil
  view_as_actions.each do |name, stock_id, label, accelerator, tooltip, value|
    action = Gtk::RadioAction.new(name, value, label: label, tooltip: tooltip, stock_id: stock_id)
    first_action = action unless group
    action.set_group group
    group = action.group
    @actiongroup.add_action_with_accel(action, accelerator)
  end

  first_action.signal_connect 'changed' do |_action, current, _user_data|
    @notebook.page = current.current_value
    hid = @toolbar_view_as_signal_hid
    @toolbar_view_as.signal_handler_block(hid) do
      @toolbar_view_as.active = current.current_value
    end
  end

  group = nil
  first_action = nil
  arrange_icons_actions.each do |name, stock_id, label, accelerator, tooltip, value|
    action = Gtk::RadioAction.new(name, value, label: label, tooltip: tooltip, stock_id: stock_id)
    first_action = action unless group
    action.set_group group
    group = action.group
    @actiongroup.add_action_with_accel(action, accelerator)
  end

  first_action.signal_connect 'changed' do |_action, current, _user_data|
    @prefs.arrange_icons_mode = current.current_value
    setup_books_iconview_sorting
  end
end

#on_aboutObject



269
270
271
272
273
274
275
276
# File 'lib/alexandria/ui/callbacks.rb', line 269

def on_about(*)
  ad = AboutDialog.new(@main_app)
  ad.signal_connect('response') do
    log.debug { 'destroy about' }
    ad.destroy
  end
  ad.show
end

#on_acquireObject



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/alexandria/ui/callbacks.rb', line 133

def on_acquire(*)
  AcquireDialog.new(@main_app,
                    selected_library) do |_books, library, is_new|
                      if is_new
                        append_library(library, true)
                        setup_move_actions
                      elsif selected_library != library
                        select_library(library)
                      end
                    end
end

#on_add_bookObject



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/alexandria/ui/callbacks.rb', line 45

def on_add_book(*)
  log.info { 'on_add_book' }
  NewBookDialog.new(@main_app, selected_library) do |_books, library, is_new|
    if is_new
      append_library(library, true)
      setup_move_actions
    elsif selected_library != library
      select_library(library)
    end
  end
end

#on_add_book_manualObject



57
58
59
60
61
62
# File 'lib/alexandria/ui/callbacks.rb', line 57

def on_add_book_manual(*)
  library = selected_library
  NewBookDialogManual.new(@main_app, library) { |_book|
    refresh_books
  }
end

#on_clear_search_resultsObject



244
245
246
247
248
249
# File 'lib/alexandria/ui/callbacks.rb', line 244

def on_clear_search_results(*)
  @filter_entry.text = ''
  @iconview.freeze
  @filtered_model.refilter
  @iconview.unfreeze
end

#on_criterion_combobox_changed(cb) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/alexandria/ui/callbacks.rb', line 114

def on_criterion_combobox_changed(cb)
  log.debug { 'changed' }
  @filter_books_mode = cb.active
  @filter_entry.text.strip!
  @iconview.freeze
  @filtered_model.refilter
  @iconview.unfreeze
end

#on_deleteObject



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/alexandria/ui/callbacks.rb', line 222

def on_delete(*)
  library = selected_library

  books = if selected_books.empty?
            nil
          else
            selected_books
          end
  # books = @library_listview.focus? ? nil : selected_books
  is_smart = library.is_a?(SmartLibrary)
  last_library = (@libraries.all_regular_libraries.length == 1)
  if books.nil? && !is_smart && last_library
    log.warn { 'Attempted to delete last library, fix GUI' }
    return
  end
  if library.empty? || ReallyDeleteDialog.new(@main_app,
                                              library,
                                              books).ok?
    undoable_delete(library, books)
  end
end

#on_deselect_allObject



191
192
193
194
195
196
197
198
199
# File 'lib/alexandria/ui/callbacks.rb', line 191

def on_deselect_all(*)
  log.debug { 'on_deselect_all' }
  case @notebook.page
  when 0
    @iconview.unselect_all
  when 1
    @listview.selection.unselect_all
  end
end

#on_exportObject



123
124
125
126
127
128
129
130
131
# File 'lib/alexandria/ui/callbacks.rb', line 123

def on_export(*)
  ExportDialog.new(@main_app, selected_library, library_sort_order)
  # FIXME: Remove this hack and fix the underlying problem.
rescue => ex
  log.error { "problem with immediate export #{ex} try again" }
  ErrorDialog.new(@main_app, _('Export failed'),
                  _('Try letting this library load ' \
                    'completely before exporting.'))
end

#on_helpObject



265
266
267
# File 'lib/alexandria/ui/callbacks.rb', line 265

def on_help(*)
  Alexandria::UI.display_help(@main_app)
end

#on_importObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/alexandria/ui/callbacks.rb', line 64

def on_import(*)
  ImportDialog.new(@main_app) do |library, bad_isbns, failed_isbns|
    unless bad_isbns.empty?
      log.debug { 'bad_isbn' }
      message = _('The following lines are not valid ISBNs and were not imported:')
      bad_isbn_warn = BadIsbnsDialog.new(@main_app, message, bad_isbns)
      bad_isbn_warn.signal_connect('response') { bad_isbn_warn.destroy }
    end
    unless failed_isbns.nil? || failed_isbns.empty?
      log.debug { "failed lookup of #{failed_isbns.size} ISBNs" }
      message = _('Books could not be found for the following ISBNs:')
      failed_lookup = BadIsbnsDialog.new(@main_app, message, failed_isbns)
      failed_lookup.signal_connect('response') { failed_lookup.destroy }
    end
    @libraries.add_library(library)
    append_library(library, true)
    setup_move_actions
  end
end

#on_newObject



27
28
29
30
31
32
33
34
# File 'lib/alexandria/ui/callbacks.rb', line 27

def on_new(*)
  name = Library.generate_new_name(@libraries.all_libraries)
  library = Library.load(name)
  @libraries.add_library(library)
  append_library(library, true)
  setup_move_actions
  library.add_observer(self)
end

#on_new_smartObject



36
37
38
39
40
41
42
43
# File 'lib/alexandria/ui/callbacks.rb', line 36

def on_new_smart(*)
  NewSmartLibraryDialog.new(@main_app) do |smart_library|
    smart_library.refilter
    @libraries.add_library(smart_library)
    append_library(smart_library, true)
    smart_library.save
  end
end

#on_preferencesObject



255
256
257
258
259
# File 'lib/alexandria/ui/callbacks.rb', line 255

def on_preferences(*)
  PreferencesDialog.new(@main_app) do
    @listview_manager.setup_listview_columns_visibility
  end
end

#on_propertiesObject



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/alexandria/ui/callbacks.rb', line 145

def on_properties(*)
  if @library_listview.focus? || selected_books.empty?
    library = selected_library
    if library.is_a?(SmartLibrary)
      SmartLibraryPropertiesDialog.new(@main_app, library) do
        library.refilter
        refresh_books
      end
    end
  else
    books = selected_books
    if books.length == 1
      book = books.first
      BookPropertiesDialog.new(@main_app,
                               selected_library,
                               book) # { |modified_book| }
    end
  end
end

#on_quitObject



165
166
167
168
169
170
171
# File 'lib/alexandria/ui/callbacks.rb', line 165

def on_quit(*)
  save_preferences
  Gtk.main_quit
  # @libraries.really_save_all_books
  @libraries.really_delete_deleted_libraries
  @libraries.all_regular_libraries.each(&:really_delete_deleted_books)
end

#on_redoObject



177
178
179
# File 'lib/alexandria/ui/callbacks.rb', line 177

def on_redo(*)
  UndoManager.instance.redo!
end

#on_renameObject



215
216
217
218
219
220
# File 'lib/alexandria/ui/callbacks.rb', line 215

def on_rename(*)
  iter = @library_listview.selection.selected
  @library_listview.set_cursor(iter.path,
                               @library_listview.get_column(0),
                               true)
end

#on_reverse_order(action) ⇒ Object



293
294
295
296
297
298
# File 'lib/alexandria/ui/callbacks.rb', line 293

def on_reverse_order(action)
  log.debug { 'on_reverse_order' }
  Preferences.instance.reverse_icons = action.active?
  Preferences.instance.save!
  setup_books_iconview_sorting
end

#on_searchObject



251
252
253
# File 'lib/alexandria/ui/callbacks.rb', line 251

def on_search(*)
  @filter_entry.grab_focus
end

#on_select_allObject



181
182
183
184
185
186
187
188
189
# File 'lib/alexandria/ui/callbacks.rb', line 181

def on_select_all(*)
  log.debug { 'on_select_all' }
  case @notebook.page
  when 0
    @iconview.select_all
  when 1
    @listview.selection.select_all
  end
end

#on_set_ratingObject



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/alexandria/ui/callbacks.rb', line 201

def on_set_rating
  Book::VALID_RATINGS.map do |rating|
    proc do
      books = selected_books
      library = selected_library
      books.each do |book|
        log.debug { "set #{book.title} rating to #{rating}" }
        book.rating = rating
        library.save(book)
      end
    end
  end
end

#on_submit_bug_reportObject



261
262
263
# File 'lib/alexandria/ui/callbacks.rb', line 261

def on_submit_bug_report(*)
  open_web_browser(BUGREPORT_URL)
end

#on_toolbar_filter_entry_changed(_entry) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/alexandria/ui/callbacks.rb', line 106

def on_toolbar_filter_entry_changed(_entry)
  log.debug { 'changed' }
  @filter_entry.text.strip!
  @iconview.freeze
  @filtered_model.refilter
  @iconview.unfreeze
end

#on_toolbar_view_as_changed(cb) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/alexandria/ui/callbacks.rb', line 90

def on_toolbar_view_as_changed(cb)
  log.debug { 'changed' }
  action = case cb.active
           when 0
             @actiongroup['AsIcons']
           when 1
             @actiongroup['AsList']
           end
  action.active = true
end

#on_undoObject



173
174
175
# File 'lib/alexandria/ui/callbacks.rb', line 173

def on_undo(*)
  UndoManager.instance.undo!
end

#on_view_sidepane(action) ⇒ Object



278
279
280
281
# File 'lib/alexandria/ui/callbacks.rb', line 278

def on_view_sidepane(action)
  log.debug { 'on_view_sidepane' }
  @paned.child1.visible = action.active?
end

#on_view_statusbar(action) ⇒ Object



288
289
290
291
# File 'lib/alexandria/ui/callbacks.rb', line 288

def on_view_statusbar(action)
  log.debug { 'on_view_statusbar' }
  @appbar.visible = action.active?
end

#on_view_toolbar(action) ⇒ Object



283
284
285
286
# File 'lib/alexandria/ui/callbacks.rb', line 283

def on_view_toolbar(action)
  log.debug { 'on_view_toolbar' }
  @toolbar.visible = action.active?
end

#on_window_destroy(_window) ⇒ Object



101
102
103
104
# File 'lib/alexandria/ui/callbacks.rb', line 101

def on_window_destroy(_window)
  log.debug { 'destroy' }
  @actiongroup['Quit'].activate
end

#on_window_state_event(_window, event) ⇒ Object



84
85
86
87
88
# File 'lib/alexandria/ui/callbacks.rb', line 84

def on_window_state_event(_window, event)
  log.debug { 'window-state-event' }
  @maximized = event.new_window_state == :maximized if event.is_a?(Gdk::EventWindowState)
  log.debug { 'end window-state-event' }
end