alexandria-book-collection-manager 0.7.9 → 0.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +5 -1
  3. data/.github/workflows/ruby.yml +36 -22
  4. data/.rubocop.yml +12 -3
  5. data/.rubocop_todo.yml +35 -47
  6. data/.simplecov +2 -2
  7. data/CHANGELOG.md +71 -24
  8. data/Gemfile +0 -6
  9. data/Rakefile +5 -5
  10. data/alexandria-book-collection-manager.gemspec +24 -21
  11. data/bin/rake +28 -0
  12. data/bin/rspec +28 -0
  13. data/doc/dependency_decisions.yml +32 -26
  14. data/{bin → exe}/alexandria +1 -3
  15. data/lib/alexandria/about.rb +1 -0
  16. data/lib/alexandria/book_providers/bl_provider.rb +4 -6
  17. data/lib/alexandria/book_providers/{douban.rb → douban_provider.rb} +1 -1
  18. data/lib/alexandria/book_providers/loc_provider.rb +2 -6
  19. data/lib/alexandria/book_providers/sbn_provider.rb +2 -12
  20. data/lib/alexandria/book_providers/thalia_provider.rb +5 -6
  21. data/lib/alexandria/book_providers/{web.rb → website_based_provider.rb} +20 -1
  22. data/lib/alexandria/book_providers/{worldcat.rb → world_cat_provider.rb} +3 -4
  23. data/lib/alexandria/book_providers/z3950_provider.rb +25 -27
  24. data/lib/alexandria/book_providers.rb +14 -10
  25. data/lib/alexandria/config.rb +2 -2
  26. data/lib/alexandria/console.rb +12 -10
  27. data/lib/alexandria/export_format.rb +3 -2
  28. data/lib/alexandria/export_library.rb +35 -40
  29. data/lib/alexandria/import_library.rb +3 -4
  30. data/lib/alexandria/import_library_csv.rb +2 -2
  31. data/lib/alexandria/library_collection.rb +1 -1
  32. data/lib/alexandria/library_store.rb +20 -15
  33. data/lib/alexandria/logging.rb +22 -21
  34. data/lib/alexandria/models/book.rb +1 -2
  35. data/lib/alexandria/models/library.rb +7 -8
  36. data/lib/alexandria/preferences.rb +7 -19
  37. data/lib/alexandria/{book_providers/pseudomarc.rb → pseudo_marc_parser.rb} +2 -2
  38. data/lib/alexandria/scanners/cue_cat.rb +5 -9
  39. data/lib/alexandria/scanners/{keyboard.rb → keyboard_wedge.rb} +3 -3
  40. data/lib/alexandria/scanners.rb +2 -2
  41. data/lib/alexandria/smart_library.rb +9 -5
  42. data/lib/alexandria/ui/acquire_dialog.rb +42 -45
  43. data/lib/alexandria/ui/alert_dialog.rb +3 -3
  44. data/lib/alexandria/ui/barcode_animation.rb +3 -3
  45. data/lib/alexandria/ui/book_properties_dialog.rb +9 -9
  46. data/lib/alexandria/ui/book_properties_dialog_base.rb +13 -14
  47. data/lib/alexandria/ui/builder_base.rb +1 -1
  48. data/lib/alexandria/ui/callbacks.rb +8 -7
  49. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -0
  50. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +1 -0
  51. data/lib/alexandria/ui/export_dialog.rb +1 -0
  52. data/lib/alexandria/ui/{iconview.rb → icon_view_manager.rb} +1 -0
  53. data/lib/alexandria/ui/icons.rb +2 -2
  54. data/lib/alexandria/ui/iconview_tooltips.rb +1 -1
  55. data/lib/alexandria/ui/init.rb +10 -4
  56. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +1 -0
  57. data/lib/alexandria/ui/libraries_combo.rb +1 -0
  58. data/lib/alexandria/ui/listview.rb +2 -0
  59. data/lib/alexandria/ui/main_app.rb +3 -1
  60. data/lib/alexandria/ui/multi_drag_treeview.rb +0 -2
  61. data/lib/alexandria/ui/new_book_dialog.rb +15 -20
  62. data/lib/alexandria/ui/new_book_dialog_manual.rb +7 -7
  63. data/lib/alexandria/ui/new_provider_dialog.rb +1 -0
  64. data/lib/alexandria/ui/new_smart_library_dialog.rb +2 -1
  65. data/lib/alexandria/ui/preferences_dialog.rb +4 -4
  66. data/lib/alexandria/ui/provider_preferences_dialog.rb +1 -0
  67. data/lib/alexandria/ui/really_delete_dialog.rb +1 -0
  68. data/lib/alexandria/ui/sidepane_manager.rb +49 -48
  69. data/lib/alexandria/ui/skip_entry_dialog.rb +1 -0
  70. data/lib/alexandria/ui/smart_library_properties_dialog.rb +1 -0
  71. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +2 -1
  72. data/lib/alexandria/ui/{sound.rb → sound_effects_player.rb} +3 -0
  73. data/lib/alexandria/ui/ui_manager.rb +194 -143
  74. data/lib/alexandria/ui.rb +1 -0
  75. data/lib/alexandria/version.rb +1 -1
  76. data/lib/alexandria/web_themes.rb +1 -1
  77. data/lib/alexandria.rb +6 -5
  78. data/po/Makefile +1 -1
  79. data/po/it.po +64 -82
  80. data/spec/alexandria/book_providers/bl_provider_spec.rb +11 -2
  81. data/spec/alexandria/book_providers/douban_provider_spec.rb +17 -0
  82. data/spec/alexandria/book_providers/loc_provider_spec.rb +10 -2
  83. data/spec/alexandria/book_providers/sbn_provider_spec.rb +10 -2
  84. data/spec/alexandria/book_providers/thalia_provider_spec.rb +9 -1
  85. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +30 -10
  86. data/spec/alexandria/book_providers/z3950_provider_spec.rb +22 -0
  87. data/spec/alexandria/book_spec.rb +5 -3
  88. data/spec/alexandria/console_spec.rb +1 -1
  89. data/spec/alexandria/export_library_spec.rb +65 -19
  90. data/spec/alexandria/library_collection_spec.rb +24 -0
  91. data/spec/alexandria/library_spec.rb +68 -53
  92. data/spec/alexandria/library_store_spec.rb +33 -1
  93. data/spec/alexandria/preferences_spec.rb +7 -7
  94. data/spec/alexandria/pseudo_marc_parser_spec.rb +71 -0
  95. data/spec/alexandria/scanners/cue_cat_spec.rb +11 -4
  96. data/spec/alexandria/scanners/keyboard_wedge_spec.rb +47 -0
  97. data/spec/alexandria/smart_library_spec.rb +7 -5
  98. data/spec/alexandria/ui/about_dialog_spec.rb +2 -2
  99. data/spec/alexandria/ui/acquire_dialog_spec.rb +8 -3
  100. data/spec/alexandria/ui/alert_dialog_spec.rb +6 -4
  101. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +2 -2
  102. data/spec/alexandria/ui/book_properties_dialog_spec.rb +5 -5
  103. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +19 -3
  104. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +2 -2
  105. data/spec/alexandria/ui/error_dialog_spec.rb +14 -3
  106. data/spec/alexandria/ui/export_dialog_spec.rb +6 -6
  107. data/spec/alexandria/ui/{iconview_spec.rb → icon_view_manager_spec.rb} +2 -2
  108. data/spec/alexandria/ui/import_dialog_spec.rb +3 -3
  109. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +2 -2
  110. data/spec/alexandria/ui/main_app_spec.rb +0 -2
  111. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +5 -5
  112. data/spec/alexandria/ui/new_book_dialog_spec.rb +7 -4
  113. data/spec/alexandria/ui/new_provider_dialog_spec.rb +3 -3
  114. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +9 -7
  115. data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
  116. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +22 -7
  117. data/spec/alexandria/ui/really_delete_dialog_spec.rb +2 -2
  118. data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
  119. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +19 -3
  120. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +2 -2
  121. data/spec/alexandria/ui/ui_manager_spec.rb +7 -5
  122. data/spec/end_to_end/basic_run_spec.rb +2 -1
  123. data/spec/spec_helper.rb +26 -33
  124. data/tasks/setup.rb +1 -1
  125. data/util/rake/fileinstall.rb +12 -13
  126. data/util/rake/gettextgenerate.rb +1 -1
  127. data/util/rake/omfgenerate.rb +1 -1
  128. metadata +97 -64
  129. /data/spec/alexandria/ui/{sound_spec.rb → sound_effects_player_spec.rb} +0 -0
