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
@@ -13,7 +13,7 @@ module Alexandria
|
|
13
13
|
|
14
14
|
def on_new(*)
|
15
15
|
name = Library.generate_new_name(@libraries.all_libraries)
|
16
|
-
library =
|
16
|
+
library = @libraries.library_store.load_library(name)
|
17
17
|
@libraries.add_library(library)
|
18
18
|
append_library(library, true)
|
19
19
|
setup_move_actions
|
@@ -21,17 +21,17 @@ module Alexandria
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def on_new_smart(*)
|
24
|
-
NewSmartLibraryDialog.new(@main_app).acquire
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
smart_library = NewSmartLibraryDialog.new(@main_app).acquire or return
|
25
|
+
|
26
|
+
smart_library.refilter
|
27
|
+
@libraries.add_library(smart_library)
|
28
|
+
append_library(smart_library, true)
|
29
|
+
smart_library.save
|
30
30
|
end
|
31
31
|
|
32
32
|
def on_add_book(*)
|
33
33
|
log.info { "on_add_book" }
|
34
|
-
NewBookDialog.new(@main_app, selected_library) do |_books, library, is_new|
|
34
|
+
dialog = NewBookDialog.new(@main_app, selected_library) do |_books, library, is_new|
|
35
35
|
if is_new
|
36
36
|
append_library(library, true)
|
37
37
|
setup_move_actions
|
@@ -39,13 +39,15 @@ module Alexandria
|
|
39
39
|
select_library(library)
|
40
40
|
end
|
41
41
|
end
|
42
|
+
dialog.show
|
42
43
|
end
|
43
44
|
|
44
45
|
def on_add_book_manual(*)
|
45
46
|
library = selected_library
|
46
|
-
NewBookDialogManual.new(@main_app, library) do |_book|
|
47
|
+
dialog = NewBookDialogManual.new(@main_app, library) do |_book|
|
47
48
|
refresh_books
|
48
49
|
end
|
50
|
+
dialog.show
|
49
51
|
end
|
50
52
|
|
51
53
|
def on_import(*)
|
@@ -53,14 +55,12 @@ module Alexandria
|
|
53
55
|
unless bad_isbns.empty?
|
54
56
|
log.debug { "bad_isbn" }
|
55
57
|
message = _("The following lines are not valid ISBNs and were not imported:")
|
56
|
-
|
57
|
-
bad_isbn_warn.signal_connect("response") { bad_isbn_warn.destroy }
|
58
|
+
BadIsbnsDialog.new(@main_app, message, bad_isbns).show
|
58
59
|
end
|
59
60
|
unless failed_isbns.nil? || failed_isbns.empty?
|
60
61
|
log.debug { "failed lookup of #{failed_isbns.size} ISBNs" }
|
61
62
|
message = _("Books could not be found for the following ISBNs:")
|
62
|
-
|
63
|
-
failed_lookup.signal_connect("response") { failed_lookup.destroy }
|
63
|
+
BadIsbnsDialog.new(@main_app, message, failed_isbns).show
|
64
64
|
end
|
65
65
|
@libraries.add_library(library)
|
66
66
|
append_library(library, true)
|
@@ -76,9 +76,9 @@ module Alexandria
|
|
76
76
|
log.debug { "end window-state-event" }
|
77
77
|
end
|
78
78
|
|
79
|
-
def on_toolbar_view_as_changed(
|
79
|
+
def on_toolbar_view_as_changed(widget)
|
80
80
|
log.debug { "changed" }
|
81
|
-
action = case
|
81
|
+
action = case widget.active
|
82
82
|
when 0
|
83
83
|
@actiongroup["AsIcons"]
|
84
84
|
when 1
|
@@ -100,9 +100,9 @@ module Alexandria
|
|
100
100
|
@iconview.unfreeze
|
101
101
|
end
|
102
102
|
|
103
|
-
def on_criterion_combobox_changed(
|
103
|
+
def on_criterion_combobox_changed(widget)
|
104
104
|
log.debug { "changed" }
|
105
|
-
@filter_books_mode =
|
105
|
+
@filter_books_mode = widget.active
|
106
106
|
@filter_entry.text.strip!
|
107
107
|
@iconview.freeze
|
108
108
|
@filtered_model.refilter
|
@@ -114,22 +114,25 @@ module Alexandria
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def on_acquire(*)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
117
|
+
dialog =
|
118
|
+
AcquireDialog.new(@main_app, selected_library) do |_books, library, is_new|
|
119
|
+
if is_new
|
120
|
+
append_library(library, true)
|
121
|
+
setup_move_actions
|
122
|
+
elsif selected_library != library
|
123
|
+
select_library(library)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
dialog.show
|
126
127
|
end
|
127
128
|
|
128
129
|
def on_properties(*)
|
129
130
|
if @library_listview.focus? || selected_books.empty?
|
130
131
|
library = selected_library
|
131
132
|
if library.is_a?(SmartLibrary)
|
132
|
-
SmartLibraryPropertiesDialog.new(@main_app, library).acquire
|
133
|
+
success = SmartLibraryPropertiesDialog.new(@main_app, library).acquire
|
134
|
+
|
135
|
+
if success
|
133
136
|
library.refilter
|
134
137
|
refresh_books
|
135
138
|
end
|
@@ -138,9 +141,10 @@ module Alexandria
|
|
138
141
|
books = selected_books
|
139
142
|
if books.length == 1
|
140
143
|
book = books.first
|
141
|
-
BookPropertiesDialog.new(@main_app,
|
142
|
-
|
143
|
-
|
144
|
+
dialog = BookPropertiesDialog.new(@main_app,
|
145
|
+
selected_library,
|
146
|
+
book)
|
147
|
+
dialog.show
|
144
148
|
end
|
145
149
|
end
|
146
150
|
end
|
@@ -197,9 +201,9 @@ module Alexandria
|
|
197
201
|
|
198
202
|
def on_rename(*)
|
199
203
|
iter = @library_listview.selection.selected
|
200
|
-
@library_listview.
|
201
|
-
|
202
|
-
|
204
|
+
column = @library_listview.get_column(0)
|
205
|
+
cell = column.cells.last
|
206
|
+
@library_listview.set_cursor_on_cell(iter.path, column, cell, true)
|
203
207
|
end
|
204
208
|
|
205
209
|
def on_delete(*)
|
@@ -236,9 +240,10 @@ module Alexandria
|
|
236
240
|
end
|
237
241
|
|
238
242
|
def on_preferences(*)
|
239
|
-
PreferencesDialog.new(@main_app) do
|
243
|
+
dialog = PreferencesDialog.new(@main_app) do
|
240
244
|
@listview_manager.setup_listview_columns_visibility
|
241
245
|
end
|
246
|
+
dialog.show
|
242
247
|
end
|
243
248
|
|
244
249
|
def on_submit_bug_report(*)
|
@@ -276,90 +281,36 @@ module Alexandria
|
|
276
281
|
end
|
277
282
|
|
278
283
|
def connect_signals
|
279
|
-
# rubocop:disable Layout/LineLength
|
280
|
-
standard_actions = [
|
281
|
-
["LibraryMenu", nil, _("_Library")],
|
282
|
-
["New", Gtk::Stock::NEW, _("_New Library"), "<control>L", _("Create a new library"), method(:on_new)],
|
283
|
-
["NewSmart", nil, _("New _Smart Library..."), "<control><shift>L", _("Create a new smart library"), method(:on_new_smart)],
|
284
|
-
["AddBook", Gtk::Stock::ADD, _("_Add Book..."), "<control>N", _("Add a new book from the Internet"), method(:on_add_book)],
|
285
|
-
["AddBookManual", nil, _("Add Book _Manually..."), "<control><shift>N", _("Add a new book manually"), method(:on_add_book_manual)],
|
286
|
-
["Import", nil, _("_Import..."), "<control>I", _("Import a library"), method(:on_import)],
|
287
|
-
["Export", nil, _("_Export..."), "<control><shift>E", _("Export the selected library"), method(:on_export)],
|
288
|
-
["Acquire", nil, _("A_cquire from Scanner..."), "<control><shift>S", _("Acquire books from a scanner"), method(:on_acquire)],
|
289
|
-
["Properties", Gtk::Stock::PROPERTIES, _("_Properties"), nil, _("Edit the properties of the selected book"), method(:on_properties)],
|
290
|
-
["Quit", Gtk::Stock::QUIT, _("_Quit"), "<control>Q", _("Quit the program"), method(:on_quit)],
|
291
|
-
["EditMenu", nil, _("_Edit")],
|
292
|
-
["Undo", Gtk::Stock::UNDO, _("_Undo"), "<control>Z", _("Undo the last action"), method(:on_undo)],
|
293
|
-
["Redo", Gtk::Stock::REDO, _("_Redo"), "<control><shift>Z", _("Redo the undone action"), method(:on_redo)],
|
294
|
-
["SelectAll", nil, _("_Select All"), "<control>A", _("Select all visible books"), method(:on_select_all)],
|
295
|
-
["DeselectAll", nil, _("Dese_lect All"), "<control><shift>A", _("Deselect everything"), method(:on_deselect_all)],
|
296
|
-
["SetRating", nil, _("My _Rating")],
|
297
|
-
["SetRating0", nil, _("None"), nil, nil, proc { on_set_rating[0].call }],
|
298
|
-
["SetRating1", nil, _("One Star"), nil, nil, proc { on_set_rating[1].call }],
|
299
|
-
["SetRating2", nil, _("Two Stars"), nil, nil, proc { on_set_rating[2].call }],
|
300
|
-
["SetRating3", nil, _("Three Stars"), nil, nil, proc { on_set_rating[3].call }],
|
301
|
-
["SetRating4", nil, _("Four Stars"), nil, nil, proc { on_set_rating[4].call }],
|
302
|
-
["SetRating5", nil, _("Five Stars"), nil, nil, proc { on_set_rating[5].call }],
|
303
|
-
["Move", nil, _("_Move")],
|
304
|
-
["Rename", nil, _("_Rename"), nil, nil, method(:on_rename)],
|
305
|
-
["Delete", Gtk::Stock::DELETE, _("_Delete"), "Delete", _("Delete the selected books or library"), method(:on_delete)],
|
306
|
-
["Search", Gtk::Stock::FIND, _("_Search"), "<control>F", _("Filter books"), method(:on_search)],
|
307
|
-
["ClearSearchResult", Gtk::Stock::CLEAR, _("_Clear Results"), "<control><alt>B", _("Clear the search results"), method(:on_clear_search_results)],
|
308
|
-
["Preferences", Gtk::Stock::PREFERENCES, _("_Preferences"), "<control>O", _("Change Alexandria's settings"), method(:on_preferences)],
|
309
|
-
["ViewMenu", nil, _("_View")],
|
310
|
-
["ArrangeIcons", nil, _("Arran_ge Icons")],
|
311
|
-
["OnlineInformation", nil, _("Display Online _Information")],
|
312
|
-
|
313
|
-
["HelpMenu", nil, _("_Help")],
|
314
|
-
["SubmitBugReport", Gtk::Stock::EDIT, _("Submit _Bug Report"), nil, _("Submit a bug report to the developers"), method(:on_submit_bug_report)],
|
315
|
-
["Help", Gtk::Stock::HELP, _("Contents"), "F1", _("View Alexandria's manual"), method(:on_help)],
|
316
|
-
["About", Gtk::Stock::ABOUT, _("_About"), nil, _("Show information about Alexandria"), method(:on_about)],
|
317
|
-
]
|
318
|
-
|
319
|
-
toggle_actions = [
|
320
|
-
["Sidepane", nil, _("Side _Pane"), "F9", nil, method(:on_view_sidepane), true],
|
321
|
-
["Toolbar", nil, _("_Toolbar"), nil, nil, method(:on_view_toolbar), true],
|
322
|
-
["Statusbar", nil, _("_Statusbar"), nil, nil, method(:on_view_statusbar), true],
|
323
|
-
["ReversedOrder", nil, _("Re_versed Order"), nil, nil, method(:on_reverse_order), false],
|
324
|
-
]
|
325
|
-
|
326
|
-
view_as_actions = [
|
327
|
-
["AsIcons", nil, _("View as _Icons"), nil, nil, 0],
|
328
|
-
["AsList", nil, _("View as _List"), nil, nil, 1]
|
329
|
-
]
|
330
|
-
|
331
|
-
arrange_icons_actions = [
|
332
|
-
["ByTitle", nil, _("By _Title"), nil, nil, 0],
|
333
|
-
["ByAuthors", nil, _("By _Authors"), nil, nil, 1],
|
334
|
-
["ByISBN", nil, _("By _ISBN"), nil, nil, 2],
|
335
|
-
["ByPublisher", nil, _("By _Publisher"), nil, nil, 3],
|
336
|
-
["ByEdition", nil, _("By _Binding"), nil, nil, 4],
|
337
|
-
["ByRating", nil, _("By _Rating"), nil, nil, 5]
|
338
|
-
]
|
339
|
-
# rubocop:enable Layout/LineLength
|
340
|
-
|
341
|
-
providers_actions = BookProviders.map do |provider|
|
342
|
-
[provider.action_name, Gtk::Stock::JUMP_TO,
|
343
|
-
_("At _%s") % provider.fullname, nil, nil,
|
344
|
-
proc { open_web_browser(provider.url(selected_books.first)) }]
|
345
|
-
end
|
346
|
-
|
347
284
|
log.debug { "Adding actions to @actiongroup" }
|
348
285
|
|
349
286
|
@actiongroup = Gtk::ActionGroup.new("actions")
|
350
287
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
288
|
+
connect_standard_actions
|
289
|
+
connect_providers_actions
|
290
|
+
connect_toggle_actions
|
291
|
+
connect_view_actions
|
292
|
+
connect_arrange_icons_actions
|
293
|
+
end
|
294
|
+
|
295
|
+
private
|
296
|
+
|
297
|
+
def connect_standard_actions
|
298
|
+
connect_actions standard_actions
|
299
|
+
end
|
300
|
+
|
301
|
+
def connect_providers_actions
|
302
|
+
connect_actions providers_actions
|
303
|
+
end
|
356
304
|
|
357
|
-
|
305
|
+
def connect_actions(actions)
|
306
|
+
actions.each do |name, stock_id, label, accelerator, tooltip, callback|
|
358
307
|
action = Gtk::Action.new(name, label: label, tooltip: tooltip, stock_id: stock_id)
|
359
308
|
@actiongroup.add_action_with_accel(action, accelerator)
|
360
309
|
action.signal_connect("activate", &callback) if callback
|
361
310
|
end
|
311
|
+
end
|
362
312
|
|
313
|
+
def connect_toggle_actions
|
363
314
|
toggle_actions
|
364
315
|
.each do |name, stock_id, label, accelerator, tooltip, callback, is_active|
|
365
316
|
action = Gtk::ToggleAction.new(name, label: label, tooltip: tooltip,
|
@@ -368,18 +319,10 @@ module Alexandria
|
|
368
319
|
@actiongroup.add_action_with_accel(action, accelerator)
|
369
320
|
action.signal_connect("toggled", &callback) if callback
|
370
321
|
end
|
322
|
+
end
|
371
323
|
|
372
|
-
|
373
|
-
|
374
|
-
action = Gtk::RadioAction.new(name, value, label: label, tooltip: tooltip,
|
375
|
-
stock_id: stock_id)
|
376
|
-
if first_action
|
377
|
-
action.join_group first_action
|
378
|
-
else
|
379
|
-
first_action = action
|
380
|
-
end
|
381
|
-
@actiongroup.add_action_with_accel(action, accelerator)
|
382
|
-
end
|
324
|
+
def connect_view_actions
|
325
|
+
first_action = connect_radio_actions view_as_actions
|
383
326
|
|
384
327
|
first_action.signal_connect "changed" do |_action, current, _user_data|
|
385
328
|
@notebook.page = current.current_value
|
@@ -388,9 +331,20 @@ module Alexandria
|
|
388
331
|
@toolbar_view_as.active = current.current_value
|
389
332
|
end
|
390
333
|
end
|
334
|
+
end
|
391
335
|
|
336
|
+
def connect_arrange_icons_actions
|
337
|
+
first_action = connect_radio_actions arrange_icons_actions
|
338
|
+
|
339
|
+
first_action.signal_connect "changed" do |_action, current, _user_data|
|
340
|
+
@prefs.arrange_icons_mode = current.current_value
|
341
|
+
setup_books_iconview_sorting
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def connect_radio_actions(actions)
|
392
346
|
first_action = nil
|
393
|
-
|
347
|
+
actions.each do |name, stock_id, label, accelerator, tooltip, value|
|
394
348
|
action = Gtk::RadioAction.new(name, value, label: label, tooltip: tooltip,
|
395
349
|
stock_id: stock_id)
|
396
350
|
if first_action
|
@@ -400,12 +354,79 @@ module Alexandria
|
|
400
354
|
end
|
401
355
|
@actiongroup.add_action_with_accel(action, accelerator)
|
402
356
|
end
|
357
|
+
first_action
|
358
|
+
end
|
403
359
|
|
404
|
-
|
405
|
-
|
406
|
-
|
360
|
+
def standard_actions
|
361
|
+
# rubocop:disable Layout/LineLength
|
362
|
+
[["LibraryMenu", nil, _("_Library")],
|
363
|
+
["New", Gtk::Stock::NEW, _("_New Library"), "<control>L", _("Create a new library"), method(:on_new)],
|
364
|
+
["NewSmart", nil, _("New _Smart Library..."), "<control><shift>L", _("Create a new smart library"), method(:on_new_smart)],
|
365
|
+
["AddBook", Gtk::Stock::ADD, _("_Add Book..."), "<control>N", _("Add a new book from the Internet"), method(:on_add_book)],
|
366
|
+
["AddBookManual", nil, _("Add Book _Manually..."), "<control><shift>N", _("Add a new book manually"), method(:on_add_book_manual)],
|
367
|
+
["Import", nil, _("_Import..."), "<control>I", _("Import a library"), method(:on_import)],
|
368
|
+
["Export", nil, _("_Export..."), "<control><shift>E", _("Export the selected library"), method(:on_export)],
|
369
|
+
["Acquire", nil, _("A_cquire from Scanner..."), "<control><shift>S", _("Acquire books from a scanner"), method(:on_acquire)],
|
370
|
+
["Properties", Gtk::Stock::PROPERTIES, _("_Properties"), nil, _("Edit the properties of the selected book"), method(:on_properties)],
|
371
|
+
["Quit", Gtk::Stock::QUIT, _("_Quit"), "<control>Q", _("Quit the program"), method(:on_quit)],
|
372
|
+
["EditMenu", nil, _("_Edit")],
|
373
|
+
["Undo", Gtk::Stock::UNDO, _("_Undo"), "<control>Z", _("Undo the last action"), method(:on_undo)],
|
374
|
+
["Redo", Gtk::Stock::REDO, _("_Redo"), "<control><shift>Z", _("Redo the undone action"), method(:on_redo)],
|
375
|
+
["SelectAll", nil, _("_Select All"), "<control>A", _("Select all visible books"), method(:on_select_all)],
|
376
|
+
["DeselectAll", nil, _("Dese_lect All"), "<control><shift>A", _("Deselect everything"), method(:on_deselect_all)],
|
377
|
+
["SetRating", nil, _("My _Rating")],
|
378
|
+
["SetRating0", nil, _("None"), nil, nil, proc { on_set_rating[0].call }],
|
379
|
+
["SetRating1", nil, _("One Star"), nil, nil, proc { on_set_rating[1].call }],
|
380
|
+
["SetRating2", nil, _("Two Stars"), nil, nil, proc { on_set_rating[2].call }],
|
381
|
+
["SetRating3", nil, _("Three Stars"), nil, nil, proc { on_set_rating[3].call }],
|
382
|
+
["SetRating4", nil, _("Four Stars"), nil, nil, proc { on_set_rating[4].call }],
|
383
|
+
["SetRating5", nil, _("Five Stars"), nil, nil, proc { on_set_rating[5].call }],
|
384
|
+
["Move", nil, _("_Move")],
|
385
|
+
["Rename", nil, _("_Rename"), nil, nil, method(:on_rename)],
|
386
|
+
["Delete", Gtk::Stock::DELETE, _("_Delete"), "Delete", _("Delete the selected books or library"), method(:on_delete)],
|
387
|
+
["Search", Gtk::Stock::FIND, _("_Search"), "<control>F", _("Filter books"), method(:on_search)],
|
388
|
+
["ClearSearchResult", Gtk::Stock::CLEAR, _("_Clear Results"), "<control><alt>B", _("Clear the search results"), method(:on_clear_search_results)],
|
389
|
+
["Preferences", Gtk::Stock::PREFERENCES, _("_Preferences"), "<control>O", _("Change Alexandria's settings"), method(:on_preferences)],
|
390
|
+
["ViewMenu", nil, _("_View")],
|
391
|
+
["ArrangeIcons", nil, _("Arran_ge Icons")],
|
392
|
+
["OnlineInformation", nil, _("Display Online _Information")],
|
393
|
+
|
394
|
+
["HelpMenu", nil, _("_Help")],
|
395
|
+
["SubmitBugReport", Gtk::Stock::EDIT, _("Submit _Bug Report"), nil, _("Submit a bug report to the developers"), method(:on_submit_bug_report)],
|
396
|
+
["Help", Gtk::Stock::HELP, _("Contents"), "F1", _("View Alexandria's manual"), method(:on_help)],
|
397
|
+
["About", Gtk::Stock::ABOUT, _("_About"), nil, _("Show information about Alexandria"), method(:on_about)]]
|
398
|
+
# rubocop:enable Layout/LineLength
|
399
|
+
end
|
400
|
+
|
401
|
+
def providers_actions
|
402
|
+
BookProviders.list.map do |provider|
|
403
|
+
[provider.action_name, Gtk::Stock::JUMP_TO,
|
404
|
+
_("At _%s") % provider.fullname, nil, nil,
|
405
|
+
proc { open_web_browser(provider.url(selected_books.first)) }]
|
407
406
|
end
|
408
407
|
end
|
408
|
+
|
409
|
+
def toggle_actions
|
410
|
+
[["Sidepane", nil, _("Side_pane"), "F9", nil, method(:on_view_sidepane), true],
|
411
|
+
["Toolbar", nil, _("_Toolbar"), nil, nil, method(:on_view_toolbar), true],
|
412
|
+
["Statusbar", nil, _("_Statusbar"), nil, nil, method(:on_view_statusbar), true],
|
413
|
+
["ReversedOrder", nil, _("Re_versed Order"), nil, nil,
|
414
|
+
method(:on_reverse_order), false]]
|
415
|
+
end
|
416
|
+
|
417
|
+
def view_as_actions
|
418
|
+
[["AsIcons", nil, _("View as _Icons"), nil, nil, 0],
|
419
|
+
["AsList", nil, _("View as _List"), nil, nil, 1]]
|
420
|
+
end
|
421
|
+
|
422
|
+
def arrange_icons_actions
|
423
|
+
[["ByTitle", nil, _("By _Title"), nil, nil, 0],
|
424
|
+
["ByAuthors", nil, _("By _Authors"), nil, nil, 1],
|
425
|
+
["ByISBN", nil, _("By _ISBN"), nil, nil, 2],
|
426
|
+
["ByPublisher", nil, _("By _Publisher"), nil, nil, 3],
|
427
|
+
["ByEdition", nil, _("By _Binding"), nil, nil, 4],
|
428
|
+
["ByRating", nil, _("By _Rating"), nil, nil, 5]]
|
429
|
+
end
|
409
430
|
end
|
410
431
|
end
|
411
432
|
end
|
@@ -44,11 +44,7 @@ module Alexandria
|
|
44
44
|
cur_tag = key.split(",").last.strip
|
45
45
|
if cur_tag.size >= min
|
46
46
|
begin
|
47
|
-
|
48
|
-
true
|
49
|
-
else
|
50
|
-
false
|
51
|
-
end
|
47
|
+
/^#{cur_tag}/.match?(iter[0])
|
52
48
|
rescue StandardError
|
53
49
|
false
|
54
50
|
end
|
@@ -164,7 +160,7 @@ module Alexandria
|
|
164
160
|
editions << book.edition
|
165
161
|
borrowers << book.loaned_to
|
166
162
|
# TODO: Ensure #tags is always an array
|
167
|
-
(book.tags
|
163
|
+
tags.concat(book.tags) if book.tags
|
168
164
|
end
|
169
165
|
end
|
170
166
|
|
@@ -20,7 +20,7 @@ module Alexandria
|
|
20
20
|
_("A file named '%s' already exists. Do you want " \
|
21
21
|
"to replace it with the one you are generating?") % filename)
|
22
22
|
# FIXME: Should accept just :cancel
|
23
|
-
|
23
|
+
dialog.default_response = Gtk::ResponseType::CANCEL
|
24
24
|
end
|
25
25
|
|
26
26
|
def erase?
|
@@ -15,13 +15,13 @@ module Alexandria
|
|
15
15
|
def initialize(parent, library, book)
|
16
16
|
super(parent,
|
17
17
|
format(_("The book '%s' already exists in '%s'. Would you like " \
|
18
|
-
|
18
|
+
"to replace it?"), book.title, library.name),
|
19
19
|
Gtk::Stock::DIALOG_QUESTION,
|
20
20
|
[[_("_Skip"), Gtk::ResponseType::CANCEL],
|
21
21
|
[_("_Replace"), Gtk::ResponseType::OK]],
|
22
22
|
_("If you replace the existing book, its contents will " \
|
23
23
|
"be overwritten."))
|
24
|
-
|
24
|
+
dialog.default_response = Gtk::ResponseType::CANCEL
|
25
25
|
end
|
26
26
|
|
27
27
|
def replace?
|
@@ -13,7 +13,7 @@ module Alexandria
|
|
13
13
|
super(parent, title, Gtk::Stock::DIALOG_ERROR,
|
14
14
|
[[Gtk::Stock::OK, :ok]], message)
|
15
15
|
# FIXME: Should accept just :ok
|
16
|
-
|
16
|
+
dialog.default_response = Gtk::ResponseType::OK
|
17
17
|
end
|
18
18
|
|
19
19
|
def display
|
@@ -10,7 +10,7 @@ require "alexandria/ui/error_dialog"
|
|
10
10
|
|
11
11
|
module Alexandria
|
12
12
|
module UI
|
13
|
-
class ExportDialog
|
13
|
+
class ExportDialog
|
14
14
|
include GetText
|
15
15
|
extend GetText
|
16
16
|
GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
|
@@ -18,17 +18,17 @@ module Alexandria
|
|
18
18
|
FORMATS = Alexandria::ExportFormat.all
|
19
19
|
THEMES = Alexandria::WebTheme.all
|
20
20
|
|
21
|
-
|
22
|
-
@export_dialog = Gtk::FileChooserDialog.new(title: _("Export '%s'") % library.name,
|
23
|
-
parent: parent,
|
24
|
-
action: :save,
|
25
|
-
buttons: [[Gtk::Stock::HELP, :help],
|
26
|
-
[Gtk::Stock::CANCEL, :cancel],
|
27
|
-
[_("_Export"), :accept]])
|
28
|
-
super(@export_dialog)
|
21
|
+
attr_reader :dialog
|
29
22
|
|
30
|
-
|
31
|
-
|
23
|
+
def initialize(parent, library, sort_order)
|
24
|
+
@dialog = Gtk::FileChooserDialog.new(title: _("Export '%s'") % library.name,
|
25
|
+
parent: parent,
|
26
|
+
action: :save,
|
27
|
+
buttons: [[Gtk::Stock::HELP, :help],
|
28
|
+
[Gtk::Stock::CANCEL, :cancel],
|
29
|
+
[_("_Export"), :accept]])
|
30
|
+
@dialog.current_name = library.name
|
31
|
+
@dialog.signal_connect("destroy") { @dialog.hide }
|
32
32
|
|
33
33
|
@parent = parent
|
34
34
|
@library = library
|
@@ -84,11 +84,11 @@ module Alexandria
|
|
84
84
|
grid.attach theme_label, 0, 1, 1, 1
|
85
85
|
grid.attach @theme_combo, 1, 1, 1, 1
|
86
86
|
grid.attach preview_image, 2, 0, 1, 3
|
87
|
-
set_extra_widget grid
|
87
|
+
@dialog.set_extra_widget grid
|
88
88
|
end
|
89
89
|
|
90
90
|
def perform
|
91
|
-
while ((response = run) != Gtk::ResponseType::CANCEL) &&
|
91
|
+
while ((response = dialog.run) != Gtk::ResponseType::CANCEL) &&
|
92
92
|
(response != Gtk::ResponseType::DELETE_EVENT)
|
93
93
|
|
94
94
|
if response == Gtk::ResponseType::HELP
|
@@ -98,21 +98,22 @@ module Alexandria
|
|
98
98
|
break if on_export(FORMATS[@types_combo.active],
|
99
99
|
THEMES[@theme_combo.active])
|
100
100
|
rescue StandardError => ex
|
101
|
-
ErrorDialog.new(@
|
101
|
+
ErrorDialog.new(@dialog, _("Export failed"), ex.message).display
|
102
|
+
break
|
102
103
|
end
|
103
104
|
end
|
104
105
|
end
|
105
|
-
destroy
|
106
|
+
dialog.destroy
|
106
107
|
end
|
107
108
|
|
108
109
|
private
|
109
110
|
|
110
111
|
def on_export(format, theme)
|
111
|
-
filename =
|
112
|
+
filename = dialog.filename
|
112
113
|
if format.ext
|
113
114
|
filename += "." + format.ext if File.extname(filename).empty?
|
114
115
|
if File.exist?(filename)
|
115
|
-
dialog = ConfirmEraseDialog.new(@
|
116
|
+
dialog = ConfirmEraseDialog.new(@dialog, filename)
|
116
117
|
return unless dialog.erase?
|
117
118
|
|
118
119
|
FileUtils.rm(filename)
|
@@ -125,7 +126,7 @@ module Alexandria
|
|
125
126
|
"file. A directory is needed for this " \
|
126
127
|
"operation. Please select a directory and " \
|
127
128
|
"try again.") % filename
|
128
|
-
ErrorDialog.new(@
|
129
|
+
ErrorDialog.new(@dialog, _("Not a directory"), msg).display
|
129
130
|
return
|
130
131
|
end
|
131
132
|
else
|
data/lib/alexandria/ui/icons.rb
CHANGED
@@ -4,41 +4,6 @@
|
|
4
4
|
#
|
5
5
|
# See the file README.md for authorship and licensing information.
|
6
6
|
|
7
|
-
class GdkPixbuf::Pixbuf
|
8
|
-
def tag(tag_pixbuf)
|
9
|
-
# Computes some tweaks.
|
10
|
-
tweak_x = tag_pixbuf.width / 3
|
11
|
-
tweak_y = tag_pixbuf.height / 3
|
12
|
-
|
13
|
-
# Creates the destination pixbuf.
|
14
|
-
new_pixbuf = GdkPixbuf::Pixbuf.new(colorspace: :rgb,
|
15
|
-
has_alpha: true,
|
16
|
-
bits_per_sample: 8,
|
17
|
-
width: width + tweak_x,
|
18
|
-
height: height + tweak_y)
|
19
|
-
|
20
|
-
# Fills with blank.
|
21
|
-
new_pixbuf.fill!(0)
|
22
|
-
|
23
|
-
# Copies the current pixbuf there (south-west).
|
24
|
-
copy_area(0, 0,
|
25
|
-
width, height,
|
26
|
-
new_pixbuf,
|
27
|
-
0, tweak_y)
|
28
|
-
|
29
|
-
# Copies the tag pixbuf there (north-est).
|
30
|
-
tag_pixbuf_x = width - (tweak_x * 2)
|
31
|
-
new_pixbuf.composite!(tag_pixbuf,
|
32
|
-
dest_x: 0, dest_y: 0,
|
33
|
-
dest_width: tag_pixbuf.width + tag_pixbuf_x,
|
34
|
-
dest_height: tag_pixbuf.height,
|
35
|
-
offset_x: tag_pixbuf_x, offset_y: 0,
|
36
|
-
scale_x: 1, scale_y: 1,
|
37
|
-
interpolation_type: :hyper, overall_alpha: 255)
|
38
|
-
new_pixbuf
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
7
|
module Alexandria
|
43
8
|
module UI
|
44
9
|
module Icons
|
@@ -53,7 +18,7 @@ module Alexandria
|
|
53
18
|
# Alexandria::UI::Icons namespace, e.g., Icons::STAR_SET
|
54
19
|
def self.load_icon_images
|
55
20
|
Dir.entries(ICONS_DIR).each do |file|
|
56
|
-
next unless
|
21
|
+
next unless file.end_with?(".png") # skip non '.png' files
|
57
22
|
|
58
23
|
# Don't use upcase and use tr instead
|
59
24
|
# For example in Turkish the upper case of 'i' is still 'i'.
|
@@ -77,13 +42,42 @@ module Alexandria
|
|
77
42
|
BOOK_ICON
|
78
43
|
end
|
79
44
|
|
45
|
+
def self.tag_icon(icon_pixbuf, tag_pixbuf)
|
46
|
+
# Computes some tweaks.
|
47
|
+
tweak_x = tag_pixbuf.width / 3
|
48
|
+
tweak_y = tag_pixbuf.height / 3
|
49
|
+
|
50
|
+
# Creates the destination pixbuf.
|
51
|
+
new_pixbuf = GdkPixbuf::Pixbuf.new(colorspace: :rgb,
|
52
|
+
has_alpha: true,
|
53
|
+
bits_per_sample: 8,
|
54
|
+
width: icon_pixbuf.width + tweak_x,
|
55
|
+
height: icon_pixbuf.height + tweak_y)
|
56
|
+
|
57
|
+
# Fills with blank.
|
58
|
+
new_pixbuf.fill!(0)
|
59
|
+
|
60
|
+
# Copies the current pixbuf there (south-west).
|
61
|
+
icon_pixbuf.copy_area(0, 0,
|
62
|
+
icon_pixbuf.width, icon_pixbuf.height,
|
63
|
+
new_pixbuf,
|
64
|
+
0, tweak_y)
|
65
|
+
|
66
|
+
# Copies the tag pixbuf there (north-est).
|
67
|
+
tag_pixbuf_x = icon_pixbuf.width - (tweak_x * 2)
|
68
|
+
new_pixbuf.composite!(tag_pixbuf,
|
69
|
+
dest_x: 0, dest_y: 0,
|
70
|
+
dest_width: tag_pixbuf.width + tag_pixbuf_x,
|
71
|
+
dest_height: tag_pixbuf.height,
|
72
|
+
offset_x: tag_pixbuf_x, offset_y: 0,
|
73
|
+
scale_x: 1, scale_y: 1,
|
74
|
+
interpolation_type: :hyper, overall_alpha: 255)
|
75
|
+
new_pixbuf
|
76
|
+
end
|
77
|
+
|
80
78
|
def self.blank?(filename)
|
81
79
|
pixbuf = GdkPixbuf::Pixbuf.new(file: filename)
|
82
80
|
(pixbuf.width == 1) && (pixbuf.height == 1)
|
83
|
-
rescue StandardError => ex
|
84
|
-
puts ex.message
|
85
|
-
puts ex.backtrace.join("\n> ")
|
86
|
-
true
|
87
81
|
end
|
88
82
|
end
|
89
83
|
end
|