alexandria-book-collection-manager 0.7.5 → 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.github/workflows/ruby.yml +72 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +65 -30
  6. data/.rubocop_todo.yml +49 -165
  7. data/.simplecov +5 -2
  8. data/CHANGELOG.md +64 -0
  9. data/ChangeLog.0 +19 -19
  10. data/INSTALL.md +26 -16
  11. data/README.md +31 -35
  12. data/Rakefile +18 -16
  13. data/alexandria-book-collection-manager.gemspec +35 -29
  14. data/doc/FAQ +2 -2
  15. data/doc/dependency_decisions.yml +22 -3
  16. data/lib/alexandria/about.rb +1 -1
  17. data/lib/alexandria/book_providers/bl_provider.rb +88 -0
  18. data/lib/alexandria/book_providers/douban.rb +2 -2
  19. data/lib/alexandria/book_providers/loc_provider.rb +38 -0
  20. data/lib/alexandria/book_providers/pseudomarc.rb +61 -71
  21. data/lib/alexandria/book_providers/sbn_provider.rb +108 -0
  22. data/lib/alexandria/book_providers/{thalia.rb → thalia_provider.rb} +37 -74
  23. data/lib/alexandria/book_providers/web.rb +2 -2
  24. data/lib/alexandria/book_providers/worldcat.rb +34 -38
  25. data/lib/alexandria/book_providers/z3950_provider.rb +199 -0
  26. data/lib/alexandria/book_providers.rb +48 -65
  27. data/lib/alexandria/default_preferences.rb +2 -1
  28. data/lib/alexandria/execution_queue.rb +13 -12
  29. data/lib/alexandria/export_library.rb +21 -22
  30. data/lib/alexandria/image_fetcher.rb +25 -0
  31. data/lib/alexandria/import_library.rb +46 -70
  32. data/lib/alexandria/import_library_csv.rb +16 -16
  33. data/lib/alexandria/library_sort_order.rb +3 -1
  34. data/lib/alexandria/library_store.rb +19 -20
  35. data/lib/alexandria/logging.rb +5 -9
  36. data/lib/alexandria/models/book.rb +15 -2
  37. data/lib/alexandria/models/library.rb +31 -35
  38. data/lib/alexandria/net.rb +1 -2
  39. data/lib/alexandria/preferences.rb +27 -33
  40. data/lib/alexandria/scanners/cue_cat.rb +6 -6
  41. data/lib/alexandria/scanners/keyboard.rb +1 -1
  42. data/lib/alexandria/scanners.rb +2 -2
  43. data/lib/alexandria/smart_library.rb +22 -26
  44. data/lib/alexandria/ui/about_dialog.rb +1 -1
  45. data/lib/alexandria/ui/acquire_dialog.rb +15 -19
  46. data/lib/alexandria/ui/alert_dialog.rb +36 -19
  47. data/lib/alexandria/ui/bad_isbns_dialog.rb +13 -9
  48. data/lib/alexandria/ui/barcode_animation.rb +6 -6
  49. data/lib/alexandria/ui/book_properties_dialog.rb +2 -3
  50. data/lib/alexandria/ui/book_properties_dialog_base.rb +35 -137
  51. data/lib/alexandria/ui/calendar_popup.rb +58 -0
  52. data/lib/alexandria/ui/callbacks.rb +144 -123
  53. data/lib/alexandria/ui/completion_models.rb +2 -6
  54. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -1
  55. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +2 -2
  56. data/lib/alexandria/ui/error_dialog.rb +1 -1
  57. data/lib/alexandria/ui/export_dialog.rb +19 -18
  58. data/lib/alexandria/ui/icons.rb +34 -40
  59. data/lib/alexandria/ui/iconview_tooltips.rb +40 -53
  60. data/lib/alexandria/ui/import_dialog.rb +49 -48
  61. data/lib/alexandria/ui/init.rb +14 -12
  62. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +2 -2
  63. data/lib/alexandria/ui/libraries_combo.rb +10 -9
  64. data/lib/alexandria/ui/listview.rb +6 -7
  65. data/lib/alexandria/ui/main_app.rb +2 -2
  66. data/lib/alexandria/ui/multi_drag_treeview.rb +5 -7
  67. data/lib/alexandria/ui/new_book_dialog.rb +63 -65
  68. data/lib/alexandria/ui/new_book_dialog_manual.rb +1 -1
  69. data/lib/alexandria/ui/new_provider_dialog.rb +12 -11
  70. data/lib/alexandria/ui/new_smart_library_dialog.rb +39 -27
  71. data/lib/alexandria/ui/preferences_dialog.rb +25 -84
  72. data/lib/alexandria/ui/provider_preferences_base_dialog.rb +10 -6
  73. data/lib/alexandria/ui/provider_preferences_dialog.rb +5 -5
  74. data/lib/alexandria/ui/really_delete_dialog.rb +2 -2
  75. data/lib/alexandria/ui/sidepane_manager.rb +38 -38
  76. data/lib/alexandria/ui/skip_entry_dialog.rb +3 -2
  77. data/lib/alexandria/ui/smart_library_properties_dialog.rb +35 -36
  78. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +61 -244
  79. data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
  80. data/lib/alexandria/ui/sound.rb +4 -6
  81. data/lib/alexandria/ui/ui_manager.rb +80 -83
  82. data/lib/alexandria/ui.rb +7 -7
  83. data/lib/alexandria/version.rb +2 -2
  84. data/lib/alexandria/web_themes.rb +15 -15
  85. data/lib/alexandria.rb +2 -2
  86. data/po/cs.po +947 -865
  87. data/po/cy.po +913 -864
  88. data/po/de.po +961 -865
  89. data/po/el.po +956 -861
  90. data/po/es.po +952 -857
  91. data/po/fr.po +950 -865
  92. data/po/ga.po +866 -819
  93. data/po/gl.po +946 -861
  94. data/po/it.po +945 -858
  95. data/po/ja.po +921 -836
  96. data/po/mk.po +953 -858
  97. data/po/nb.po +932 -847
  98. data/po/nl.po +955 -849
  99. data/po/pl.po +999 -963
  100. data/po/pt.po +946 -850
  101. data/po/pt_BR.po +944 -859
  102. data/po/ru.po +959 -868
  103. data/po/sk.po +950 -863
  104. data/po/sv.po +944 -859
  105. data/po/uk.po +925 -846
  106. data/po/zh_TW.po +926 -841
  107. data/schemas/alexandria.schemas +1 -1
  108. data/share/alexandria/glade/main_app__builder.glade +6 -21
  109. data/share/gnome/help/alexandria/C/adding-books.xml +3 -4
  110. data/share/gnome/help/alexandria/C/introduction.xml +0 -16
  111. data/share/gnome/help/alexandria/C/searching.xml +1 -4
  112. data/share/gnome/help/alexandria/C/settings.xml +0 -30
  113. data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
  114. data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
  115. data/share/gnome/help/alexandria/fr/alexandria.xml +5 -160
  116. data/share/gnome/help/alexandria/ja/adding-books.xml +1 -1
  117. data/share/gnome/help/alexandria/ja/introduction.xml +0 -15
  118. data/share/gnome/help/alexandria/ja/searching.xml +3 -7
  119. data/share/gnome/help/alexandria/ja/settings.xml +0 -27
  120. data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
  121. data/spec/alexandria/book_providers/bl_provider_spec.rb +13 -0
  122. data/spec/alexandria/book_providers/loc_provider_spec.rb +17 -0
  123. data/spec/alexandria/book_providers/sbn_provider_spec.rb +13 -0
  124. data/spec/alexandria/book_providers/thalia_provider_spec.rb +119 -0
  125. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
  126. data/spec/alexandria/book_providers_spec.rb +0 -154
  127. data/spec/alexandria/console_spec.rb +0 -5
  128. data/spec/alexandria/export_library_spec.rb +27 -38
  129. data/spec/alexandria/library_spec.rb +76 -46
  130. data/spec/alexandria/preferences_spec.rb +29 -3
  131. data/spec/alexandria/scanners/cue_cat_spec.rb +1 -1
  132. data/spec/alexandria/ui/about_dialog_spec.rb +1 -1
  133. data/spec/alexandria/ui/acquire_dialog_spec.rb +1 -1
  134. data/spec/alexandria/ui/alert_dialog_spec.rb +1 -1
  135. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +1 -1
  136. data/spec/alexandria/ui/book_properties_dialog_spec.rb +47 -5
  137. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +1 -1
  138. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +1 -1
  139. data/spec/alexandria/ui/error_dialog_spec.rb +1 -1
  140. data/spec/alexandria/ui/export_dialog_spec.rb +25 -4
  141. data/spec/alexandria/ui/icons_spec.rb +26 -0
  142. data/spec/alexandria/ui/iconview_spec.rb +1 -1
  143. data/spec/alexandria/ui/import_dialog_spec.rb +35 -3
  144. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +1 -1
  145. data/spec/alexandria/ui/main_app_spec.rb +1 -1
  146. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +39 -3
  147. data/spec/alexandria/ui/new_provider_dialog_spec.rb +19 -3
  148. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +28 -3
  149. data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
  150. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +23 -8
  151. data/spec/alexandria/ui/really_delete_dialog_spec.rb +1 -1
  152. data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
  153. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +1 -1
  154. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +37 -6
  155. data/spec/alexandria/ui/ui_manager_spec.rb +116 -2
  156. data/spec/data/libraries/0.6.2/My Library/9780571147168.yaml +2 -0
  157. data/spec/end_to_end/basic_run_spec.rb +3 -8
  158. data/spec/fixtures/cover.jpg +0 -0
  159. data/spec/spec_helper.rb +47 -3
  160. data/tasks/spec.rake +3 -5
  161. data/util/rake/fileinstall.rb +16 -15
  162. data/util/rake/omfgenerate.rb +1 -1
  163. metadata +141 -52
  164. data/.travis.yml +0 -39
  165. data/lib/alexandria/book_providers/adlibris.rb +0 -196
  166. data/lib/alexandria/book_providers/amazon_aws.rb +0 -252
  167. data/lib/alexandria/book_providers/amazon_ecs_util.rb +0 -388
  168. data/lib/alexandria/book_providers/barnes_and_noble.rb +0 -209
  169. data/lib/alexandria/book_providers/proxis.rb +0 -175
  170. data/lib/alexandria/book_providers/siciliano.rb +0 -257
  171. data/lib/alexandria/book_providers/z3950.rb +0 -415
  172. data/spec/alexandria/ui/ui_utilities_spec.rb +0 -62
  173. data/spec/alexandria/utilities_spec.rb +0 -52
