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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Alexandria
4
4
  module Config
5
- SHARE_DIR = File.expand_path('../../share', File.dirname(__FILE__))
5
+ SHARE_DIR = File.expand_path("../../share", File.dirname(__FILE__))
6
6
  SOUNDS_DIR = "#{SHARE_DIR}/sounds/alexandria"
7
7
  DATA_DIR = "#{SHARE_DIR}/alexandria"
8
8
  MAIN_DATA_DIR = DATA_DIR
@@ -9,11 +9,11 @@ module Alexandria
9
9
  collection = Alexandria::LibraryCollection.instance
10
10
  collection.reload
11
11
  libraries = collection.all_regular_libraries
12
- output_string = ''
12
+ output_string = ""
13
13
  @books = libraries.flatten
14
14
  @books.each do |book|
15
- book_authors = book.authors.join(' & ') if authors
16
- output_string += [book.title, book_authors].join(', ') + "\n"
15
+ book_authors = book.authors.join(" & ") if authors
16
+ output_string += [book.title, book_authors].join(", ") + "\n"
17
17
  end
18
18
  output_string
19
19
  end
@@ -0,0 +1,37 @@
1
+ # This file is automatically generated by the alexandria installer.
2
+ # Do not edit it directly.
3
+
4
+ module Alexandria
5
+ class Preferences
6
+ DEFAULT_VALUES = {
7
+ "position" => [0, 0],
8
+ "size" => [640, 480],
9
+ "maximized" => false,
10
+ "sidepane_position" => 140,
11
+ "view_as" => 0,
12
+ "arrange_icons_mode" => 0,
13
+ "reverse_icons" => false,
14
+ "selected_library" => "",
15
+ "barcode_scanner" => "CueCat",
16
+ "play_scanning_sound" => true,
17
+ "play_scan_sound" => true,
18
+ "toolbar_visible" => true,
19
+ "sidepane_visible" => true,
20
+ "statusbar_visible" => true,
21
+ "col_authors_visible" => true,
22
+ "col_edition_visible" => true,
23
+ "col_isbn_visible" => true,
24
+ "col_publisher_visible" => true,
25
+ "col_publish_date_visible" => true,
26
+ "col_loaned_to_visible" => true,
27
+ "col_rating_visible" => true,
28
+ "col_redd_visible" => true,
29
+ "col_own_visible" => true,
30
+ "col_want_visible" => true,
31
+ "col_tags_visible" => true,
32
+ "cols_width" => "{}",
33
+ "providers_priority" => ["Amazon", "BarnesAndNoble", "AdLibris", "Proxis", "Thalia", "Siciliano", "WorldCat", "LOC", "BL", "SBN"],
34
+ "view_advanced_settings" => false
35
+ }
36
+ end
37
+ end
@@ -63,10 +63,11 @@ module Alexandria
63
63
 
64
64
  id, procedure, args, need_retval = ary
65
65
  retval = procedure.call(*args)
66
- if need_retval
67
- @protect_pending_retvals.synchronize do
68
- @pending_retvals << [id, retval]
69
- end
66
+
67
+ return unless need_retval
68
+
69
+ @protect_pending_retvals.synchronize do
70
+ @pending_retvals << [id, retval]
70
71
  end
71
72
  end
72
73
 
@@ -81,14 +82,14 @@ module Alexandria
81
82
  @id += 1
82
83
  @pending_calls << [@id, procedure, args, need_retval]
83
84
  end
84
- if need_retval
85
- loop do
86
- @protect_pending_retvals.synchronize do
87
- ary = @pending_retvals.find { |id, _retval| id == @id }
88
- if ary
89
- @pending_retvals.delete(ary)
90
- return ary[1]
91
- end
85
+ return unless need_retval
86
+
87
+ loop do
88
+ @protect_pending_retvals.synchronize do
89
+ ary = @pending_retvals.find { |id, _retval| id == @id }
90
+ if ary
91
+ @pending_retvals.delete(ary)
92
+ return ary[1]
92
93
  end