@@ -11,6 +11,7 @@ require "alexandria/library_sort_order"
11
11
 
12
12
  module Alexandria
13
13
  module UI
14
+ # rubocop:disable Metrics/ClassLength
14
15
  class UIManager < BuilderBase
15
16
  attr_accessor :main_app, :actiongroup, :appbar, :prefs, :listview, :iconview,
16
17
  :listview_model, :iconview_model, :filtered_model
@@ -18,6 +19,7 @@ module Alexandria
18
19
 
19
20
  include Logging
20
21
  include GetText
22
+
21
23
  GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
22
24
 
23
25
  def initialize(parent)
@@ -237,58 +239,36 @@ module Alexandria
237
239
  end
238
240
  end
239
241
 
242
+ LIST_STORE_COLUMNS = [
243
+ GdkPixbuf::Pixbuf, # COVER_LIST
244
+ GdkPixbuf::Pixbuf, # COVER_ICON
245
+ String, # TITLE
246
+ String, # TITLE_REDUCED
247
+ String, # AUTHORS
248
+ String, # ISBN
249
+ String, # PUBLISHER
250
+ String, # PUBLISH_DATE
251
+ String, # EDITION
252
+ Integer, # RATING
253
+ String, # IDENT
254
+ String, # NOTES
255
+ TrueClass, # REDD
256
+ TrueClass, # OWN
257
+ TrueClass, # WANT
258
+ String, # TAGS
259
+ String # LOANED TO
260
+ ].freeze
261
+
240
262
  def setup_active_model
