# frozen_string_literal: true # This file is part of Alexandria. # # See the file README.md for authorship and licensing information. require "alexandria/scanners/cue_cat" require "alexandria/scanners/keyboard" require "alexandria/ui/builder_base" require "alexandria/ui/provider_preferences_dialog" require "alexandria/ui/new_provider_dialog" module Alexandria module UI class PreferencesDialog < BuilderBase include Alexandria::Logging include GetText GetText.bindtextdomain(Alexandria::TEXTDOMAIN, charset: "UTF-8") def initialize(parent, &changed_block) super("preferences_dialog__builder.glade", widget_names) @preferences_dialog.transient_for = parent @changed_block = changed_block @cols = { @checkbutton_col_authors => "col_authors_visible", @checkbutton_col_isbn => "col_isbn_visible", @checkbutton_col_publisher => "col_publisher_visible", @checkbutton_col_publish_date => "col_publish_date_visible", @checkbutton_col_edition => "col_edition_visible", @checkbutton_col_redd => "col_redd_visible", @checkbutton_col_own => "col_own_visible", @checkbutton_col_want => "col_want_visible", @checkbutton_col_rating => "col_rating_visible", @checkbutton_col_tags => "col_tags_visible", @checkbutton_col_loaned_to => "col_loaned_to_visible" } @cols.each_pair do |checkbutton, pref_name| if checkbutton checkbutton.active = Preferences.instance.send(pref_name) else log.warn do "no CheckButton for property #{pref_name} " \ "(probably conflicting versions of GUI and lib code)" end end end model = Gtk::ListStore.new(String, String, TrueClass, Integer) @treeview_providers.model = model reload_providers model.signal_connect_after("row-changed") { update_priority } renderer = Gtk::CellRendererToggle.new renderer.activatable = true renderer.signal_connect("toggled") do |_rndrr, path| tree_path = Gtk::TreePath.new(path) @treeview_providers.selection.select_path(tree_path) prov = selected_provider if prov prov.toggle_enabled adjust_selected_provider(prov) # reload_providers end end # renderer.active = true column = Gtk::TreeViewColumn.new("Enabled", renderer) column.set_cell_data_func(renderer) do |_col, rndr, _mod, iter| value = iter[2] rndr.active = value end @treeview_providers.append_column(column) renderer = Gtk::CellRendererText.new column = Gtk::TreeViewColumn.new("Providers", renderer) # :text => 0) column.set_cell_data_func(renderer) do |_col, rndr, _mod, iter| rndr.markup = iter[0] # enabled = iter[2] # unless enabled # rndr.foreground = "gray" # end # rndr.active = value end @treeview_providers.append_column(column) @treeview_providers.selection.signal_connect("changed") \ { sensitize_providers } @button_prov_setup.sensitive = false @button_prov_up.sensitive = @button_prov_down.sensitive = BookProviders.length > 1 @buttonbox_prov.set_child_secondary(@button_prov_add, true) @buttonbox_prov.set_child_secondary(@button_prov_remove, true) if BookProviders.abstract_classes.empty? @checkbutton_prov_advanced.sensitive = false else view_advanced = Preferences.instance.view_advanced_settings @checkbutton_prov_advanced.active = true if view_advanced end setup_enable_disable_popup sensitize_providers setup_barcode_scanner_tab end def widget_names [:button_prov_add, :button_prov_down, :button_prov_remove, :button_prov_setup, :button_prov_up, :buttonbox_prov, :checkbutton_col_authors, :checkbutton_col_edition, :checkbutton_col_isbn, :checkbutton_col_loaned_to, :checkbutton_col_own, :checkbutton_col_publish_date, :checkbutton_col_publisher, :checkbutton_col_rating, :checkbutton_col_redd, :checkbutton_col_tags, :checkbutton_col_want, :checkbutton_prov_advanced, :preferences_dialog, :treeview_providers, :scanner_device_type, :use_scanning_sound, :use_scan_sound] end def setup_barcode_scanner_tab @scanner_device_model = Gtk::ListStore.new(String, String) chosen_scanner_name = Preferences.instance.barcode_scanner index = 0 @scanner_device_type.model = @scanner_device_model renderer = Gtk::CellRendererText.new @scanner_device_type.pack_start(renderer, true) @scanner_device_type.add_attribute(renderer, "text", 0) Alexandria::Scanners.each_scanner do |scanner| iter = @scanner_device_model.append iter[0] = scanner.display_name iter[1] = scanner.name @scanner_device_type.active = index if chosen_scanner_name == scanner.name index += 1 end @use_scanning_sound.active = Preferences.instance.play_scanning_sound @use_scan_sound.active = Preferences.instance.play_scan_sound end def setup_enable_disable_popup # New Enable/Disable pop-up menu... @enable_disable_providers_menu = Gtk::Menu.new @enable_item = Gtk::MenuItem.new(label: _("Disable Provider")) @enable_item.signal_connect("activate") do prov = selected_provider prov.toggle_enabled adjust_selected_provider(prov) end @enable_disable_providers_menu.append(@enable_item) @enable_disable_providers_menu.show_all @treeview_providers.signal_connect("button_press_event") do |widget, event| if event_is_right_click(event) if (path = widget.get_path_at_pos(event.x, event.y)) widget.grab_focus obj = widget.selection path = path.first unless obj.path_is_selected?(path) widget.unselect_all obj.select_path(path) end sel = widget.selection.selected if sel already_enabled = sel[2] message = already_enabled ? _("Disable Provider") : _("Enable Provider") @enable_item.label = message GLib::Idle.add do @enable_disable_providers_menu.popup(nil, nil, event.button, event.time) false end end else puts "not on a path" end end end # Popup the menu on Shift-F10 @treeview_providers.signal_connect("popup_menu") do selected_prov = @treeview_providers.selection.selected puts selected_prov.inspect if selected_prov GLib::Idle.add do already_enabled = selected_prov[2] message = already_enabled ? _("Disable Provider") : _("Enable Provider") @enable_item.label = message @enable_disable_providers_menu.popup(nil, nil, 0, :current_time) false end else puts "no action" end end end def event_is_right_click(event) (event.event_type == :button_press) && (event.button == 3) end def prefs_empty(prefs) prefs.empty? || ((prefs.size == 1) && (prefs.first.name == "enabled")) end def on_provider_setup provider = selected_provider unless prefs_empty(provider.prefs) ProviderPreferencesDialog.new(@preferences_dialog, provider).acquire end end def on_provider_up iter = @treeview_providers.selection.selected previous_path = iter.path previous_path.prev! model = @treeview_providers.model model.move_after(model.get_iter(previous_path), iter) sensitize_providers update_priority end def on_provider_down iter = @treeview_providers.selection.selected next_iter = iter.dup next_iter.next! @treeview_providers.model.move_after(iter, next_iter) sensitize_providers update_priority end def on_provider_advanced_toggled(checkbutton) on = checkbutton.active? Preferences.instance.view_advanced_settings = on @button_prov_add.visible = @button_prov_remove.visible = on end def on_provider_add dialog = NewProviderDialog.new(@preferences_dialog).acquire if dialog.instance BookProviders.update_priority reload_providers end end def on_scanner_device_type(_combo) iter = @scanner_device_type.active_iter Preferences.instance.barcode_scanner = iter[1] if iter && iter[1] end def on_use_scanning_sound(checkbox) Preferences.instance.play_scanning_sound = checkbox.active? end def on_use_scan_sound(checkbox) Preferences.instance.play_scan_sound = checkbox.active? end def on_provider_remove provider = selected_provider dialog = AlertDialog.new(@main_app, _("Are you sure you want to " \ "permanently delete the provider " \ "'%s'?") % provider.fullname, Gtk::Stock::DIALOG_QUESTION, [[Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL], [Gtk::Stock::DELETE, Gtk::ResponseType::OK]], _("If you continue, the provider and " \ "all of its preferences will be " \ "permanently deleted.")) dialog.default_response = Gtk::ResponseType::CANCEL dialog.show_all if dialog.run == Gtk::ResponseType::OK provider.remove BookProviders.update_priority reload_providers end dialog.destroy end def on_column_toggled(checkbutton) raise if @cols[checkbutton].nil? Preferences.instance.send("#{@cols[checkbutton]}=", checkbutton.active?) @changed_block.call end def on_providers_button_press_event(_widget, event) # double left click on_provider_setup if (event.event_type == :'2button_press') && (event.button == 1) end def on_close @preferences_dialog.destroy Alexandria::Preferences.instance.save! end def on_help Alexandria::UI.display_help(@preferences_dialog, "alexandria-preferences") end private def reload_providers model = @treeview_providers.model model.clear BookProviders.each_with_index do |x, index| iter = model.append iter[0] = if x.enabled x.fullname else "#{x.fullname}" end iter[1] = x.name iter[2] = x.enabled iter[3] = index end end def selected_provider iter = @treeview_providers.selection.selected BookProviders.find { |x| x.name == iter[1] } unless iter.nil? end def adjust_selected_provider(prov) iter = @treeview_providers.selection.selected iter[0] = if prov.enabled prov.fullname else "#{prov.fullname}" end iter[2] = prov.enabled end def sensitize_providers model = @treeview_providers.model sel_iter = @treeview_providers.selection.selected if sel_iter.nil? # No selection, we are probably called by ListStore#clear @button_prov_up.sensitive = false @button_prov_down.sensitive = false @button_prov_setup.sensitive = false @button_prov_remove.sensitive = false else last_iter = model.get_iter((BookProviders.length - 1).to_s) @button_prov_up.sensitive = sel_iter != model.iter_first @button_prov_down.sensitive = sel_iter != last_iter provider = BookProviders.find { |x| x.name == sel_iter[1] } @button_prov_setup.sensitive = !prefs_empty(provider.prefs) @button_prov_remove.sensitive = provider.abstract? end end def update_priority priority = [] @treeview_providers.model.each do |_model, _path, iter| priority << iter[1] end Preferences.instance.providers_priority = priority BookProviders.update_priority end end end end