@@ -8,17 +8,16 @@ module Alexandria
8
8
  module UI
9
9
  # Generalized Dialog for lists of bad isbns. Used for on_import. Can also
10
10
  # be used for on_load library conversions.
11
- class BadIsbnsDialog < SimpleDelegator
11
+ class BadIsbnsDialog
12
12
  def initialize(parent, message, list)
13
- dialog = Gtk::MessageDialog.new(parent: parent,
14
- flags: :modal,
15
- type: :warning,
16
- buttons: :close,
17
- message: message)
18
- super(dialog)
13
+ @dialog = Gtk::MessageDialog.new(parent: parent,
14
+ flags: :modal,
15
+ type: :warning,
16
+ buttons: :close,
17
+ message: message)
18
+ the_vbox = @dialog.children.first
19
19
 
20
20
  isbn_container = Gtk::Box.new :horizontal
21
- the_vbox = children.first
22
21
  the_vbox.pack_start(isbn_container)
23
22
  the_vbox.reorder_child(isbn_container, 3)
24
23
  scrolley = Gtk::ScrolledWindow.new
@@ -30,7 +29,12 @@ module Alexandria
30
29
  list.each do |li|
31
30
  textview.buffer.insert_at_cursor("#{li}\n")
32
31
  end
33
- show_all
32
+
33
+ @dialog.signal_connect("response") { @dialog.destroy }
34
+ end
35
+
36
+ def show
37
+ @dialog.show_all
34
38
  end