241
263
  log.debug { "setting up active model" }
242
264
  # The active model.
243
265
 
244
- list = [
245
- GdkPixbuf::Pixbuf, # COVER_LIST
246
- GdkPixbuf::Pixbuf, # COVER_ICON
247
- String, # TITLE
248
- String, # TITLE_REDUCED
249
- String, # AUTHORS
250
- String, # ISBN
251
- String, # PUBLISHER
252
- String, # PUBLISH_DATE
253
- String, # EDITION
254
- Integer, # RATING
255
- String, # IDENT
256
- String, # NOTES
257
- TrueClass, # REDD
258
- TrueClass, # OWN
259
- TrueClass, # WANT
260
- String, # TAGS
261
- String # LOANED TO
262
- ]
263
-
264
- @model = Gtk::ListStore.new(*list)
266
+ @model = Gtk::ListStore.new(*LIST_STORE_COLUMNS)
265
267
 
266
268
  # Filter books according to the search toolbar widgets.
267
269
  @filtered_model = Gtk::TreeModelFilter.new(@model)
268
270
  @filtered_model.set_visible_func do |_model, iter|
269
- # log.debug { "visible_func" }
270
- @filter_books_mode ||= 0
271
- filter = @filter_entry.text
272
- if filter.empty?
273
- true
274
- else
275
- data = case @filter_books_mode
276
- when 0
277
- (iter[Columns::TITLE] || "") +
278
- (iter[Columns::AUTHORS] || "") +
279
- (iter[Columns::ISBN] || "") +
280
- (iter[Columns::PUBLISHER] || "") +
281
- (iter[Columns::NOTES] || "") +
282
- (iter[Columns::TAGS] || "")
283
- when 2 then iter[Columns::TITLE]
284
- when 3 then iter[Columns::AUTHORS]
285
- when 4 then iter[Columns::ISBN]
286
- when 5 then iter[Columns::PUBLISHER]
287
- when 6 then iter[Columns::NOTES]
288
- when 7 then iter[Columns::TAGS]
289
- end
290
- !data.nil? && data.downcase.include?(filter.downcase)
291
- end
271
+ filter_iter(iter, @filter_entry.text)
292
272
  end