93
94
  end
94
95
  end
@@ -11,17 +11,17 @@ module Alexandria
11
11
  include GetText
12
12
  include Logging
13
13
  extend GetText
14
- bindtextdomain(Alexandria::TEXTDOMAIN, charset: 'UTF-8')
14
+ bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8")
15
15
 
16
16
  def self.all
17
17
  [
18
- new(_('Archived ONIX XML'), 'onix.tbz2', :export_as_onix_xml_archive),
19
- new(_('Archived Tellico XML'), 'tc', :export_as_tellico_xml_archive),
20
- new(_('BibTeX'), 'bib', :export_as_bibtex),
21
- new(_('CSV list'), 'csv', :export_as_csv_list),
22
- new(_('ISBN List'), 'txt', :export_as_isbn_list),
23
- new(_('iPod Notes'), nil, :export_as_ipod_notes),
24
- new(_('HTML Web Page'), nil, :export_as_html, true)
18
+ new(_("Archived ONIX XML"), "onix.tbz2", :export_as_onix_xml_archive),
19
+ new(_("Archived Tellico XML"), "tc", :export_as_tellico_xml_archive),
20
+ new(_("BibTeX"), "bib", :export_as_bibtex),
21
+ new(_("CSV list"), "csv", :export_as_csv_list),
22
+ new(_("ISBN List"), "txt", :export_as_isbn_list),
23
+ new(_("iPod Notes"), nil, :export_as_ipod_notes),
24
+ new(_("HTML Web Page"), nil, :export_as_html, true)
25
25
  ]
26
26
  end
27
27
 
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require 'csv'
8
- require 'image_size'
9
- require 'tmpdir'
7
+ require "csv"
8
+ require "image_size"
9
+ require "tmpdir"
10
10
 
11
11
  module Alexandria
12
12
  class ExportLibrary
@@ -36,41 +36,38 @@ module Alexandria
36
36
  end
37
37
 
38
38
  def export_as_onix_xml_archive(filename)
39
- File.open(File.join(Dir.tmpdir, 'onix.xml'), 'w') do |io|
39
+ dir = Dir.mktmpdir
40
+ File.open(File.join(dir, "onix.xml"), "w") do |io|
40
41
  to_onix_document.write(io, 0)
41
42
  end
42
- copy_covers(File.join(Dir.tmpdir, 'images'))
43
- Dir.chdir(Dir.tmpdir) do
43
+ copy_covers(File.join(dir, "images"))
44
+ Dir.chdir(dir) do
44
45
  output = `tar -cjf \"#{filename}\" onix.xml images 2>&1`
45
46
  raise output unless $CHILD_STATUS.success?
46
47
  end
47
- FileUtils.rm_rf(File.join(Dir.tmpdir, 'images'))
48
- FileUtils.rm(File.join(Dir.tmpdir, 'onix.xml'))
48
+ FileUtils.rm_rf(File.join(dir, "images"))
49
+ FileUtils.rm(File.join(dir, "onix.xml"))
50
+ ensure
51
+ FileUtils.remove_entry dir
49
52
  end
50
53
 
51
54
  def export_as_tellico_xml_archive(filename)
52
- File.open(File.join(Dir.tmpdir, 'tellico.xml'), 'w') do |io|
53
- begin
54
- to_tellico_document.write(io, 0)
55
- rescue StandardError => ex
56
- puts ex.message
57
- puts ex.backtrace
58
- raise ex
59
- end
55
+ File.open(File.join(Dir.tmpdir, "tellico.xml"), "w") do |io|
56
+ to_tellico_document.write(io, 0)
60
57
  end
61
- copy_covers(File.join(Dir.tmpdir, 'images'))
58
+ copy_covers(File.join(Dir.tmpdir, "images"))
62
59
  Dir.chdir(Dir.tmpdir) do
63
60
  output = `zip -q -r \"#{filename}\" tellico.xml images 2>&1`