35
39
  end
36
40
  end
@@ -96,11 +96,11 @@ module Alexandria
96
96
  end
97
97
 
98
98
  def set_passive
99
- if @canvas
100
- passive_bg = "#F4F4F4"
101
- @canvas.set_property(:background_color, passive_bg)
102
- @barcode_bars.each { |rect| rect.set_property(:fill_color, passive_bg) }
103
- end
99
+ @canvas or return
100
+
101
+ passive_bg = "#F4F4F4"
102
+ @canvas.set_property(:background_color, passive_bg)
103
+ @barcode_bars.each { |rect| rect.set_property(:fill_color, passive_bg) }
104
104
  end
105
105
 
106
106
  def manual_input
@@ -121,7 +121,7 @@ module Alexandria
121
121
  until d.empty?
122
122
  space_width = d[0].chr.to_i
123
123
  bar_width = d[1].chr.to_i
124
- d = d[2..-1]
124
+ d = d[2..]
125
125
  @barcode_data << [space_width, bar_width]
126
126
  end
127
127
  end
@@ -9,14 +9,13 @@ require "alexandria/ui/error_dialog"
9
9
  module Alexandria
10
10
  module UI
11
11
  class BookPropertiesDialog < BookPropertiesDialogBase
12
- include Logging
13
12
  include GetText