293
273
 
294
274
  # Give filter entry the initial keyboard focus.
@@ -296,6 +276,30 @@ module Alexandria
296
276
  log.debug { "done setting up active model" }
297
277
  end
298
278
 
279
+ def filter_iter(iter, filter)
280
+ if filter.empty?
281
+ true
282
+ else
283
+ @filter_books_mode ||= 0
284
+ data = case @filter_books_mode
285
+ when 0
286
+ (iter[Columns::TITLE] || "") +
287
+ (iter[Columns::AUTHORS] || "") +
288
+ (iter[Columns::ISBN] || "") +
289
+ (iter[Columns::PUBLISHER] || "") +
290
+ (iter[Columns::NOTES] || "") +
291
+ (iter[Columns::TAGS] || "")
292
+ when 2 then iter[Columns::TITLE]
293
+ when 3 then iter[Columns::AUTHORS]
294
+ when 4 then iter[Columns::ISBN]
295
+ when 5 then iter[Columns::PUBLISHER]
296
+ when 6 then iter[Columns::NOTES]
297
+ when 7 then iter[Columns::TAGS]
298
+ end
299
+ !data.nil? && data.downcase.include?(filter.downcase)
300
+ end
301
+ end
302
+
299
303
  def on_library_button_press_event(widget, event)
300
304
  log.debug { "library_button_press_event" }
301
305
 
@@ -449,55 +453,56 @@ module Alexandria
449
453
 
450
454
  # Focus is the wrong idiom here.
451
455
  unless @clicking_on_sidepane || (@main_app.focus == @library_listview)
452
- # unless @main_app.focus == @library_listview
456
+ sensizite_action_group_items(books, library)
457
+ sensitize_provider_actions(books)
458
+ end
459
+ @clicking_on_sidepane = false
460
+ end
453
461
 
454
- log.debug { "Currently focused widget: #{@main_app.focus.inspect}" }
455
- log.debug { "#{@library_listview} : #{@library_popup} : #{@listview}" }
456
- log.debug do
457
- "@library_listview: #{@library_listview.has_focus?} " \
458
- "or @library_popup:#{@library_popup.has_focus?}"
459
- end
460
- log.debug { "@library_listview does *NOT* have focus" }
461
- log.debug { "Books are empty: #{books.empty?}" }
462
- @actiongroup["Properties"].sensitive = \
463
- @actiongroup["OnlineInformation"].sensitive = \
464
- books.length == 1
465
- @actiongroup["SelectAll"].sensitive = \
466
- books.length < library.length
467
-
468
- @actiongroup["Delete"].sensitive = \
469
- @actiongroup["DeselectAll"].sensitive = \
470
- @actiongroup["Move"].sensitive =
471
- @actiongroup["SetRating"].sensitive = !books.empty?
472
-
473
- log.debug do
474
- "on_books_selection_changed Delete: #{@actiongroup['Delete'].sensitive?}"
475
- end
462
+ def sensizite_action_group_items(books, library)
463
+ log.debug { "Currently focused widget: #{@main_app.focus.inspect}" }
464
+ log.debug { "#{@library_listview} : #{@library_popup} : #{@listview}" }
465
+ log.debug do
466
+ "@library_listview: #{@library_listview.has_focus?} " \
467
+ "or @library_popup:#{@library_popup.has_focus?}"
468
+ end
469
+ log.debug { "@library_listview does *NOT* have focus" }
470
+ log.debug { "Books are empty: #{books.empty?}" }
476
471
 