64
61
  raise output unless $CHILD_STATUS.success?
65
62
  end
66
- FileUtils.rm_rf(File.join(Dir.tmpdir, 'images'))
67
- FileUtils.rm(File.join(Dir.tmpdir, 'tellico.xml'))
63
+ FileUtils.rm_rf(File.join(Dir.tmpdir, "images"))
64
+ FileUtils.rm(File.join(Dir.tmpdir, "tellico.xml"))
68
65
  end
69
66
 
70
67
  def export_as_isbn_list(filename)
71
- File.open(filename, 'w') do |io|
68
+ File.open(filename, "w") do |io|
72
69
  each do |book|
73
- io.puts((book.isbn || ''))
70
+ io.puts((book.isbn || ""))
74
71
  end
75
72
  end
76
73
  end
@@ -78,17 +75,17 @@ module Alexandria
78
75
  def export_as_html(filename, theme)
79
76
  FileUtils.mkdir(filename) unless File.exist?(filename)
80
77
  Dir.chdir(filename) do
81
- copy_covers('pixmaps')
82
- FileUtils.cp_r(theme.pixmaps_directory, 'pixmaps') if theme.has_pixmaps?
83
- FileUtils.cp(theme.css_file, '.')
84
- File.open('index.html', 'w') do |io|
78
+ copy_covers("pixmaps")
79
+ FileUtils.cp_r(theme.pixmaps_directory, "pixmaps") if theme.has_pixmaps?
80
+ FileUtils.cp(theme.css_file, ".")
81
+ File.open("index.html", "w") do |io|
85
82
  io << to_xhtml(File.basename(theme.css_file))
86
83
  end
87
84
  end
88
85
  end
89
86
 
90
87
  def export_as_bibtex(filename)
91
- File.open(filename, 'w') do |io|
88
+ File.open(filename, "w") do |io|
92
89
  io << to_bibtex
93
90
  end
94
91
  end
@@ -97,27 +94,28 @@ module Alexandria
97
94
  FileUtils.mkdir(filename) unless File.exist?(filename)
98
95
  tempdir = Dir.getwd
99
96
  Dir.chdir(filename)
100
- copy_covers('pixmaps')
101
- File.open('index.linx', 'w') do |io|
102
- io.puts '<TITLE>' + name + '</TITLE>'
97
+ copy_covers("pixmaps")
98
+ File.open("index.linx", "w") do |io|
99
+ io.puts "<TITLE>" + name + "</TITLE>"
103
100
  each do |book|
104
- io.puts '<A HREF="' + book.ident + '">' + book.title + '</A>'
101
+ io.puts '<A HREF="' + book.ident + '">' + book.title + "</A>"
105
102
  end
106
103
  io.close
107
104
  end
108
105
  each do |book|
109
- File.open(book.ident, 'w') do |io|
106
+ File.open(book.ident, "w") do |io|
110
107
  io.puts "<TITLE>#{book.title} </TITLE>"
111
108
  # put a link to the book's cover. only works on iPod 5G and above(?).
112
109
  if File.exist?(cover(book))
113
- io.puts '<A HREF="pixmaps/' + book.ident + '.jpg' + '">' + book.title + '</A>'
110
+ io.puts '<A HREF="pixmaps/' + book.ident + ".jpg" + '">' + book.title + "</A>"
114
111
  else
115
112
  io.puts book.title
116
113
  end
117
- io.puts book.authors.join(', ')
114
+ io.puts book.authors.join(", ")
118
115
  io.puts book.edition
119
- io.puts((book.isbn || ''))
120
- # we need to close the files so the iPod can be ejected/unmounted without us closing Alexandria
116
+ io.puts((book.isbn || ""))
117
+ # we need to close the files so the iPod can be ejected/unmounted
118
+ # without us closing Alexandria
121
119
  io.close
122
120
  end
123
121
  end
@@ -126,84 +124,83 @@ module Alexandria
126
124
  end