14
13
  extend GetText
15
14
  GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
16
15
 
17
16
  def initialize(parent, library, book)
18
17
  super(parent, library.cover(book))
19
- puts "Initializing Book Properties Dialog..." if $DEBUG
18
+ log.debug { "Initializing Book Properties Dialog" }
20
19
 
21
20
  cancel_button = Gtk::Button.new(stock_id: Gtk::Stock::CANCEL)
22
21
  cancel_button.signal_connect("clicked") { on_cancel }
@@ -86,7 +85,7 @@ module Alexandria
86
85
  if (@checkbutton_redd.active = book.redd?)
87
86
  @redd_date.sensitive = true
88
87
  if book.redd_when.nil?
89
- puts "no redd_when"
88
+ log.debug { "no redd_when" }
90
89
  else
91
90
  @redd_date.text = format_date(book.redd_when)
92
91
  end
@@ -5,11 +5,14 @@
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
7
  require "alexandria/ui/builder_base"
8
+ require "alexandria/ui/calendar_popup"
8
9
  require "alexandria/ui/error_dialog"
9
10
 
10
11
  module Alexandria
11
12
  module UI
12
13
  class BookPropertiesDialogBase < BuilderBase
14
+ include CalendarPopup
15
+ include Logging
13
16
  include GetText
14
17
  extend GetText
15
18
  GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
@@ -51,7 +54,7 @@ module Alexandria
51
54
  editable: 1)
52
55
  @treeview_authors.append_column(col)
53
56
 
54
- setup_calendar_widgets
57
+ setup_date_widgets
55
58
  GLib::Timeout.add(150) do
56
59
  @setup_finished = true
57
60
 
@@ -59,130 +62,31 @@ module Alexandria
59
62
  end
60
63
  end
61
64
 
62
- def setup_calendar_widgets
63
- @popup_displayed = false
64
- @calendar_popup = Gtk::Window.new # Gtk::Window::POPUP)
65
- # @calendar_popup.modal = true
66
- @calendar_popup.decorated = false
67
- @calendar_popup.skip_taskbar_hint = true
68
- @calendar_popup.skip_pager_hint = true
69
- @calendar_popup.events = [:focus_change_mask]
70
-
71
- @calendar_popup.set_transient_for(@book_properties_dialog)
72
- @calendar_popup.set_type_hint :dialog
73
- @calendar_popup.name = "calendar-popup"
74
- @calendar_popup.resizable = false
75
- # @calendar_popup.border_width = 4
76
- # @calendar_popup.app_paintable = true
77
-
78
- @calendar_popup.signal_connect("focus-out-event") do |_popup, _event|
79
- hide_calendar_popup
80
- false
81
- end
82
-
83
- @calendar = Gtk::Calendar.new
84
- @calendar_popup.add(@calendar)
85
-
86
- @calendar.signal_connect("day-selected") do
87
- date_arr = @calendar.date
88
- year = date_arr[0]
89
- month = date_arr[1] # + 1 # gtk : months 0-indexed, Time.gm : 1-index
90
- day = date_arr[2]
91
- if @calendar_popup_for_entry
92
- time = Time.gm(year, month, day)
93
- @calendar_popup_for_entry.text = format_date(time)
94
- end
95
- end
96
-
97
- @calendar.signal_connect("day-selected-double-click") do
98
- date_arr = @calendar.date
99
- year = date_arr[0]
100
- month = date_arr[1] # + 1 # gtk : months 0-indexed, Time.gm : 1-index
101
- day = date_arr[2]
102
- if @calendar_popup_for_entry
103
- time = Time.gm(year, month, day)
104
- @calendar_popup_for_entry.text = format_date(time)
105
- end
106
- hide_calendar_popup
107
- end
65
+ def show
66
+ @book_properties_dialog.show
67
+ end
108
68
 
69
+ def setup_date_widgets
109
70
  @redd_date.signal_connect("icon-press") do |entry, primary, _icon|