472
+ @actiongroup["Properties"].sensitive = @actiongroup["OnlineInformation"].sensitive =
473
+ books.length == 1
474
+ @actiongroup["SelectAll"].sensitive = books.length < library.length
475
+ @actiongroup["DeselectAll"].sensitive = @actiongroup["SetRating"].sensitive =
476
+ !books.empty?
477
+
478
+ can_delete_or_move =
477
479
  if library.is_a?(SmartLibrary)
478
- @actiongroup["Delete"].sensitive =
479
- @actiongroup["Move"].sensitive = false
480
+ false
481
+ else
482
+ !books.empty?
480
483
  end
484
+ @actiongroup["Delete"].sensitive = @actiongroup["Move"].sensitive =
485
+ can_delete_or_move
486
+ end
481
487
 
482
- # Sensitize providers URL
483
- if books.length == 1
484
- b = books.first
485
- # FIXME: Clean up endless negation in this logic
486
- no_urls = true
487
- BookProviders.list.each do |provider|
488
- has_no_url = true
489
- begin
490
- has_no_url = (b.isbn.nil? || b.isbn.strip.empty? || provider.url(b).nil?)
491
- rescue StandardError => ex
492
- log.warn { "Error determining URL from #{provider.name}; #{ex.message}" }
493
- end
494
- @actiongroup[provider.action_name].sensitive = !has_no_url
495
- no_urls = false unless has_no_url
496
- end
497
- @actiongroup["OnlineInformation"].sensitive = false if no_urls
488
+ # Sensitize providers URL
489
+ def sensitize_provider_actions(books)
490
+ return if books.length != 1
491
+
492
+ b = books.first
493
+ # FIXME: Clean up endless negation in this logic
494
+ no_urls = true
495
+ BookProviders.list.each do |provider|
496
+ has_no_url = true
497
+ begin
498
+ has_no_url = b.isbn.nil? || b.isbn.strip.empty? || provider.url(b).nil?
499
+ rescue StandardError => ex
500
+ log.warn { "Error determining URL from #{provider.name}; #{ex.message}" }
498
501
  end
502
+ @actiongroup[provider.action_name].sensitive = !has_no_url
503
+ no_urls = false unless has_no_url
499
504
  end
500
- @clicking_on_sidepane = false
505
+ @actiongroup["OnlineInformation"].sensitive = false if no_urls
501
506
  end
502
507
 
503
508
  def on_switch_page(_notebook, _page, page_num)
@@ -609,8 +614,8 @@ module Alexandria
609
614
 
610
615
  def handle_ruined_books
611
616
  new_message = _(
612
- "The data files for the following books are malformed or empty. Do you wish to" \
613
- " attempt to download new information for them from the online book providers?\n")
617
+ "The data files for the following books are malformed or empty. Do you wish to " \
618
+ "attempt to download new information for them from the online book providers?\n")
614
619
 
615
620
  @libraries.ruined_books.each do |bi|
616
621
  new_message += "\n#{bi[1] || bi[1].inspect}"
@@ -624,7 +629,7 @@ module Alexandria
624
629
  if response_type == Gtk::ResponseType::OK
625
630
  # progress indicator...
626
631
  @progressbar.fraction = 0
627
- @appbar.children.first.visible = true # show the progress bar
632
+ show_progress_bar
628
633
 
629
634
  total_book_count = @libraries.ruined_books.size
630
635
  fraction_per_book = 1.0 / total_book_count
@@ -634,38 +639,8 @@ module Alexandria
634
639
  GLib::Idle.add do
635
640
  ruined_book = @libraries.ruined_books.pop
636
641
  if ruined_book