127
125
 
128
126
  def export_as_csv_list(filename)
129
- CSV.open(filename, 'w', col_sep: ';') do |csv|
130
- csv << ['Title', 'Authors', 'Publisher', 'Edition', 'ISBN', 'Year Published',
131
- "Rating(#{Book::DEFAULT_RATING} to #{Book::MAX_RATING_STARS})", 'Notes',
132
- 'Want?', 'Read?', 'Own?', 'Tags']
127
+ CSV.open(filename, "w", col_sep: ";") do |csv|
128
+ csv << ["Title", "Authors", "Publisher", "Edition", "ISBN", "Year Published",
129
+ "Rating(#{Book::DEFAULT_RATING} to #{Book::MAX_RATING_STARS})", "Notes",
130
+ "Want?", "Read?", "Own?", "Tags"]
133
131
  each do |book|
134
- csv << [book.title, book.authors.join(', '), book.publisher, book.edition, book.isbn,
135
- book.publishing_year, book.rating, book.notes,
136
- (book.want ? '1' : '0'), (book.redd ? '1' : '0'), (book.own ? '1' : '0'),
137
- (book.tags ? book.tags.join(', ') : '')]
132
+ csv << [book.title, book.authors.join(", "), book.publisher, book.edition,
133
+ book.isbn, book.publishing_year, book.rating, book.notes,
134
+ (book.want ? "1" : "0"), (book.redd ? "1" : "0"), (book.own ? "1" : "0"),
135
+ (book.tags ? book.tags.join(", ") : "")]
138
136
  end
139
137
  end
140
138
  end
141
139
 
142
140
  private
143
141
 
144
- ONIX_DTD_URL = 'http://www.editeur.org/onix/2.1/reference/onix-international.dtd'
142
+ ONIX_DTD_URL = "http://www.editeur.org/onix/2.1/reference/onix-international.dtd"
145
143
  def to_onix_document
146
144
  doc = REXML::Document.new
147
145
  doc << REXML::XMLDecl.new
