alexandria-book-collection-manager 0.7.3 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.github/workflows/ruby.yml +77 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +86 -36
  6. data/.rubocop_todo.yml +58 -161
  7. data/.simplecov +5 -2
  8. data/CHANGELOG.md +56 -2
  9. data/Gemfile +4 -3
  10. data/INSTALL.md +23 -11
  11. data/README.md +52 -41
  12. data/Rakefile +78 -75
  13. data/alexandria-book-collection-manager.gemspec +50 -44
  14. data/bin/alexandria +12 -22
  15. data/doc/FAQ +1 -2
  16. data/doc/dependency_decisions.yml +27 -8
  17. data/lib/alexandria.rb +25 -23
  18. data/lib/alexandria/about.rb +50 -50
  19. data/lib/alexandria/book_providers.rb +86 -91
  20. data/lib/alexandria/book_providers/adlibris.rb +37 -74
  21. data/lib/alexandria/book_providers/amazon_aws.rb +94 -100
  22. data/lib/alexandria/book_providers/amazon_ecs_util.rb +289 -324
  23. data/lib/alexandria/book_providers/barnes_and_noble.rb +42 -42
  24. data/lib/alexandria/book_providers/douban.rb +25 -41
  25. data/lib/alexandria/book_providers/proxis.rb +34 -29
  26. data/lib/alexandria/book_providers/pseudomarc.rb +77 -85
  27. data/lib/alexandria/book_providers/siciliano.rb +60 -64
  28. data/lib/alexandria/book_providers/thalia_provider.rb +161 -0
  29. data/lib/alexandria/book_providers/web.rb +5 -5
  30. data/lib/alexandria/book_providers/worldcat.rb +66 -95
  31. data/lib/alexandria/book_providers/z3950.rb +153 -169
  32. data/lib/alexandria/config.rb +1 -1
  33. data/lib/alexandria/console.rb +3 -3
  34. data/lib/alexandria/default_preferences.rb +37 -0
  35. data/lib/alexandria/execution_queue.rb +13 -12
  36. data/lib/alexandria/export_format.rb +8 -8
  37. data/lib/alexandria/export_library.rb +128 -127
  38. data/lib/alexandria/import_library.rb +102 -126
  39. data/lib/alexandria/import_library_csv.rb +41 -41
  40. data/lib/alexandria/library_collection.rb +6 -5
  41. data/lib/alexandria/library_sort_order.rb +4 -2
  42. data/lib/alexandria/library_store.rb +39 -28
  43. data/lib/alexandria/logging.rb +10 -14
  44. data/lib/alexandria/models/book.rb +5 -4
  45. data/lib/alexandria/models/library.rb +63 -53
  46. data/lib/alexandria/net.rb +5 -6
  47. data/lib/alexandria/preferences.rb +66 -63
  48. data/lib/alexandria/scanners.rb +2 -2
  49. data/lib/alexandria/scanners/{cuecat.rb → cue_cat.rb} +17 -17
  50. data/lib/alexandria/scanners/keyboard.rb +8 -8
  51. data/lib/alexandria/smart_library.rb +110 -112
  52. data/lib/alexandria/ui.rb +15 -15
  53. data/lib/alexandria/ui/{dialogs/about_dialog.rb → about_dialog.rb} +2 -2
  54. data/lib/alexandria/ui/{dialogs/acquire_dialog.rb → acquire_dialog.rb} +108 -109
  55. data/lib/alexandria/ui/alert_dialog.rb +66 -0
  56. data/lib/alexandria/ui/{dialogs/bad_isbns_dialog.rb → bad_isbns_dialog.rb} +13 -9
  57. data/lib/alexandria/ui/{dialogs/barcode_animation.rb → barcode_animation.rb} +16 -15
  58. data/lib/alexandria/ui/{dialogs/book_properties_dialog.rb → book_properties_dialog.rb} +25 -38
  59. data/lib/alexandria/ui/{dialogs/book_properties_dialog_base.rb → book_properties_dialog_base.rb} +64 -157
  60. data/lib/alexandria/ui/builder_base.rb +1 -1
  61. data/lib/alexandria/ui/calendar_popup.rb +58 -0
  62. data/lib/alexandria/ui/callbacks.rb +187 -155
  63. data/lib/alexandria/ui/completion_models.rb +8 -22
  64. data/lib/alexandria/ui/confirm_erase_dialog.rb +33 -0
  65. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +34 -0
  66. data/lib/alexandria/ui/dndable.rb +7 -7
  67. data/lib/alexandria/ui/error_dialog.rb +25 -0
  68. data/lib/alexandria/ui/{dialogs/export_dialog.rb → export_dialog.rb} +37 -58
  69. data/lib/alexandria/ui/icons.rb +38 -43
  70. data/lib/alexandria/ui/iconview.rb +12 -10
  71. data/lib/alexandria/ui/iconview_tooltips.rb +41 -54
  72. data/lib/alexandria/ui/import_dialog.rb +157 -0
  73. data/lib/alexandria/ui/init.rb +30 -41
  74. data/lib/alexandria/ui/{dialogs/keep_bad_isbn_dialog.rb → keep_bad_isbn_dialog.rb} +9 -6
  75. data/lib/alexandria/ui/libraries_combo.rb +15 -14
  76. data/lib/alexandria/ui/listview.rb +69 -67
  77. data/lib/alexandria/ui/main_app.rb +24 -26
  78. data/lib/alexandria/ui/misc_dialogs.rb +10 -0
  79. data/lib/alexandria/ui/multi_drag_treeview.rb +8 -9
  80. data/lib/alexandria/ui/{dialogs/new_book_dialog.rb → new_book_dialog.rb} +113 -114
  81. data/lib/alexandria/ui/{dialogs/new_book_dialog_manual.rb → new_book_dialog_manual.rb} +22 -19
  82. data/lib/alexandria/ui/new_provider_dialog.rb +100 -0
  83. data/lib/alexandria/ui/new_smart_library_dialog.rb +74 -0
  84. data/lib/alexandria/ui/preferences_dialog.rb +313 -0
  85. data/lib/alexandria/ui/provider_preferences_base_dialog.rb +95 -0
  86. data/lib/alexandria/ui/provider_preferences_dialog.rb +35 -0
  87. data/lib/alexandria/ui/{dialogs/misc_dialogs.rb → really_delete_dialog.rb} +7 -28
  88. data/lib/alexandria/ui/{sidepane.rb → sidepane_manager.rb} +53 -48
  89. data/lib/alexandria/ui/skip_entry_dialog.rb +33 -0
  90. data/lib/alexandria/ui/smart_library_properties_dialog.rb +60 -0
  91. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +242 -0
  92. data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
  93. data/lib/alexandria/ui/sound.rb +11 -13
  94. data/lib/alexandria/ui/ui_manager.rb +216 -200
  95. data/lib/alexandria/version.rb +4 -19
  96. data/lib/alexandria/web_themes.rb +21 -21
  97. data/po/Makefile +2 -2
  98. data/po/cs.po +992 -875
  99. data/po/cy.po +961 -874
  100. data/po/de.po +990 -865
  101. data/po/el.po +989 -865
  102. data/po/es.po +985 -861
  103. data/po/fr.po +987 -867
  104. data/po/ga.po +908 -820
  105. data/po/gl.po +980 -860
  106. data/po/it.po +986 -864
  107. data/po/ja.po +969 -849
  108. data/po/mk.po +984 -860
  109. data/po/nb.po +979 -859
  110. data/po/nl.po +983 -860
  111. data/po/pl.po +1018 -971
  112. data/po/pt.po +988 -857
  113. data/po/pt_BR.po +983 -863
  114. data/po/ru.po +994 -871
  115. data/po/sk.po +989 -867
  116. data/po/sv.po +976 -856
  117. data/po/uk.po +972 -858
  118. data/po/zh_TW.po +974 -854
  119. data/schemas/alexandria.schemas +24 -2
  120. data/share/alexandria/glade/acquire_dialog__builder.glade +1 -1
  121. data/share/alexandria/glade/book_properties_dialog__builder.glade +1 -1
  122. data/share/alexandria/glade/main_app__builder.glade +6 -21
  123. data/share/alexandria/glade/new_book_dialog__builder.glade +1 -1
  124. data/share/alexandria/glade/preferences_dialog__builder.glade +1 -1
  125. data/share/gnome/help/alexandria/C/introduction.xml +0 -4
  126. data/share/gnome/help/alexandria/C/searching.xml +1 -1
  127. data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
  128. data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
  129. data/share/gnome/help/alexandria/fr/alexandria.xml +1 -1
  130. data/share/gnome/help/alexandria/ja/introduction.xml +0 -4
  131. data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
  132. data/spec/alexandria/book_providers/thalia_provider_spec.rb +119 -0
  133. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
  134. data/spec/alexandria/book_providers_spec.rb +62 -156
  135. data/spec/alexandria/book_spec.rb +12 -10
  136. data/spec/alexandria/console_spec.rb +6 -11
  137. data/spec/alexandria/export_library_spec.rb +47 -58
  138. data/spec/alexandria/library_spec.rb +121 -109
  139. data/spec/alexandria/library_store_spec.rb +8 -8
  140. data/spec/alexandria/preferences_spec.rb +44 -17
  141. data/spec/alexandria/scanners/cue_cat_spec.rb +52 -0
  142. data/spec/alexandria/smart_library_spec.rb +15 -15
  143. data/spec/alexandria/ui/about_dialog_spec.rb +14 -0
  144. data/spec/alexandria/ui/acquire_dialog_spec.rb +14 -0
  145. data/spec/alexandria/ui/alert_dialog_spec.rb +16 -0
  146. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +14 -0
  147. data/spec/alexandria/ui/book_properties_dialog_spec.rb +59 -0
  148. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +14 -0
  149. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +16 -0
  150. data/spec/alexandria/ui/error_dialog_spec.rb +14 -0
  151. data/spec/alexandria/ui/export_dialog_spec.rb +36 -0
  152. data/spec/alexandria/ui/icons_spec.rb +26 -0
  153. data/spec/alexandria/ui/iconview_spec.rb +7 -21
  154. data/spec/alexandria/ui/import_dialog_spec.rb +46 -0
  155. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +17 -0
  156. data/spec/alexandria/ui/main_app_spec.rb +7 -34
  157. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +51 -0
  158. data/spec/alexandria/ui/{dialogs/new_book_dialog_spec.rb → new_book_dialog_spec.rb} +4 -4
  159. data/spec/alexandria/ui/new_provider_dialog_spec.rb +30 -0
  160. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +39 -0
  161. data/spec/alexandria/ui/preferences_dialog_spec.rb +14 -0
  162. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +34 -0
  163. data/spec/alexandria/ui/really_delete_dialog_spec.rb +16 -0
  164. data/spec/alexandria/ui/sidepane_manager_spec.rb +15 -0
  165. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +14 -0
  166. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +49 -0
  167. data/spec/alexandria/ui/sound_spec.rb +2 -2
  168. data/spec/alexandria/ui/ui_manager_spec.rb +44 -20
  169. data/spec/end_to_end/basic_run_spec.rb +21 -38
  170. data/spec/fixtures/cover.jpg +0 -0
  171. data/spec/spec_helper.rb +54 -10
  172. data/tasks/setup.rb +2 -2
  173. data/tasks/spec.rake +11 -11
  174. data/util/rake/fileinstall.rb +38 -35
  175. data/util/rake/gettextgenerate.rb +7 -7
  176. data/util/rake/omfgenerate.rb +7 -7
  177. metadata +158 -45
  178. data/dogtail/basic_run_test.py +0 -9
  179. data/lib/alexandria/book_providers/renaud.rb +0 -155
  180. data/lib/alexandria/book_providers/thalia.rb +0 -198
  181. data/lib/alexandria/ui/dialogs/alert_dialog.rb +0 -63
  182. data/lib/alexandria/ui/dialogs/import_dialog.rb +0 -176
  183. data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +0 -62
  184. data/lib/alexandria/ui/dialogs/preferences_dialog.rb +0 -563
  185. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog.rb +0 -61
  186. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog_base.rb +0 -423
  187. data/spec/alexandria/scanners/cuecat_spec.rb +0 -67
  188. data/spec/alexandria/ui/dialogs_spec.rb +0 -162
  189. data/spec/alexandria/ui/sidepane_spec.rb +0 -29
  190. data/spec/alexandria/ui/ui_utilities_spec.rb +0 -62
  191. data/spec/alexandria/utilities_spec.rb +0 -52
  192. data/tasks/dogtail.rake +0 -6