637
- book, isbn, library = ruined_book
638
- begin
639
- book_rslt = Alexandria::BookProviders.isbn_search(isbn.to_s)
640
- book = book_rslt[0]
641
- cover_uri = book_rslt[1]
642
-
643
- # TODO: if the book was saved okay, make sure the old
644
- # empty yaml file doesn't stick around esp if doing
645
- # isbn-10 --> isbn-13 conversion...
646
- if isbn.size == 10
647
- filename = library.yaml(isbn)
648
- log.debug { "removing old file #{filename}" }
649
- begin
650
- File.delete(filename)
651
- rescue StandardError => ex
652
- log.error { "Could not delete empty file #{filename}" }
653
- end
654
- end
655
-
656
- log.debug do
657
- "Trying to add #{book.title}, #{cover_uri}" \
658
- " in library ''#{library.name}'"
659
- end
660
- library.save_cover(book, cover_uri) unless cover_uri.nil?
661
- library << book
662
- library.save(book)
663
- set_status_label(format(_("Added '%s' to library '%s'"),
664
- book.title, library.name))
665
- rescue StandardError => ex
666
- log.error { "Couldn't add book #{isbn}: #{ex}" }
667
- log.error { ex.backtrace.join("\n") }
668
- end
642
+ _book, isbn, library = ruined_book
643
+ repair_ruined_book(isbn, library)
669
644
 
670
645
  prog_percentage += fraction_per_book
671
646
  @progressbar.fraction = prog_percentage
@@ -680,8 +655,7 @@ module Alexandria
680
655
  # @listview.columns_autosize
681
656
 
682
657
  @progressbar.fraction = 1
683
- ## Hide the progress bar.
684
- @appbar.children.first.visible = false
658
+ hide_progress_bar
685
659
  ## Refresh the status bar.
686
660
  set_status_label("")
687
661
  # on_books_selection_changed
@@ -692,6 +666,75 @@ module Alexandria
692
666
  end
693
667
  end
694
668
 
669
+ def repair_ruined_book(isbn, library)
670
+ book_rslt = Alexandria::BookProviders.isbn_search(isbn.to_s)
671
+ book = book_rslt[0]
672
+ cover_uri = book_rslt[1]
673
+
674
+ # TODO: if the book was saved okay, make sure the old
675
+ # empty yaml file doesn't stick around esp if doing
676
+ # isbn-10 --> isbn-13 conversion...
677
+ if isbn.size == 10
678
+ filename = library.yaml(isbn)
679
+ log.debug { "removing old file #{filename}" }
680
+ begin
681
+ File.delete(filename)
682
+ rescue StandardError => ex
683
+ log.error { "Could not delete empty file #{filename}" }
684
+ end
685
+ end
686
+
687
+ log.debug do
688
+ "Trying to add #{book.title}, #{cover_uri} " \
689
+ "in library ''#{library.name}'"
690
+ end
691
+ library.save_cover(book, cover_uri) unless cover_uri.nil?
692
+ library << book
693
+ library.save(book)
694
+ set_status_label(format(_("Added '%s' to library '%s'"),
695
+ book.title, library.name))
696
+ rescue StandardError => ex
697
+ log.error { "Couldn't add book #{isbn}: #{ex}" }
698
+ log.error { ex.backtrace.join("\n") }
699
+ end
700
+
701
+ def progress_bar
702
+ @progress_bar ||= @appbar.children.first
703
+ end
704
+
705
+ def show_progress_bar
706
+ progress_bar.visible = true
707
+ end
708
+
709
+ def hide_progress_bar
710
+ progress_bar.visible = false
711
+ end
712
+
713
+ def start_progress_bar_pulsing(dialog)
714
+ GLib::Idle.add do
715
+ show_progress_bar
716
+ @progress_pulsing = GLib::Timeout.add(100) do
717
+ if dialog.destroyed?
718
+ @progress_pulsing = nil
719
+ hide_progress_bar
720
+ false
721
+ else
722
+ progress_bar.pulse
723
+ true
724
+ end
725
+ end
726
+ false
727
+ end
728
+ end
729
+
730
+ def stop_progress_bar_pulsing
731
+ GLib::Idle.add do
732
+ hide_progress_bar
733
+ GLib::Source.remove(@progress_pulsing) if @progress_pulsing
734
+ false
735
+ end
736
+ end
737
+
695
738
  def cache_scaled_icon(icon, width, height)
696
739
  log.debug { "cache_scaled_icon #{icon}, #{width}, #{height}" }