148
- doc << REXML::DocType.new('ONIXMessage',
146
+ doc << REXML::DocType.new("ONIXMessage",
149
147
  "SYSTEM \"#{ONIX_DTD_URL}\"")
150
- msg = doc.add_element('ONIXMessage')
151
- header = msg.add_element('Header')
152
- header.add_element('FromCompany').text = 'Alexandria'
153
- header.add_element('FromPerson').text = Etc.getlogin
148
+ msg = doc.add_element("ONIXMessage")
149
+ header = msg.add_element("Header")
150
+ header.add_element("FromCompany").text = "Alexandria"
151
+ header.add_element("FromPerson").text = Etc.getlogin
154
152
  now = Time.now
155
- header.add_element('SentDate').text = format('%.4d%.2d%.2d%.2d%.2d',
156
- now.year, now.month, now.day, now.hour, now.min)
157
- header.add_element('MessageNote').text = name
153
+ header.add_element("SentDate").text = now.strftime("%Y%m%d%H%M")
154
+ header.add_element("MessageNote").text = name
158
155
  @sorted.each_with_index do |book, idx|
159
156
  # fields that are missing: edition and rating.
160
- prod = msg.add_element('Product')
161
- prod.add_element('RecordReference').text = idx
162
- prod.add_element('NotificationType').text = '03' # confirmed
163
- prod.add_element('RecordSourceName').text =
164
- 'Alexandria ' + Alexandria::DISPLAY_VERSION
165
- prod.add_element('ISBN').text = (book.isbn || '')
166
- prod.add_element('ProductForm').text = 'BA' # book
167
- prod.add_element('DistinctiveTitle').text = book.title
157
+ prod = msg.add_element("Product")
158
+ prod.add_element("RecordReference").text = idx
159
+ prod.add_element("NotificationType").text = "03" # confirmed
160
+ prod.add_element("RecordSourceName").text =
161
+ "Alexandria " + Alexandria::DISPLAY_VERSION
162
+ prod.add_element("ISBN").text = (book.isbn || "")
163
+ prod.add_element("ProductForm").text = "BA" # book
164
+ prod.add_element("DistinctiveTitle").text = book.title
168
165
  unless book.authors.empty?
169
166
  book.authors.each do |author|
170
- elem = prod.add_element('Contributor')
167
+ elem = prod.add_element("Contributor")
171
168
  # author
172
- elem.add_element('ContributorRole').text = 'A01'
173
- elem.add_element('PersonName').text = author
169
+ elem.add_element("ContributorRole").text = "A01"
170
+ elem.add_element("PersonName").text = author
174
171
  end
175
172
  end
176
173
  if book.notes && !book.notes.empty?
177
- elem = prod.add_element('OtherText')
174
+ elem = prod.add_element("OtherText")
178
175
  # reader description
179
- elem.add_element('TextTypeCode').text = '12'
180
- elem.add_element('TextFormat').text = '00' # ASCII
181
- elem.add_element('Text').text = book.notes
176
+ elem.add_element("TextTypeCode").text = "12"
177
+ elem.add_element("TextFormat").text = "00" # ASCII
178
+ elem.add_element("Text").text = book.notes
182
179
  end
183
180
  if File.exist?(cover(book))
184
- elem = prod.add_element('MediaFile')
181
+ elem = prod.add_element("MediaFile")
185
182
  # front cover image
186
- elem.add_element('MediaFileTypeCode').text = '04'
187
- elem.add_element('MediaFileFormatCode').text =
188
- (Library.jpeg?(cover(book)) ? '03' : '02')
183
+ elem.add_element("MediaFileTypeCode").text = "04"
184
+ elem.add_element("MediaFileFormatCode").text =
185
+ (Library.jpeg?(cover(book)) ? "03" : "02")
189
186
  # filename
190
- elem.add_element('MediaFileLinkTypeCode').text = '06'
191
- elem.add_element('MediaFileLink').text =
192
- File.join('images', final_cover(book))
187
+ elem.add_element("MediaFileLinkTypeCode").text = "06"
188
+ elem.add_element("MediaFileLink").text =
189
+ File.join("images", final_cover(book))
193
190
  end
194
191
  if book.isbn
195
- BookProviders.each do |provider|
196
- elem = prod.add_element('ProductWebsite')
197
- elem.add_element('ProductWebsiteDescription').text =
192
+ BookProviders.list.each do |provider|
193
+ elem = prod.add_element("ProductWebsite")
194
+ elem.add_element("ProductWebsiteDescription").text =
198
195
  provider.fullname
199
- elem.add_element('ProductWebsiteLink').text =
196
+ elem.add_element("ProductWebsiteLink").text =
200
197
  provider.url(book)
201
198
  end
202
199
  end
203
- elem = prod.add_element('Publisher')
204
- elem.add_element('PublishingRole').text = '01'
205
- elem.add_element('PublisherName').text = book.publisher
206
- prod.add_element('PublicationDate').text = book.publishing_year
200
+ elem = prod.add_element("Publisher")
201
+ elem.add_element("PublishingRole").text = "01"
202
+ elem.add_element("PublisherName").text = book.publisher
203
+ prod.add_element("PublicationDate").text = book.publishing_year
207
204
  end
208
205
  doc
209
206
  end
@@ -213,49 +210,51 @@ module Alexandria
213
210
  # http://periapsis.org/tellico/doc/hacking.html
214
211
  doc = REXML::Document.new
215
212
  doc << REXML::XMLDecl.new
216
- doc << REXML::DocType.new('tellico',
213
+ doc << REXML::DocType.new("tellico",
217
214
  'PUBLIC "-//Robby Stephenson/DTD Tellico V7.0//EN"' \
218
215
  ' "http://periapsis.org/tellico/dtd/v7/tellico.dtd"')
219
- tellico = doc.add_element('tellico')
220
- tellico.add_attribute('syntaxVersion', '7')
221
- tellico.add_namespace('http://periapsis.org/tellico/')
222
- collection = tellico.add_element('collection')
223
- collection.add_attribute('title', name)
224
- collection.add_attribute('type', '2')
225
- fields = collection.add_element('fields')
226
- field1 = fields.add_element('field')
216
+ tellico = doc.add_element("tellico")
217
+ tellico.add_attribute("syntaxVersion", "7")
218
+ tellico.add_namespace("http://periapsis.org/tellico/")
219
+ collection = tellico.add_element("collection")
220
+ collection.add_attribute("title", name)
221
+ collection.add_attribute("type", "2")
222
+ fields = collection.add_element("fields")
223
+ field1 = fields.add_element("field")
227
224
  # a field named _default implies adding all default book
228
225
  # collection fields
229
- field1.add_attribute('name', '_default')
230
- images = collection.add_element('images')
226
+ field1.add_attribute("name", "_default")
227
+ images = collection.add_element("images")
231
228
  @sorted.each_with_index do |book, idx|
232
- entry = collection.add_element('entry')
229
+ entry = collection.add_element("entry")
233
230
  new_index = (idx + 1).to_s
234
- entry.add_attribute('id', new_index)
231
+ entry.add_attribute("id", new_index)
235
232
  # translate the binding
236
- entry.add_element('title').text = book.title
237
- entry.add_element('isbn').text = (book.isbn || '')
238
- entry.add_element('pub_year').text = book.publishing_year
239
- entry.add_element('binding').text = book.edition
240
- entry.add_element('publisher').text = book.publisher
233
+ entry.add_element("title").text = book.title
234
+ entry.add_element("isbn").text = (book.isbn || "")
235
+ entry.add_element("pub_year").text = book.publishing_year
236
+ entry.add_element("binding").text = book.edition
237
+ entry.add_element("publisher").text = book.publisher
241
238
  unless book.authors.empty?
242
- authors = entry.add_element('authors')
239
+ authors = entry.add_element("authors")
243
240
  book.authors.each do |author|
244
- authors.add_element('author').text = author
241
+ authors.add_element("author").text = author
245
242
  end
246
243
  end
247
- entry.add_element('read').text = book.redd.to_s if book.redd
248
- entry.add_element('loaned').text = book.loaned.to_s if book.loaned
249
- entry.add_element('rating').text = book.rating unless book.rating == Book::DEFAULT_RATING
250
- entry.add_element('comments').text = book.notes if book.notes && !book.notes.empty?
244
+ entry.add_element("read").text = book.redd.to_s if book.redd
245
+ entry.add_element("loaned").text = book.loaned.to_s if book.loaned
246
+ unless book.rating == Book::DEFAULT_RATING
247
+ entry.add_element("rating").text = book.rating
248
+ end
249
+ entry.add_element("comments").text = book.notes if book.notes && !book.notes.empty?
251
250
  if File.exist?(cover(book))
252
- entry.add_element('cover').text = final_cover(book)
253
- image = images.add_element('image')
254
- image.add_attribute('id', final_cover(book))
251
+ entry.add_element("cover").text = final_cover(book)
252
+ image = images.add_element("image")
253
+ image.add_attribute("id", final_cover(book))
255
254
  image_s = ImageSize.new(IO.read(cover(book)))
256
- image.add_attribute('height', image_s.height.to_s)
257
- image.add_attribute('width', image_s.width.to_s)
258
- image.add_attribute('format', image_s.format)
255
+ image.add_attribute("height", image_s.height.to_s)
256
+ image.add_attribute("width", image_s.width.to_s)
257
+ image.add_attribute("format", image_s.format)
259
258
  end
260
259
  end
261
260
  doc
@@ -264,16 +263,16 @@ module Alexandria
264
263
  def xhtml_escape(str)
265
264
  escaped = str.dup
266
265
  # used to occasionally use CGI.escapeHTML
267
- escaped.gsub!(/&/, '&amp;')
268
- escaped.gsub!(/</, '&lt;')
269
- escaped.gsub!(/>/, '&gt;')
270
- escaped.gsub!(/\"/, '&quot;')
266
+ escaped.gsub!(/&/, "&amp;")
267
+ escaped.gsub!(/</, "&lt;")
268
+ escaped.gsub!(/>/, "&gt;")
269
+ escaped.gsub!(/"/, "&quot;")
271
270
  escaped
272
271
  end
273
272
 
274
273
  def to_xhtml(css)
275
- generator = 'Alexandria ' + Alexandria::DISPLAY_VERSION
276
- xhtml = +''
274
+ generator = "Alexandria " + Alexandria::DISPLAY_VERSION
275
+ xhtml = +""
277
276
  xhtml << <<~EOS
278
277
  <?xml version="1.0" encoding="UTF-8"?>
279
278
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
@@ -326,7 +325,7 @@ module Alexandria
326
325
  <li class="book_author">#{xhtml_escape(author)}</li>
327
326
  EOS
328
327
  end
329
- xhtml << '</ul>'
328
+ xhtml << "</ul>"
330
329
  end
331
330
 
332
331
  unless book.edition.nil?
@@ -356,15 +355,15 @@ module Alexandria
356
355
  end
357
356
 
358
357
  def to_bibtex
359
- generator = 'Alexandria ' + Alexandria::DISPLAY_VERSION
360
- bibtex = +''
358
+ generator = "Alexandria " + Alexandria::DISPLAY_VERSION
359
+ bibtex = +""
361
360
  bibtex << "\%Generated on #{Date.today} by: #{generator}\n"
362
361
  bibtex << "\%\n"
363
362
  bibtex << "\n"
364
363
 
365
364
  auths = Hash.new(0)
366
365
  each do |book|
367
- k = (book.authors[0] || 'Anonymous').split[0]
366
+ k = (book.authors[0] || "Anonymous").split[0]
368
367
  if auths.key?(k)
369
368
  auths[k] += 1
370
369
  else
@@ -382,27 +381,29 @@ module Alexandria
382
381
  bibtex << "\",\n"
383
382
  bibtex << "title = \"#{latex_escape(book.title)}\",\n"
384
383
  bibtex << "publisher = \"#{latex_escape(book.publisher)}\",\n"
385
- bibtex << "OPTnote = \"#{latex_escape(book.notes)}\",\n" if book.notes && !book.notes.empty?
384
+ if book.notes && !book.notes.empty?
385
+ bibtex << "OPTnote = \"#{latex_escape(book.notes)}\",\n"
386
+ end
386
387
  # year is a required field in bibtex @BOOK
387
- bibtex << 'year = ' + (book.publishing_year || '"n/a"').to_s + "\n"
388
+ bibtex << "year = " + (book.publishing_year || '"n/a"').to_s + "\n"
388
389
  bibtex << "}\n\n"
389
390
  end
390
391
  bibtex
391
392
  end
392
393
 
393
394
  def latex_escape(str)
394
- return '' if str.nil?
395
+ return "" if str.nil?
395
396
 
396
397
  my_str = str.dup
397
398
  my_str.gsub!(/%/, '\\%')
398
399
  my_str.gsub!(/~/, '\\textasciitilde')
399
- my_str.gsub!(/\&/, '\\\\&')
400
+ my_str.gsub!(/&/, '\\\\&')
400
401
  my_str.gsub!(/\#/, '\\\\#')
401
402
  my_str.gsub!(/\{/, '\\{')
402
403
  my_str.gsub!(/\}/, '\\}')
403
404
  my_str.gsub!(/_/, '\\_')
404
405
  my_str.gsub!(/\$/, "\\\$")
405
- my_str.gsub!(/\"(.+)\"/, "``\1''")
406
+ my_str.gsub!(/"(.+)"/, "``\1''")
406
407
  my_str
407
408
  end
408
409
  end