alexandria-book-collection-manager 0.6.9.pre1 → 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -4
- data/.rubocop_todo.yml +21 -79
- data/CHANGELOG.md +9 -1
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/alexandria-book-collection-manager.gemspec +26 -4
- data/bin/alexandria +1 -1
- data/doc/AUTHORS +2 -1
- data/lib/alexandria.rb +1 -1
- data/lib/alexandria/about.rb +6 -6
- data/lib/alexandria/book_providers.rb +1 -1
- data/lib/alexandria/book_providers/adlibris.rb +4 -4
- data/lib/alexandria/book_providers/barnes_and_noble.rb +9 -5
- data/lib/alexandria/book_providers/bol_it.rb +0 -2
- data/lib/alexandria/book_providers/ibs_it.rb +0 -2
- data/lib/alexandria/book_providers/mcu.rb +3 -5
- data/lib/alexandria/book_providers/proxis.rb +1 -5
- data/lib/alexandria/book_providers/renaud.rb +0 -2
- data/lib/alexandria/book_providers/thalia.rb +10 -8
- data/lib/alexandria/book_providers/webster_it.rb +0 -2
- data/lib/alexandria/book_providers/worldcat.rb +8 -4
- data/lib/alexandria/book_providers/z3950.rb +2 -8
- data/lib/alexandria/execution_queue.rb +1 -3
- data/lib/alexandria/export_library.rb +2 -7
- data/lib/alexandria/import_library.rb +1 -6
- data/lib/alexandria/logging.rb +1 -1
- data/lib/alexandria/models/book.rb +2 -2
- data/lib/alexandria/models/library.rb +5 -7
- data/lib/alexandria/preferences.rb +1 -1
- data/lib/alexandria/scanners.rb +4 -3
- data/lib/alexandria/scanners/cuecat.rb +1 -1
- data/lib/alexandria/smart_library.rb +4 -3
- data/lib/alexandria/ui/callbacks.rb +2 -2
- data/lib/alexandria/ui/completion_models.rb +22 -19
- data/lib/alexandria/ui/dialogs/acquire_dialog.rb +2 -4
- data/lib/alexandria/ui/dialogs/barcode_animation.rb +1 -1
- data/lib/alexandria/ui/dialogs/book_properties_dialog.rb +1 -3
- data/lib/alexandria/ui/dialogs/book_properties_dialog_base.rb +0 -4
- data/lib/alexandria/ui/dialogs/export_dialog.rb +1 -3
- data/lib/alexandria/ui/dialogs/import_dialog.rb +4 -4
- data/lib/alexandria/ui/dialogs/new_book_dialog.rb +8 -11
- data/lib/alexandria/ui/dialogs/new_book_dialog_manual.rb +4 -5
- data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +15 -9
- data/lib/alexandria/ui/dialogs/preferences_dialog.rb +20 -23
- data/lib/alexandria/ui/dialogs/smart_library_properties_dialog_base.rb +10 -14
- data/lib/alexandria/ui/dndable.rb +0 -1
- data/lib/alexandria/ui/gtk_thread_help.rb +2 -1
- data/lib/alexandria/ui/icons.rb +3 -3
- data/lib/alexandria/ui/iconview_tooltips.rb +9 -5
- data/lib/alexandria/ui/init.rb +6 -6
- data/lib/alexandria/ui/listview.rb +4 -4
- data/lib/alexandria/ui/main_app.rb +1 -1
- data/lib/alexandria/ui/multi_drag_treeview.rb +3 -5
- data/lib/alexandria/ui/sidepane.rb +26 -10
- data/lib/alexandria/ui/ui_manager.rb +5 -9
- data/lib/alexandria/undo_manager.rb +0 -2
- data/lib/alexandria/version.rb +3 -3
- data/lib/alexandria/web_themes.rb +1 -3
- data/{test/providers_test.rb → spec/alexandria/book_providers_spec.rb} +17 -15
- data/{test/book_test.rb → spec/alexandria/book_spec.rb} +4 -4
- data/spec/alexandria/library_spec.rb +189 -141
- data/spec/alexandria/scanners/cuecat_spec.rb +0 -2
- data/spec/alexandria/ui/main_app_spec.rb +13 -8
- data/spec/alexandria/ui/sidepane_spec.rb +1 -1
- data/spec/alexandria/ui/ui_utilities_spec.rb +1 -1
- data/{test → spec}/data/isbns.txt +0 -0
- data/tasks/spec.rake +2 -0
- data/util/rake/fileinstall.rb +1 -1
- metadata +32 -16
- data/tasks/test.rake +0 -38
- data/test/application_test.rb +0 -39
- data/test/isbn_test.rb +0 -68
- data/test/test_helper.rb +0 -42
@@ -125,8 +125,8 @@ module Alexandria
|
|
125
125
|
rescue => ex
|
126
126
|
log.error { "problem with immediate export #{ex} try again" }
|
127
127
|
ErrorDialog.new(@main_app, _('Export failed'),
|
128
|
-
|
129
|
-
|
128
|
+
_('Try letting this library load ' \
|
129
|
+
'completely before exporting.'))
|
130
130
|
end
|
131
131
|
|
132
132
|
def on_acquire(_widget, _event)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (C) 2005-2006 Laurent Sansonetti
|
2
|
-
#
|
2
|
+
# Copyright (C) 2011 Matijs van Zuijlen
|
3
3
|
#
|
4
4
|
# Alexandria is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU General Public License as
|
@@ -68,9 +68,7 @@ class Gtk::Entry
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
#######
|
72
71
|
private
|
73
|
-
#######
|
74
72
|
|
75
73
|
def complete(model_id)
|
76
74
|
completion = Gtk::EntryCompletion.new
|
@@ -86,20 +84,21 @@ begin
|
|
86
84
|
|
87
85
|
EVOLUTION_CONTACTS =
|
88
86
|
Revolution::Revolution.new.get_all_contacts.map do |contact|
|
89
|
-
|
87
|
+
first = contact.first_name
|
88
|
+
last = contact.last_name
|
90
89
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
if first
|
91
|
+
first.strip!
|
92
|
+
first = nil if first.empty?
|
93
|
+
end
|
95
94
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
95
|
+
if last
|
96
|
+
last.strip!
|
97
|
+
last = nil if last.empty?
|
98
|
+
end
|
100
99
|
|
101
|
-
|
102
|
-
|
100
|
+
first and last ? first + ' ' + last : first ? first : last
|
101
|
+
end
|
103
102
|
rescue LoadError => e
|
104
103
|
Alexandria.log.debug { 'Could not find optional ruby-revolution; Evolution contacts will not be loaded' }
|
105
104
|
EVOLUTION_CONTACTS = []
|
@@ -116,7 +115,8 @@ module Alexandria
|
|
116
115
|
TITLE, AUTHOR, PUBLISHER, EDITION, BORROWER, TAG = (0..6).to_a
|
117
116
|
|
118
117
|
def initialize
|
119
|
-
@models
|
118
|
+
@models = []
|
119
|
+
@libraries = []
|
120
120
|
5.times { @models << Gtk::ListStore.new(String) }
|
121
121
|
@models << Gtk::ListStore.new(String)
|
122
122
|
touch
|
@@ -174,9 +174,7 @@ module Alexandria
|
|
174
174
|
@models[TAG]
|
175
175
|
end
|
176
176
|
|
177
|
-
#######
|
178
177
|
private
|
179
|
-
#######
|
180
178
|
|
181
179
|
def touch
|
182
180
|
@dirty = true
|
@@ -187,7 +185,11 @@ module Alexandria
|
|
187
185
|
end
|
188
186
|
|
189
187
|
def rebuild_models
|
190
|
-
titles
|
188
|
+
titles = []
|
189
|
+
authors = []
|
190
|
+
publishers = []
|
191
|
+
editions = []
|
192
|
+
borrowers = []
|
191
193
|
tags = []
|
192
194
|
@libraries.each do |library|
|
193
195
|
library.each do |book|
|
@@ -196,7 +198,8 @@ module Alexandria
|
|
196
198
|
publishers << book.publisher
|
197
199
|
editions << book.edition
|
198
200
|
borrowers << book.loaned_to
|
199
|
-
|
201
|
+
# TODO: Ensure #tags is always an array
|
202
|
+
(book.tags || []).each { |tag| tags << tag }
|
200
203
|
end
|
201
204
|
end
|
202
205
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Copyright (C) 2004-2006 Laurent Sansonetti
|
2
2
|
# Copyright (C) 2007 Cathal Mc Ginley
|
3
|
-
#
|
3
|
+
# Copyright (C) 2011 Matijs van Zuijlen
|
4
4
|
#
|
5
5
|
# Alexandria is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU General Public License as
|
@@ -174,7 +174,6 @@ module Alexandria
|
|
174
174
|
log.debug { "removing iter #{iter[0]}" }
|
175
175
|
model.remove(iter)
|
176
176
|
end
|
177
|
-
|
178
177
|
end
|
179
178
|
else
|
180
179
|
model.freeze_notify do
|
@@ -553,7 +552,7 @@ module Alexandria
|
|
553
552
|
def play_sound(effect)
|
554
553
|
# HACK, do some thread waiting, if possible
|
555
554
|
puts "scanning sound : #{@prefs.play_scanning_sound}"
|
556
|
-
puts "scan sound: #{
|
555
|
+
puts "scan sound: #{@prefs.play_scan_sound}"
|
557
556
|
if effect == 'scanning'
|
558
557
|
puts effect
|
559
558
|
return unless @prefs.play_scanning_sound
|
@@ -620,7 +619,6 @@ module Alexandria
|
|
620
619
|
|
621
620
|
cell.pixbuf = pixbuf
|
622
621
|
end
|
623
|
-
|
624
622
|
end
|
625
623
|
|
626
624
|
@barcodes_treeview.append_column(col)
|
@@ -109,9 +109,7 @@ module Alexandria
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
#######
|
113
112
|
private
|
114
|
-
#######
|
115
113
|
|
116
114
|
def on_close
|
117
115
|
if @entry_isbn.text == ''
|
@@ -203,7 +201,7 @@ module Alexandria
|
|
203
201
|
|
204
202
|
def on_help
|
205
203
|
Alexandria::UI.display_help(@preferences_dialog,
|
206
|
-
|
204
|
+
'editing-book-properties')
|
207
205
|
end
|
208
206
|
end
|
209
207
|
end
|
@@ -102,7 +102,6 @@ module Alexandria
|
|
102
102
|
time = Time.gm(year, month, day)
|
103
103
|
@calendar_popup_for_entry.text = format_date(time)
|
104
104
|
end
|
105
|
-
|
106
105
|
end
|
107
106
|
|
108
107
|
@calendar.signal_connect('day-selected-double-click') do
|
@@ -146,7 +145,6 @@ module Alexandria
|
|
146
145
|
@book_properties_dialog.modal = true
|
147
146
|
|
148
147
|
Gtk.timeout_add(150) do
|
149
|
-
|
150
148
|
# If we set @popup_displayed=false immediately, then a click
|
151
149
|
# event on the primary icon of the Entry simultaneous with
|
152
150
|
# the focus-out-event of the Calendar causes the Calendar to
|
@@ -370,9 +368,7 @@ module Alexandria
|
|
370
368
|
end
|
371
369
|
end
|
372
370
|
|
373
|
-
#######
|
374
371
|
private
|
375
|
-
#######
|
376
372
|
|
377
373
|
def rating=(rating)
|
378
374
|
images = [
|
@@ -93,7 +93,7 @@ module Alexandria
|
|
93
93
|
types_combo.signal_connect('changed') do
|
94
94
|
theme_label.visible = theme_combo.visible =
|
95
95
|
preview_image.visible =
|
96
|
-
|
96
|
+
FORMATS[types_combo.active].needs_preview?
|
97
97
|
end
|
98
98
|
types_combo.show
|
99
99
|
|
@@ -132,9 +132,7 @@ module Alexandria
|
|
132
132
|
destroy
|
133
133
|
end
|
134
134
|
|
135
|
-
#######
|
136
135
|
private
|
137
|
-
#######
|
138
136
|
|
139
137
|
def on_export(format, theme)
|
140
138
|
unless @library.respond_to?(format.message)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (C) 2004-2006 Laurent Sansonetti
|
2
|
-
#
|
2
|
+
# Copyright (C) 2011 Matijs van Zuijlen
|
3
3
|
#
|
4
4
|
# Alexandria is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU General Public License as
|
@@ -135,8 +135,8 @@ module Alexandria
|
|
135
135
|
file = File.basename(filename, '.*')
|
136
136
|
base = GLib.locale_to_utf8(file)
|
137
137
|
new_library_name = Library.generate_new_name(
|
138
|
-
|
139
|
-
|
138
|
+
Libraries.instance.all_libraries,
|
139
|
+
base)
|
140
140
|
|
141
141
|
filter = filters[self.filter]
|
142
142
|
puts "Going forward with filter: #{filter.name}" if $DEBUG
|
@@ -166,7 +166,7 @@ module Alexandria
|
|
166
166
|
thread = Thread.start do
|
167
167
|
begin
|
168
168
|
library, @bad_isbns, @failed_isbns = filter.invoke(new_library_name,
|
169
|
-
|
169
|
+
filename)
|
170
170
|
rescue => ex
|
171
171
|
trace = ex.backtrace.join("\n> ")
|
172
172
|
log.error { "Import failed: #{ex.message} #{trace}" }
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (C) 2004-2006 Laurent Sansonetti
|
2
|
-
#
|
2
|
+
# Copyright (C) 2011 Matijs van Zuijlen
|
3
3
|
#
|
4
4
|
# Alexandria is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU General Public License as
|
@@ -273,8 +273,10 @@ module Alexandria
|
|
273
273
|
|
274
274
|
criterion = @entry_search.text.strip
|
275
275
|
@treeview_results.model.clear
|
276
|
-
log.info {
|
277
|
-
|
276
|
+
log.info {
|
277
|
+
'TreeStore Model: %s columns; ref_counts: %s' %
|
278
|
+
[@treeview_results.model.n_columns, @treeview_results.model.ref_count]
|
279
|
+
}
|
278
280
|
|
279
281
|
@find_error = nil
|
280
282
|
@results = nil
|
@@ -377,7 +379,7 @@ module Alexandria
|
|
377
379
|
def on_results_button_press_event(_widget, event)
|
378
380
|
# double left click
|
379
381
|
if event.event_type == Gdk::Event::BUTTON2_PRESS and
|
380
|
-
|
382
|
+
event.button == 1
|
381
383
|
|
382
384
|
on_add
|
383
385
|
end
|
@@ -396,7 +398,6 @@ module Alexandria
|
|
396
398
|
@button_add.sensitive = false
|
397
399
|
notify_start_add_by_isbn
|
398
400
|
Gtk.idle_add do
|
399
|
-
|
400
401
|
@find_thread = Thread.new do
|
401
402
|
log.info { "New @find_thread #{Thread.current}" }
|
402
403
|
begin
|
@@ -457,7 +458,6 @@ module Alexandria
|
|
457
458
|
end
|
458
459
|
books_to_add << [book, cover]
|
459
460
|
end
|
460
|
-
|
461
461
|
end
|
462
462
|
books_to_add.each do |book, cover_uri|
|
463
463
|
add_book_to_library(library, book, cover_uri)
|
@@ -573,9 +573,8 @@ module Alexandria
|
|
573
573
|
clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
|
574
574
|
if (text = clipboard.wait_for_text)
|
575
575
|
if Library.valid_isbn?(text) or Library.valid_ean?(text) or
|
576
|
-
|
576
|
+
Library.valid_upc?(text)
|
577
577
|
Gtk.idle_add do
|
578
|
-
|
579
578
|
@entry_isbn.text = text
|
580
579
|
@entry_isbn.grab_focus
|
581
580
|
@entry_isbn.select_region(0, -1) # select all...
|
@@ -594,7 +593,7 @@ module Alexandria
|
|
594
593
|
|
595
594
|
def on_clicked(widget, event)
|
596
595
|
if event.event_type == Gdk::Event::BUTTON_PRESS and
|
597
|
-
|
596
|
+
event.button == 1
|
598
597
|
|
599
598
|
radio, target_widget, box2, box3 = case widget
|
600
599
|
when @eventbox_entry_search
|
@@ -620,9 +619,7 @@ module Alexandria
|
|
620
619
|
Alexandria::UI.display_help(@preferences_dialog, 'add-book-by-isbn')
|
621
620
|
end
|
622
621
|
|
623
|
-
#######
|
624
622
|
private
|
625
|
-
#######
|
626
623
|
|
627
624
|
def assert_not_exist(library, isbn)
|
628
625
|
# Check that the book doesn't already exist in the library.
|
@@ -65,9 +65,7 @@ module Alexandria
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
#######
|
69
68
|
private
|
70
|
-
#######
|
71
69
|
|
72
70
|
def on_cancel
|
73
71
|
@book_properties_dialog.destroy
|
@@ -83,7 +81,8 @@ module Alexandria
|
|
83
81
|
isbn = nil
|
84
82
|
if @entry_isbn.text != ''
|
85
83
|
ary = @library.select { |book|
|
86
|
-
book.ident == @entry_isbn.text
|
84
|
+
book.ident == @entry_isbn.text
|
85
|
+
}
|
87
86
|
raise AddError.new(_('The EAN/ISBN you provided is ' \
|
88
87
|
'already used in this library.')) unless ary.empty?
|
89
88
|
isbn = begin
|
@@ -110,8 +109,8 @@ module Alexandria
|
|
110
109
|
'provided.'))
|
111
110
|
end
|
112
111
|
book = Book.new(title, authors, isbn, publisher,
|
113
|
-
|
114
|
-
|
112
|
+
publishing_year == 0 ? nil : publishing_year,
|
113
|
+
edition)
|
115
114
|
book.rating = @current_rating
|
116
115
|
book.notes = @textview_notes.buffer.text
|
117
116
|
book.loaned = @checkbutton_loaned.active?
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright (C) 2004-2006 Laurent Sansonetti
|
2
|
+
# Copyright (C) 2015 Matijs van Zuijlen
|
2
3
|
#
|
3
4
|
# Alexandria is free software; you can redistribute it and/or
|
4
5
|
# modify it under the terms of the GNU General Public License as
|
@@ -41,16 +42,10 @@ module Alexandria
|
|
41
42
|
elsif response == Gtk::Dialog::RESPONSE_OK
|
42
43
|
if user_confirms_possible_weirdnesses_before_saving?
|
43
44
|
rules = smart_library_rules
|
44
|
-
basename =
|
45
|
-
rules.first.value.is_a?(String) and
|
46
|
-
!rules.first.value.strip.empty?
|
47
|
-
rules.first.value
|
48
|
-
else
|
49
|
-
_('Smart Library')
|
50
|
-
end
|
45
|
+
basename = smart_library_base_name(rules) || _('Smart Library')
|
51
46
|
name = Library.generate_new_name(
|
52
|
-
|
53
|
-
|
47
|
+
Libraries.instance.all_libraries,
|
48
|
+
basename)
|
54
49
|
library = SmartLibrary.new(name,
|
55
50
|
rules,
|
56
51
|
predicate_operator_rule)
|
@@ -62,6 +57,17 @@ module Alexandria
|
|
62
57
|
|
63
58
|
destroy
|
64
59
|
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def smart_library_base_name(rules)
|
64
|
+
if rules.length == 1
|
65
|
+
value = rules.first.value
|
66
|
+
if value.is_a?(String) and !value.strip.empty?
|
67
|
+
return value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (C) 2004-2006 Laurent Sansonetti
|
2
|
-
#
|
2
|
+
# Copyright (C) 2011 Matijs van Zuijlen
|
3
3
|
#
|
4
4
|
# Alexandria is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU General Public License as
|
@@ -193,9 +193,7 @@ module Alexandria
|
|
193
193
|
@selected_instance
|
194
194
|
end
|
195
195
|
|
196
|
-
#######
|
197
196
|
private
|
198
|
-
#######
|
199
197
|
|
200
198
|
def sensitize
|
201
199
|
entries = @table.children.select { |x| x.is_a?(Gtk::Entry) }
|
@@ -242,8 +240,10 @@ module Alexandria
|
|
242
240
|
if checkbutton
|
243
241
|
checkbutton.active = Preferences.instance.send(pref_name)
|
244
242
|
else
|
245
|
-
log.warn {
|
246
|
-
|
243
|
+
log.warn {
|
244
|
+
"no CheckButton for property #{pref_name} " \
|
245
|
+
'(probably conflicting versions of GUI and lib code)'
|
246
|
+
}
|
247
247
|
end
|
248
248
|
end
|
249
249
|
|
@@ -355,7 +355,6 @@ module Alexandria
|
|
355
355
|
prov = selected_provider
|
356
356
|
prov.toggle_enabled
|
357
357
|
adjust_selected_provider(prov)
|
358
|
-
|
359
358
|
}
|
360
359
|
@enable_disable_providers_menu.append(@enable_item)
|
361
360
|
@enable_disable_providers_menu.show_all
|
@@ -387,21 +386,21 @@ module Alexandria
|
|
387
386
|
|
388
387
|
# Popup the menu on Shift-F10
|
389
388
|
@treeview_providers.signal_connect('popup_menu') {
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
end
|
401
|
-
else
|
402
|
-
puts 'no action'
|
389
|
+
selected_prov = @treeview_providers.selection.selected
|
390
|
+
puts selected_prov.inspect
|
391
|
+
if selected_prov
|
392
|
+
Gtk.idle_add do
|
393
|
+
already_enabled = selected_prov[2]
|
394
|
+
message = already_enabled ? _('Disable Provider') : _('Enable Provider')
|
395
|
+
@enable_item.label = message
|
396
|
+
|
397
|
+
@enable_disable_providers_menu.popup(nil, nil, 0, Gdk::Event::CURRENT_TIME)
|
398
|
+
false
|
403
399
|
end
|
404
|
-
|
400
|
+
else
|
401
|
+
puts 'no action'
|
402
|
+
end
|
403
|
+
}
|
405
404
|
end
|
406
405
|
|
407
406
|
def event_is_right_click(event)
|
@@ -515,12 +514,10 @@ module Alexandria
|
|
515
514
|
|
516
515
|
def on_help
|
517
516
|
Alexandria::UI.display_help(@preferences_dialog,
|
518
|
-
|
517
|
+
'alexandria-preferences')
|
519
518
|
end
|
520
519
|
|
521
|
-
#######
|
522
520
|
private
|
523
|
-
#######
|
524
521
|
|
525
522
|
def reload_providers
|
526
523
|
model = @treeview_providers.model
|