697
740
  @cache ||= {}
@@ -703,11 +746,9 @@ module Alexandria
703
746
  REDUCE_TITLE_REGEX = Regexp.new("^(.{#{ICON_TITLE_MAXLEN}}).*$")
704
747
 
705
748
  def fill_iter_with_book(iter, book)
706
- log.debug { "fill iter #{iter} with book #{book}" }
707
749
  iter[Columns::IDENT] = book.ident.to_s
708
750
  iter[Columns::TITLE] = book.title
709
- title = book.title.sub(REDUCE_TITLE_REGEX, '\1...')
710
- iter[Columns::TITLE_REDUCED] = title
751
+ iter[Columns::TITLE_REDUCED] = reduced_title(book.title)
711
752
  iter[Columns::AUTHORS] = book.authors.join(", ")
712
753
  iter[Columns::ISBN] = book.isbn.to_s
713
754
  iter[Columns::PUBLISHER] = book.publisher
@@ -715,30 +756,37 @@ module Alexandria
715
756
  iter[Columns::EDITION] = book.edition
716
757
  iter[Columns::NOTES] = (book.notes || "")
717
758
  iter[Columns::LOANED_TO] = (book.loaned_to || "")
718
- rating = (book.rating || Book::DEFAULT_RATING)
759
+
760
+ rating = book.rating || Book::DEFAULT_RATING
719
761
  # ascending order is the default
720
762
  iter[Columns::RATING] = Book::MAX_RATING_STARS - rating
763
+
721
764
  iter[Columns::OWN] = book.own?
722
765
  iter[Columns::REDD] = book.redd?
723
766
  iter[Columns::WANT] = book.want?
724
- iter[Columns::TAGS] = if book.tags
725
- book.tags.join(",")
726
- else
727
- ""
728
- end
767
+ iter[Columns::TAGS] = book.tags&.join(",") || ""
729
768
 
730
769
  icon = Icons.cover(selected_library, book)
731
- log.debug { "Setting icon #{icon} for book #{book.title}" }
732
- iter[Columns::COVER_LIST] = cache_scaled_icon(icon, 20, 25)
770
+ iter[Columns::COVER_LIST] = cover_list_icon(icon)
771
+ iter[Columns::COVER_ICON] = cover_icon(icon, rating)
772
+ end
773
+
774
+ def reduced_title(title)
775
+ title.sub(REDUCE_TITLE_REGEX, '\1...')
776
+ end
777
+
778
+ def cover_list_icon(icon)
779
+ cache_scaled_icon(icon, 20, 25)
780
+ end
733
781
 
782
+ def cover_icon(icon, rating)
734
783
  if icon.height > ICON_HEIGHT
735
784
  new_width = icon.width / (icon.height / ICON_HEIGHT.to_f)
736
785
  new_height = [ICON_HEIGHT, icon.height].min
737
786
  icon = cache_scaled_icon(icon, new_width, new_height)
738
787
  end
739
788
  icon = Icons.tag_icon(icon, Icons::FAVORITE_TAG) if rating == Book::MAX_RATING_STARS
740
- iter[Columns::COVER_ICON] = icon
741
- log.debug { "Full iter: " + (0..15).map { |num| iter[num].inspect }.join(", ") }
789
+ icon
742
790
  end
743
791
 
744
792
  def append_book(book, _tail = nil)
@@ -807,8 +855,10 @@ module Alexandria
807
855
  @iconview.freeze
808
856
  @listview.freeze
809
857
  @model.clear
858
+
810
859
  @progressbar.fraction = 0
811
- @appbar.children.first.visible = true # show the progress bar
860
+ show_progress_bar
861
+
812
862
  set_status_label(_("Loading '%s'...") % library.name)
813
863
  total = library.length
814
864
  log.debug { "library #{library.name} length #{library.length}" }
@@ -833,9 +883,10 @@ module Alexandria
833
883
  @listview.unfreeze # NEW / bdewey
834
884
  @filtered_model.refilter
835
885
  @listview.columns_autosize