110
- if primary.nick == "primary"
71
+ case primary.nick
72
+ when "primary"
111
73
  display_calendar_popup(entry)
112
- elsif primary.nick == "secondary"
74
+ when "secondary"
113
75
  clear_date_entry(entry)
114
76
  end
115
77
  end
116
78
 
117
79
  @date_loaned_since.signal_connect("icon-press") do |entry, primary, _icon|
118
- if primary.nick == "primary"
80
+ case primary.nick
81
+ when "primary"
119
82
  display_calendar_popup(entry)
120
- elsif primary.nick == "secondary"
83
+ when "secondary"
121
84
  clear_date_entry(entry)
122
85
  @label_loaning_duration.label = ""
123
86
  end
124
87
  end
125
88
  end
126
89
 
127
- def clear_date_entry(entry)
128
- entry.text = ""
129
- end
130
-
131
- def hide_calendar_popup
132
- @calendar_popup_for_entry = nil
133
-
134
- @calendar_popup.hide_all
135
- @book_properties_dialog.modal = true
136
-
137
- GLib::Timeout.add(150) do
138
- # If we set @popup_displayed=false immediately, then a click
139
- # event on the primary icon of the Entry simultaneous with
140
- # the focus-out-event of the Calendar causes the Calendar to
141
- # pop up again milliseconds after being closed.
142
- #
143
- # This is never what the user intends.
144
- #
145
- # So we add a small delay before the primary icon's event
146
- # handler is told to pop up the calendar in response to
147
- # clicks.
148
-
149
- @popup_displayed = false
150
- false
151
- end
152
- end
153
-
154
- def display_calendar_popup(entry)
155
- if @popup_displayed
156
- hide_calendar_popup
157
- else
158
- @calendar_popup_for_entry = entry
159
- unless entry.text.strip.empty?
160
- time = parse_date(entry.text)
161
- unless time.nil?
162
- @calendar.year = time.year
163
- @calendar.month = time.month - 1
164
- @calendar.day = time.day
165
- end
166
- end
167
- @book_properties_dialog.modal = false
168
- @calendar_popup.move(*get_entry_popup_coords(entry))
169
- @calendar_popup.show_all
170
- @popup_displayed = true
171
- end
172
- end
173
-
174
- def get_entry_popup_coords(entry)
175
- gdk_win = entry.parent_window
176
- x, y = gdk_win.origin
177
- alloc = entry.allocation
178
- x += alloc.x
179
- y += alloc.y
180
- y += alloc.height
181
- # x = [0, x].max
182
- # y = [0, y].max
183
- [x, y]
184
- end
185
-
186
90
  def widget_names