@@ -1,62 +0,0 @@
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 NewSmartLibraryDialog < SmartLibraryPropertiesDialogBase
10
- include GetText
11
- GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: 'UTF-8')
12
-
13
- def initialize(parent)
14
- super(parent)
15
-
16
- add_buttons([Gtk::Stock::CANCEL, :cancel],
17
- [Gtk::Stock::NEW, :ok])
18
-
19
- self.title = _('New Smart Library')
20
- # FIXME: Should accept just :cancel
21
- self.default_response = Gtk::ResponseType::CANCEL
22
- end
23
-
24
- def acquire
25
- show_all
26
- insert_new_rule
27
-
28
- while ((response = run) != Gtk::ResponseType::CANCEL) &&
29
- (response != Gtk::ResponseType::DELETE_EVENT)
30
-
31
- if response == Gtk::ResponseType::HELP
32
- Alexandria::UI.display_help(self, 'new-smart-library')
33
- elsif response == Gtk::ResponseType::OK
34
- if user_confirms_possible_weirdnesses_before_saving?
35
- rules = smart_library_rules
36
- basename = smart_library_base_name(rules) || _('Smart Library')
37
- name = Library.generate_new_name(
38
- LibraryCollection.instance.all_libraries,
39
- basename)
40
- library = SmartLibrary.new(name,
41
- rules,
42
- predicate_operator_rule)
43
- yield(library)
44
- break
45
- end
46
- end
47
- end
48
-
49
- destroy
50
- end
51
-
52
- private
53
-
54
- def smart_library_base_name(rules)
55
- if rules.length == 1
56
- value = rules.first.value
57
- return value if value.is_a?(String) && !value.strip.empty?
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,563 +0,0 @@
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
- require 'alexandria/ui/builder_base'
8
- require 'alexandria/scanners/cuecat'
9
- require 'alexandria/scanners/keyboard'
10
-
11
- class Gtk::Entry
12
- attr_writer :mandatory
13
- def mandatory?
14
- @mandatory
15
- end
16
- end
17
-
18
- module Alexandria
19
- module UI
20
- class ProviderPreferencesBaseDialog < SimpleDelegator
21
- def initialize(title:, parent:, flags:, buttons:)
22
- dialog = Gtk::Dialog.new(title: title, parent: parent, flags: flags, buttons: buttons)
23
- super(dialog)
24
-
25
- self.resizable = false
26
- child.border_width = 12
27
-
28
- @controls = []
29
- end
30
-
31
- def fill_table(table, provider)
32
- i = table.n_rows
33
- table.resize(table.n_rows + provider.prefs.length,
34
- table.n_columns)
35
- table.border_width = 12
36
- table.row_spacings = 6
37
- table.column_spacings = 12
38
-
39
- @controls.clear
40
-
41
- provider.prefs.read.each do |variable|
42
- if variable.name == 'piggyback'
43
- next
44
- # ULTRA-HACK!! for bug #13302
45
- # not displaying the visual choice, as its usually unnecessary
46
- # Either way, this is confusing to the user: FIX
47
- # - Cathal Mc Ginley 2008-02-18
48
- end
49
-
50
- if variable.name == 'enabled'
51
- # also don't display Enabled/Disabled
52
- next
53
- end
54
-
55
- label = Gtk::Label.new('_' + variable.description + ':')
56
- label.use_underline = true
57
- label.xalign = 0
58
- table.attach_defaults(label, 0, 1, i, i + 1)
59
-
60
- if variable.possible_values.nil?
61
- entry = Gtk::Entry.new
62
- entry.text = variable.value.to_s
63
- entry.mandatory = variable.mandatory?
64
- else
65
- entry = Gtk::ComboBoxText.new
66
- variable.possible_values.each do |value|
67
- entry.append_text(value.to_s)
68
- end
69
- index = variable.possible_values.index(variable.value)
70
- entry.active = index
71
- end
72
- label.mnemonic_widget = entry
73
-
74
- @controls << [variable, entry]
75
-
76
- table.attach_defaults(entry, 1, 2, i, i + 1)
77
- i += 1
78
- end
79
- table
80
- end
81
-
82
- def sync_variables
83
- @controls.each do |variable, entry|
84
- variable.new_value = case entry
85
- when Gtk::ComboBox
86
- variable.possible_values[entry.active]
87
- when Gtk::Entry
88
- entry.text
89
- end
90
- end
91
- end
92
- end
93
-
94
- class ProviderPreferencesDialog < ProviderPreferencesBaseDialog
95
- include GetText
96
- GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: 'UTF-8')
97
-
98
- def initialize(parent, provider)
99
- super(title: _('Preferences for %s') % provider.fullname,
100
- parent: parent,
101
- flags: :modal,
102
- buttons: [[Gtk::Stock::CLOSE, :close]])
103
-
104
- table = Gtk::Table.new(0, 0)
105
- fill_table(table, provider)
106
- child.pack_start(table)
107
-
108
- signal_connect('destroy') { sync_variables }
109
- end
110
-
111
- def acquire
112
- show_all
113
- run
114
- destroy
115
- end
116
- end
117
-
118
- class NewProviderDialog < ProviderPreferencesBaseDialog
119
- include GetText
120
- GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: 'UTF-8')
121
-
122
- def initialize(parent)
123
- super(title: _('New Provider'),
124
- parent: parent,
125
- flags: :modal,
126
- buttons: [[Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]])
127
- @add_button = add_button(Gtk::Stock::ADD,
128
- Gtk::ResponseType::ACCEPT)
129
-
130
- instances = BookProviders.abstract_classes.map(&:new)
131
- @selected_instance = nil
132
-
133
- @table = Gtk::Table.new(2, 2)
134
- child.pack_start(@table)
135
-
136
- # Name.
137
-
138
- label_name = Gtk::Label.new(_('_Name:'))
139
- label_name.use_underline = true
140
- label_name.xalign = 0
141
- @table.attach_defaults(label_name, 0, 1, 0, 1)
142
-
143
- entry_name = Gtk::Entry.new
144
- entry_name.mandatory = true
145
- label_name.mnemonic_widget = entry_name
146
- @table.attach_defaults(entry_name, 1, 2, 0, 1)
147
-
148
- # Type.
149
-
150
- label_type = Gtk::Label.new(_('_Type:'))
151
- label_type.use_underline = true
152
- label_type.xalign = 0
153
- @table.attach_defaults(label_type, 0, 1, 1, 2)
154
-
155
- combo_type = Gtk::ComboBoxText.new
156
- instances.each do |instance|
157
- combo_type.append_text(instance.name)
158
- end
159
- combo_type.signal_connect('changed') do |cb|
160
- @selected_instance = instances[cb.active]
161
- fill_table(@table, @selected_instance)
162
- sensitize
163
- # FIXME: this should be re-written once we have multiple
164
- # abstract providers.
165
- end
166
- combo_type.active = 0
167
- label_type.mnemonic_widget = combo_type
168
- @table.attach_defaults(combo_type, 1, 2, 1, 2)
169
- end
170
-
171
- def acquire
172
- show_all
173
- if run == Gtk::ResponseType::ACCEPT
174
- @selected_instance.reinitialize(entry_name.text)
175
- sync_variables
176
- else
177
- @selected_instance = nil
178
- end
179
- destroy
180
- end
181
-
182
- def instance
183
- @selected_instance
184
- end
185
-
186
- private
187
-
188
- def sensitize
189
- entries = @table.children.select { |x| x.is_a?(Gtk::Entry) }
190
- entries.each do |entry|
191
- entry.signal_connect('changed') do
192
- sensitive = true
193
- entries.each do |entry2|
194
- if entry2.mandatory?
195
- sensitive = !entry2.text.strip.empty?
196
- break unless sensitive
197
- end
198
- end
199
- @add_button.sensitive = sensitive
200
- end
201
- end
202
- @add_button.sensitive = false
203
- end
204
- end
205
-
206
- class PreferencesDialog < BuilderBase
207
- include Alexandria::Logging
208
- include GetText
209
- GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: 'UTF-8')
210
-
211
- def initialize(parent, &changed_block)
212
- super('preferences_dialog__builder.glade', widget_names)
213
- @preferences_dialog.transient_for = parent
214
- @changed_block = changed_block
215
-
216
- @cols = {
217
- @checkbutton_col_authors => 'col_authors_visible',
218
- @checkbutton_col_isbn => 'col_isbn_visible',
219
- @checkbutton_col_publisher => 'col_publisher_visible',
220
- @checkbutton_col_publish_date => 'col_publish_date_visible',
221
- @checkbutton_col_edition => 'col_edition_visible',
222
- @checkbutton_col_redd => 'col_redd_visible',
223
- @checkbutton_col_own => 'col_own_visible',
224
- @checkbutton_col_want => 'col_want_visible',
225
- @checkbutton_col_rating => 'col_rating_visible',
226
- @checkbutton_col_tags => 'col_tags_visible',
227
- @checkbutton_col_loaned_to => 'col_loaned_to_visible'
228
- }
229
- @cols.each_pair do |checkbutton, pref_name|
230
- if checkbutton
231
- checkbutton.active = Preferences.instance.send(pref_name)
232
- else
233
- log.warn {
234
- "no CheckButton for property #{pref_name} " \
235
- '(probably conflicting versions of GUI and lib code)'
236
- }
237
- end
238
- end
239
-
240
- model = Gtk::ListStore.new(String, String, TrueClass, Integer)
241
- @treeview_providers.model = model
242
- reload_providers
243
- model.signal_connect_after('row-changed') { update_priority }
244
-
245
- renderer = Gtk::CellRendererToggle.new
246
- renderer.activatable = true
247
- renderer.signal_connect('toggled') do |_rndrr, path|
248
- tree_path = Gtk::TreePath.new(path)
249
- @treeview_providers.selection.select_path(tree_path)
250
- prov = selected_provider
251
- if prov
252
- prov.toggle_enabled
253
- adjust_selected_provider(prov)
254
- # reload_providers
255
- end
256
- end
257
-
258
- # renderer.active = true
259
- column = Gtk::TreeViewColumn.new('Enabled', renderer)
260
- column.set_cell_data_func(renderer) do |_col, rndr, _mod, iter|
261
- value = iter[2]
262
- rndr.active = value
263
- end
264
-
265
- @treeview_providers.append_column(column)
266
-
267
- renderer = Gtk::CellRendererText.new
268
- column = Gtk::TreeViewColumn.new('Providers',
269
- renderer)
270
- # :text => 0)
271
- column.set_cell_data_func(renderer) do |_col, rndr, _mod, iter|
272
- rndr.markup = iter[0]
273
- # enabled = iter[2]
274
- # unless enabled
275
- # rndr.foreground = "gray"
276
- # end
277
- # rndr.active = value
278
- end
279
- @treeview_providers.append_column(column)
280
- @treeview_providers.selection.signal_connect('changed') \
281
- { sensitize_providers }
282
-
283
- @button_prov_setup.sensitive = false
284
- @button_prov_up.sensitive = @button_prov_down.sensitive = BookProviders.length > 1
285
-
286
- @buttonbox_prov.set_child_secondary(@button_prov_add, true)
287
- @buttonbox_prov.set_child_secondary(@button_prov_remove, true)
288
-
289
- if BookProviders.abstract_classes.empty?
290
- @checkbutton_prov_advanced.sensitive = false
291
- else
292
- view_advanced = Preferences.instance.view_advanced_settings
293
- @checkbutton_prov_advanced.active = true if view_advanced
294
- end
295
-
296
- setup_enable_disable_popup
297
- sensitize_providers
298
- setup_barcode_scanner_tab
299
- end
300
-
301
- def widget_names
302
- [:button_prov_add, :button_prov_down, :button_prov_remove,
303
- :button_prov_setup, :button_prov_up, :buttonbox_prov,
304
- :checkbutton_col_authors, :checkbutton_col_edition,
305
- :checkbutton_col_isbn, :checkbutton_col_loaned_to,
306
- :checkbutton_col_own, :checkbutton_col_publish_date,
307
- :checkbutton_col_publisher, :checkbutton_col_rating,
308
- :checkbutton_col_redd, :checkbutton_col_tags,
309
- :checkbutton_col_want, :checkbutton_prov_advanced,
310
- :preferences_dialog, :treeview_providers,
311
- :scanner_device_type, :use_scanning_sound, :use_scan_sound]
312
- end
313
-
314
- def setup_barcode_scanner_tab
315
- @scanner_device_model = Gtk::ListStore.new(String, String)
316
- chosen_scanner_name = Preferences.instance.barcode_scanner
317
- index = 0
318
- @scanner_device_type.model = @scanner_device_model
319
- renderer = Gtk::CellRendererText.new
320
- @scanner_device_type.pack_start(renderer, true)
321
- @scanner_device_type.add_attribute(renderer, 'text', 0)
322
-
323
- Alexandria::Scanners.each_scanner do |scanner|
324
- iter = @scanner_device_model.append
325
- iter[0] = scanner.display_name
326
- iter[1] = scanner.name
327
- @scanner_device_type.active = index if chosen_scanner_name == scanner.name
328
- index += 1
329
- end
330
-
331
- @use_scanning_sound.active = Preferences.instance.play_scanning_sound
332
- @use_scan_sound.active = Preferences.instance.play_scan_sound
333
- end
334
-
335
- def setup_enable_disable_popup
336
- # New Enable/Disable pop-up menu...
337
- @enable_disable_providers_menu = Gtk::Menu.new
338
- @enable_item = Gtk::MenuItem.new(label: _('Disable Provider'))
339
- @enable_item.signal_connect('activate') {
340
- prov = selected_provider
341
- prov.toggle_enabled
342
- adjust_selected_provider(prov)
343
- }
344
- @enable_disable_providers_menu.append(@enable_item)
345
- @enable_disable_providers_menu.show_all
346
-
347
- @treeview_providers.signal_connect('button_press_event') do |widget, event|
348
- if event_is_right_click(event)
349
- if (path = widget.get_path_at_pos(event.x, event.y))
350
- widget.grab_focus
351
- obj = widget.selection
352
- path = path.first
353
- unless obj.path_is_selected?(path)
354
- widget.unselect_all
355
- obj.select_path(path)
356
- end
357
- sel = widget.selection.selected
358
- if sel
359
- already_enabled = sel[2]
360
- message = already_enabled ? _('Disable Provider') : _('Enable Provider')
361
- @enable_item.label = message
362
- GLib::Idle.add do
363
- @enable_disable_providers_menu.popup(nil, nil, event.button, event.time)
364
- false
365
- end
366
- end
367
- else
368
- puts 'not on a path'
369
- end
370
- end
371
- end
372
-
373
- # Popup the menu on Shift-F10
374
- @treeview_providers.signal_connect('popup_menu') {
375
- selected_prov = @treeview_providers.selection.selected
376
- puts selected_prov.inspect
377
- if selected_prov
378
- GLib::Idle.add do
379
- already_enabled = selected_prov[2]
380
- message = already_enabled ? _('Disable Provider') : _('Enable Provider')
381
- @enable_item.label = message
382
-
383
- @enable_disable_providers_menu.popup(nil, nil, 0, :current_time)
384
- false
385
- end
386
- else
387
- puts 'no action'
388
- end
389
- }
390
- end
391
-
392
- def event_is_right_click(event)
393
- (event.event_type == :button_press) && (event.button == 3)
394
- end
395
-
396
- def prefs_empty(prefs)
397
- prefs.empty? || ((prefs.size == 1) && (prefs.first.name == 'enabled'))
398
- end
399
-
400
- def on_provider_setup
401
- provider = selected_provider
402
- unless prefs_empty(provider.prefs)
403
- ProviderPreferencesDialog.new(@preferences_dialog, provider).acquire
404
- end
405
- end
406
-
407
- def on_provider_up
408
- iter = @treeview_providers.selection.selected
409
- previous_path = iter.path
410
- previous_path.prev!
411
- model = @treeview_providers.model
412
- model.move_after(model.get_iter(previous_path), iter)
413
- sensitize_providers
414
- update_priority
415
- end
416
-
417
- def on_provider_down
418
- iter = @treeview_providers.selection.selected
419
- next_iter = iter.dup
420
- next_iter.next!
421
- @treeview_providers.model.move_after(iter, next_iter)
422
- sensitize_providers
423
- update_priority
424
- end
425
-
426
- def on_provider_advanced_toggled(checkbutton)
427
- on = checkbutton.active?
428
- Preferences.instance.view_advanced_settings = on
429
- @button_prov_add.visible = @button_prov_remove.visible = on
430
- end
431
-
432
- def on_provider_add
433
- dialog = NewProviderDialog.new(@preferences_dialog).acquire
434
- if dialog.instance
435
- BookProviders.update_priority
436
- reload_providers
437
- end
438
- end
439
-
440
- def on_scanner_device_type(_combo)
441
- iter = @scanner_device_type.active_iter
442
- Preferences.instance.barcode_scanner = iter[1] if iter && iter[1]
443
- end
444
-
445
- def on_use_scanning_sound(checkbox)
446
- Preferences.instance.play_scanning_sound = checkbox.active?
447
- end
448
-
449
- def on_use_scan_sound(checkbox)
450
- Preferences.instance.play_scan_sound = checkbox.active?
451
- end
452
-
453
- def on_provider_remove
454
- provider = selected_provider
455
- dialog = AlertDialog.new(@main_app,
456
- _('Are you sure you want to ' \
457
- 'permanently delete the provider ' \
458
- "'%s'?") % provider.fullname,
459
- Gtk::Stock::DIALOG_QUESTION,
460
- [[Gtk::Stock::CANCEL,
461
- Gtk::ResponseType::CANCEL],
462
- [Gtk::Stock::DELETE,
463
- Gtk::ResponseType::OK]],
464
- _('If you continue, the provider and ' \
465
- 'all of its preferences will be ' \
466
- 'permanently deleted.'))
467
- dialog.default_response = Gtk::ResponseType::CANCEL
468
- dialog.show_all
469
- if dialog.run == Gtk::ResponseType::OK
470
- provider.remove
471
- BookProviders.update_priority
472
- reload_providers
473
- end
474
- dialog.destroy
475
- end
476
-
477
- def on_column_toggled(checkbutton)
478
- raise if @cols[checkbutton].nil?
479
-
480
- Preferences.instance.send("#{@cols[checkbutton]}=",
481
- checkbutton.active?)
482
-
483
- @changed_block.call
484
- end
485
-
486
- def on_providers_button_press_event(_widget, event)
487
- # double left click
488
- on_provider_setup if (event.event_type == :'2button_press') && (event.button == 1)
489
- end
490
-
491
- def on_close
492
- @preferences_dialog.destroy
493
- Alexandria::Preferences.instance.save!
494
- end
495
-
496
- def on_help
497
- Alexandria::UI.display_help(@preferences_dialog,
498
- 'alexandria-preferences')
499
- end
500
-
501
- private
502
-
503
- def reload_providers
504
- model = @treeview_providers.model
505
- model.clear
506
- BookProviders.each_with_index do |x, index|
507
- iter = model.append
508
- iter[0] = if x.enabled
509
- x.fullname
510
- else
511
- "<i>#{x.fullname}</i>"
512
- end
513
- iter[1] = x.name
514
- iter[2] = x.enabled
515
- iter[3] = index
516
- end
517
- end
518
-
519
- def selected_provider
520
- iter = @treeview_providers.selection.selected
521
- BookProviders.find { |x| x.name == iter[1] } unless iter.nil?
522
- end
523
-
524
- def adjust_selected_provider(prov)
525
- iter = @treeview_providers.selection.selected
526
- iter[0] = if prov.enabled
527
- prov.fullname
528
- else
529
- "<i>#{prov.fullname}</i>"
530
- end
531
- iter[2] = prov.enabled
532
- end
533
-
534
- def sensitize_providers
535
- model = @treeview_providers.model
536
- sel_iter = @treeview_providers.selection.selected
537
- if sel_iter.nil?
538
- # No selection, we are probably called by ListStore#clear
539
- @button_prov_up.sensitive = false
540
- @button_prov_down.sensitive = false
541
- @button_prov_setup.sensitive = false
542
- @button_prov_remove.sensitive = false
543
- else
544
- last_iter = model.get_iter((BookProviders.length - 1).to_s)
545
- @button_prov_up.sensitive = sel_iter != model.iter_first
546
- @button_prov_down.sensitive = sel_iter != last_iter
547
- provider = BookProviders.find { |x| x.name == sel_iter[1] }
548
- @button_prov_setup.sensitive = !prefs_empty(provider.prefs)
549
- @button_prov_remove.sensitive = provider.abstract?
550
- end
551
- end
552
-
553
- def update_priority
554
- priority = []
555
- @treeview_providers.model.each do |_model, _path, iter|
556
- priority << iter[1]
557
- end
558
- Preferences.instance.providers_priority = priority
559
- BookProviders.update_priority
560
- end
561
- end
562
- end
563
- end