886
+
836
887
  @progressbar.fraction = 1
837
- # Hide the progress bar.
838
- @appbar.children.first.visible = false
888
+ hide_progress_bar
889
+
839
890
  # Refresh the status bar.
840
891
  on_books_selection_changed
841
892
  @library_listview.set_sensitive(true)
@@ -850,7 +901,7 @@ module Alexandria
850
901
  log.debug { "selected_library" }
851
902
  if (iter = @library_listview.selection.selected)
852
903
  target_name = iter[1]
853
- @libraries.all_libraries.find { |it| it.name == target_name }
904
+ @libraries.all_libraries.find { _1.name == target_name }
854
905
  else
855
906
  @libraries.all_libraries.first
856
907
  end
@@ -1033,9 +1084,8 @@ module Alexandria
1033
1084
 
1034
1085
  @actiongroup.remove_action(action)
1035
1086
  end
1036
- actions = []
1037
- @libraries.all_regular_libraries.each do |library|
1038
- actions << [
1087
+ actions = @libraries.all_regular_libraries.map do |library|
1088
+ [
1039
1089
  library.action_name, nil,
1040
1090
  _("In '_%s'") % library.name,
1041
1091
  nil, nil, proc { move_selected_books_to_library(library) }
@@ -1192,5 +1242,6 @@ module Alexandria
1192
1242
  @filtered_model.convert_path_to_child_path(filter_path) if filter_path
1193
1243
  end
1194
1244
  end
1245
+ # rubocop:enable Metrics/ClassLength
1195
1246
  end
1196
1247
  end
data/lib/alexandria/ui.rb CHANGED
@@ -30,6 +30,7 @@ require "alexandria/ui/main_app"
30
30
  module Alexandria
31
31
  module UI
32
32
  include Logging
33
+
33
34
  def self.init_icons
34
35
  log.info { "Initializing Icons" }
35
36
  Icons.init
@@ -5,7 +5,7 @@
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
7
  module Alexandria
8
- VERSION = "0.7.9"
8
+ VERSION = "0.7.11"
9
9
  DATA_VERSION = "0.6.3"
10
10
  DISPLAY_VERSION = VERSION
11
11
  end
@@ -39,7 +39,7 @@ module Alexandria
39
39
  File.join(Alexandria::Config::DATA_DIR, "web-themes"),
40
40
 
41
41
  # User dir
42
- File.join(ENV["HOME"], ".alexandria", ".web-themes")
42
+ File.join(Dir.home, ".alexandria", ".web-themes")
43
43
  ]
44
44
  themes_dir.map { |x| load(x) }.flatten
45
45
  end
data/lib/alexandria.rb CHANGED
@@ -21,10 +21,11 @@ require "alexandria/logging"
21
21
  require "alexandria/about"
22
22
 
23
23
  module Alexandria
24
- def self.set_proxy
25
- if !ENV["http_proxy"].nil? && URI.parse(ENV["http_proxy"]).userinfo.nil?
26
- ENV["http_proxy"] = nil
27
- end
24
+ def self.clear_invalid_proxy
25
+ current_proxy = ENV.fetch("http_proxy", nil)
26
+ return if current_proxy.nil?
27
+
28
+ ENV["http_proxy"] = nil if URI.parse(current_proxy).userinfo.nil?
28
29
  end
29
30
 
30
31
  def self.set_log_level
@@ -33,7 +34,7 @@ module Alexandria
33
34
  end
34
35
 
35
36
  def self.main
36
- set_proxy
37
+ clear_invalid_proxy
37
38
  set_log_level
38
39
  Alexandria::UI.main
39
40
  end
data/po/Makefile CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  POT=./alexandria.pot
3
3
 
4
- RUBY=../bin/alexandria $(shell find ../lib -name '*.rb' -and -not -path '*macui*')
4
+ RUBY=../exe/alexandria $(shell find ../lib -name '*.rb' -and -not -path '*macui*')
5
5
 
6
6
  GLADE=$(shell find ../share/alexandria/glade -name '*.glade')
7
7