187
91
  [:book_properties_dialog, :button_box, :button_cover,
188
92
  :checkbutton_loaned, :checkbutton_own, :checkbutton_redd,
@@ -242,39 +146,32 @@ module Alexandria
242
146
  end
243
147
 
244
148
  def own_toggled
245
- @checkbutton_want.inconsistent = if @checkbutton_own.active?
246
- true
247
- else
248
- false
249
- end
149
+ @checkbutton_want.inconsistent = @checkbutton_own.active?
250
150
  end
251
151
 
252
152
  def want_toggled; end
253
153
 
254
154
  @@latest_filechooser_directory = ENV["HOME"]
255
155
  def on_change_cover
256
- backend = `uname`.chomp == "FreeBSD" ? "neant" : "gnome-vfs"
257
- dialog = Gtk::FileChooserDialog.new(_("Select a cover image"),
258
- @book_properties_dialog,
259
- Gtk::FileChooser::ACTION_OPEN,
260
- backend,
261
- [_("No Cover"), Gtk::ResponseType::REJECT],
262
- [Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL],
263
- [Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT])
156
+ dialog = Gtk::FileChooserDialog.new(title: _("Select a cover image"),
157
+ parent: @book_properties_dialog,
158
+ action: :open,
159
+ buttons: [[_("No Cover"), :reject],
160
+ [Gtk::Stock::CANCEL, :cancel],
161
+ [Gtk::Stock::OPEN, :accept]])
264
162
  dialog.current_folder = @@latest_filechooser_directory
265
163
  response = dialog.run
266
- if response == Gtk::ResponseType::ACCEPT
164
+ case response
165
+ when Gtk::ResponseType::ACCEPT
267
166
  begin
268
167
  @delete_cover_file = false
269
168
  cover = GdkPixbuf::Pixbuf.new(file: dialog.filename)
270
169
  # At this stage the file format is recognized.
271
170
 
272
- if File.exist?(@cover_file)
273
- unless @original_cover_file
274
- # make a back up, but only of the original
275
- @original_cover_file = "#{@cover_file}~"
276
- FileUtils.cp(@cover_file, @original_cover_file)
277
- end
171
+ if File.exist?(@cover_file) && !@original_cover_file
172
+ # make a back up, but only of the original
173
+ @original_cover_file = "#{@cover_file}~"
174
+ FileUtils.cp(@cover_file, @original_cover_file)
278
175
  end
279
176
  if cover.height > COVER_ABSOLUTE_MAXHEIGHT
280
177
  FileUtils.cp(dialog.filename, "#{@cover_file}.orig")
@@ -294,7 +191,7 @@ module Alexandria
294
191
  rescue RuntimeError => ex
295
192
  ErrorDialog.new(@book_properties_dialog, ex.message).display
296
193
  end
297
- elsif response == Gtk::ResponseType::REJECT
194
+ when Gtk::ResponseType::REJECT
298
195
  ## FileUtils.rm_f(@cover_file) # fixing bug #16707
299
196
  @delete_cover_file = true
300
197
 
@@ -347,10 +244,11 @@ module Alexandria
347
244
  def redd_toggled
348
245
  redd_yes = @checkbutton_redd.active?
349
246
  @redd_date.sensitive = redd_yes
350
- if @setup_finished
351
- # don't do this when popping up the dialog for the first time
352
- display_calendar_popup(@redd_date) if redd_yes && @redd_date.text.strip.empty?
353
- end
247
+
248
+ return unless redd_yes && @redd_date.text.strip.empty?
249
+
250
+ # don't do this when popping up the dialog for the first time
251
+ display_calendar_popup(@redd_date) if @setup_finished
354
252
  end
355
253
 
356
254
  private
@@ -363,10 +261,10 @@ module Alexandria
363
261
  @image_rating4,
364
262
  @image_rating5
365
263
  ]
366
- raise "out of range" if rating < 0 || rating > images.length
264
+ raise _("out of range") if rating < 0 || rating > images.length
367
265
 
368
266
  images[0..rating - 1].each { |x| x.pixbuf = Icons::STAR_SET }
369
- images[rating..-1].each { |x| x.pixbuf = Icons::STAR_UNSET }
267
+ images[rating..].each { |x| x.pixbuf = Icons::STAR_UNSET }
370
268
  @current_rating = rating
371
269
  end
372
270
 
@@ -0,0 +1,58 @@
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
+ module CalendarPopup
10
+ def setup_calendar_widgets
11
+ @calendar_popup = Gtk::Popover.new
12
+ @calendar_popup.position = :bottom
13
+
14
+ @calendar = Gtk::Calendar.new
15
+ @calendar.show
16
+ @calendar_popup.add(@calendar)
17
+
18
+ @calendar.signal_connect("day-selected") do
19
+ assign_selected_date
20
+ end
21
+
22
+ @calendar.signal_connect("day-selected-double-click") do
23
+ assign_selected_date
24
+ @calendar_popup.hide
25
+ end
26
+ end
27
+
28
+ def assign_selected_date
29
+ date_arr = @calendar.date
30
+ year = date_arr[0]
31
+ month = date_arr[1] # + 1 # gtk : months 0-indexed, Time.gm : 1-index
32
+ day = date_arr[2]
33
+ time = Time.gm(year, month, day)
34
+ @calendar_popup_for_entry.text = format_date(time)
35
+ end
36
+
37
+ def clear_date_entry(entry)
38
+ entry.text = ""
39
+ end
40
+
41
+ def display_calendar_popup(entry)
42
+ setup_calendar_widgets unless defined? @calendar_popup
43
+
44
+ @calendar_popup_for_entry = entry
45
+ unless entry.text.strip.empty?
46
+ time = parse_date(entry.text)
47
+ unless time.nil?
48
+ @calendar.year = time.year
49
+ @calendar.month = time.month - 1
50
+ @calendar.day = time.day
51
+ end
52
+ end
53
+ @calendar_popup.set_relative_to(entry)
54
+ @calendar_popup.popup
55
+ end
56
+ end
57
+ end
58
+ end