def __init__(self, parent, error_text): main_text = _("Submit Error Report") secondary_text = _( "Various details regarding the error and your system will be send " "to a third party online service " "(<a href='https://www.sentry.io'>www.sentry.io</a>). You can " "review the data before sending it below.") secondary_text += u"\n\n" secondary_text += _( "(optional) Please provide a short description of what happened " "when the error occurred:") super(SubmitErrorDialog, self).__init__(modal=True, text=main_text, secondary_text=secondary_text, secondary_use_markup=True) self.set_transient_for(parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Send"), self.RESPONSE_SUBMIT) self.set_default_response(Gtk.ResponseType.CANCEL) area = self.get_message_area() self._entry = UndoEntry() self._entry.set_placeholder_text(_("Short description…")) area.pack_start(self._entry, False, True, 0) expand = TextExpander(_("Data to be sent:"), error_text) area.pack_start(expand, False, True, 0) area.show_all() self.get_widget_for_response(Gtk.ResponseType.CANCEL).grab_focus()
def __init__(self, parent, title, text, okbutton=Gtk.STOCK_OPEN): super(GetStringDialog, self).__init__(title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_default_size(width=self._WIDTH, height=0) self.set_resizable(True) self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, okbutton, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all()
def __init__(self, parent, title, text, button_label=_("_OK"), button_icon=Icons.DOCUMENT_OPEN, tooltip=None): super().__init__( title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_resizable(True) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(button_label, button_icon, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() if tooltip: self._val.set_tooltip_text(tooltip) self._val.set_max_width_chars(50) box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all()
def PluginPreferences(self, win): box = Gtk.VBox(spacing=12) # api key section def key_changed(entry, *args): config.set("plugins", "fingerprint_acoustid_api_key", entry.get_text()) button = Button(_("Request API key"), Icons.NETWORK_WORKGROUP) button.connect("clicked", lambda s: util.website("https://acoustid.org/api-key")) key_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(get_api_key()) entry.connect("changed", key_changed) label = Gtk.Label(label=_("API _key:")) label.set_use_underline(True) label.set_mnemonic_widget(entry) key_box.pack_start(label, False, True, 0) key_box.pack_start(entry, True, True, 0) key_box.pack_start(button, False, True, 0) box.pack_start(Frame(_("AcoustID Web Service"), child=key_box), True, True, 0) return box
class ExportToFolderDialog(Dialog): """A dialog to collect export settings""" def __init__(self, parent, pattern): super(ExportToFolderDialog, self).__init__( title=_("Export Playlist to Folder"), transient_for=parent, use_header_bar=True) self.set_default_size(400, -1) self.set_resizable(True) self.set_border_width(6) self.vbox.set_spacing(6) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Export"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) destination_label = Gtk.Label(_("Destination folder:")) destination_label.set_line_wrap(True) destination_label.set_xalign(0.0) box.pack_start(destination_label, False, False, 0) frame = Gtk.Frame() self.directory_chooser = Gtk.FileChooserWidget( action=Gtk.FileChooserAction.SELECT_FOLDER) self.directory_chooser.set_select_multiple(False) self.directory_chooser.set_border_width(1) frame.add(self.directory_chooser) frame.set_shadow_type(Gtk.ShadowType.IN) frame.set_border_width(0) box.pack_start(frame, True, True, 0) pattern_label = Gtk.Label(_("Filename pattern:")) pattern_label.set_line_wrap(True) pattern_label.set_xalign(0.0) box.pack_start(pattern_label, False, False, 0) self.pattern_entry = UndoEntry() self.pattern_entry.set_text(pattern) box.pack_start(self.pattern_entry, False, False, 0) self.vbox.pack_start(box, True, True, 0) self.set_response_sensitive(Gtk.ResponseType.OK, False) def changed(*args): has_directory = self.directory_chooser.get_filename() is not None self.set_response_sensitive(Gtk.ResponseType.OK, has_directory) pattern_text = self.pattern_entry.get_text() has_pattern = bool(pattern_text) self.set_response_sensitive(Gtk.ResponseType.OK, has_pattern) self.directory_chooser.connect("selection-changed", changed) self.pattern_entry.connect("changed", changed) self.get_child().show_all()
class ExportToFolderDialog(Dialog): """A dialog to collect export settings""" def __init__(self, parent, pattern): super(ExportToFolderDialog, self).__init__(title=_("Export Playlist to Folder"), transient_for=parent, use_header_bar=True) self.set_default_size(400, -1) self.set_resizable(True) self.set_border_width(6) self.vbox.set_spacing(6) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Export"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) destination_label = Gtk.Label(_("Destination folder:")) destination_label.set_line_wrap(True) destination_label.set_xalign(0.0) box.pack_start(destination_label, False, False, 0) frame = Gtk.Frame() self.directory_chooser = Gtk.FileChooserWidget( action=Gtk.FileChooserAction.SELECT_FOLDER) self.directory_chooser.set_select_multiple(False) self.directory_chooser.set_border_width(1) frame.add(self.directory_chooser) frame.set_shadow_type(Gtk.ShadowType.IN) frame.set_border_width(0) box.pack_start(frame, True, True, 0) pattern_label = Gtk.Label(_("Filename pattern:")) pattern_label.set_line_wrap(True) pattern_label.set_xalign(0.0) box.pack_start(pattern_label, False, False, 0) self.pattern_entry = UndoEntry() self.pattern_entry.set_text(pattern) box.pack_start(self.pattern_entry, False, False, 0) self.vbox.pack_start(box, True, True, 0) self.set_response_sensitive(Gtk.ResponseType.OK, False) def changed(*args): has_directory = self.directory_chooser.get_filename() is not None self.set_response_sensitive(Gtk.ResponseType.OK, has_directory) pattern_text = self.pattern_entry.get_text() has_pattern = bool(pattern_text) self.set_response_sensitive(Gtk.ResponseType.OK, has_pattern) self.directory_chooser.connect("selection-changed", changed) self.pattern_entry.connect("changed", changed) self.get_child().show_all()
def __init__(self): super(Preferences, self).__init__(spacing=12) self.set_border_width(6) ccb = pconfig.ConfigCheckButton(_("Hide main window on close"), "window_hide", populate=True) self.pack_start(ccb, False, True, 0) def on_scroll_changed(button, new_state): if button.get_active(): pconfig.set("modifier_swap", new_state) modifier_swap = pconfig.getboolean("modifier_swap") scrollwheel_box = Gtk.VBox(spacing=0) group = Gtk.RadioButton(group=None, label=_("Scroll wheel adjusts volume"), use_underline=True) group.connect("toggled", on_scroll_changed, False) group.set_active(not modifier_swap) scrollwheel_box.pack_start(group, False, True, 0) group = Gtk.RadioButton(group=group, label=_("Scroll wheel changes song"), use_underline=True) group.connect("toggled", on_scroll_changed, True) group.set_active(modifier_swap) scrollwheel_box.pack_start(group, False, True, 0) self.pack_start(qltk.Frame(_("Scroll _Wheel"), child=scrollwheel_box), True, True, 0) box = Gtk.VBox(spacing=12) entry_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry_box.pack_start(entry, True, True, 0) def on_reverted(*args): pconfig.reset("tooltip") entry.set_text(pconfig.gettext("tooltip")) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) entry_box.pack_start(revert, False, True, 0) box.pack_start(entry_box, False, True, 0) preview = Gtk.Label() preview.set_line_wrap(True) frame = Gtk.Frame() frame.add(preview) box.pack_start(frame, False, True, 0) frame = qltk.Frame(_("Tooltip Display"), child=box) frame.get_label_widget().set_mnemonic_widget(entry) self.pack_start(frame, True, True, 0) entry.connect("changed", self.__changed_entry, preview, frame) entry.set_text(pconfig.gettext("tooltip")) for child in self.get_children(): child.show_all()
def create_pattern(): hbox = Gtk.HBox(spacing=6) hbox.set_border_width(6) label = Gtk.Label(label=_("Default filename pattern:")) hbox.pack_start(label, False, True, 0) entry = UndoEntry() if CONFIG.default_pattern: entry.set_text(CONFIG.default_pattern) entry.connect('changed', changed) hbox.pack_start(entry, True, True, 0) return hbox
def PluginPreferences(self, parent): outer_vb = Gtk.VBox(spacing=12) vb = Gtk.VBox(spacing=12) # Naming Pattern hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_PAT_PLAYING, self.DEFAULT_PAT)) entry.connect('changed', self.config_entry_changed, self.CFG_PAT_PLAYING) lbl = Gtk.Label(label=_("Naming pattern:")) entry.set_tooltip_markup(_("File path based off of tags " "to move a file after update. " "Accepts QL Patterns e.g. %s") % util.monospace(util.escape("<~artist" + "~title>"))) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Frame frame = qltk.Frame(_("New File Location/Name"), child=vb) outer_vb.pack_start(frame, False, True, 0) return outer_vb
def __init__(self): super(Preferences, self).__init__(spacing=12) correct_browser = not isinstance(app.browser, AudioFeeds) table = Gtk.Table(2, 2) table.set_col_spacings(6) table.set_row_spacings(6) labels = {} entries = {} for idx, key in enumerate(["gpodder.net/name", "gpodder.net/password", "gpodder.net/device"]): text, tooltip = _SETTINGS[key][:2] label = Gtk.Label(label=text) entry = UndoEntry() entry.set_text(get_cfg(key)) if key == "gpodder.net/password": entry.set_visibility(False) entries[key] = entry labels[key] = label labels[key].set_mnemonic_widget(entry) label.set_tooltip_text(tooltip) label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx+1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) table.attach(entry, 1, 2, idx, idx+1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) # value, lower, upper, step_increment, page_increment def gpodder_go(button): for key in entries: value = entries[key].get_text() set_cfg(key, value) name = get_cfg("gpodder.net/name") password = get_cfg("gpodder.net/password") device = get_cfg("gpodder.net/device") fetch_gpodder(name, password, device) button = Gtk.Button(label=_("Fetch!" if correct_browser else "(Fetch) Please switch to a different browser!"), sensitive=correct_browser) button.connect("pressed", gpodder_go) table.attach(button, 0, 2, idx+1, idx+2) self.pack_start(qltk.Frame("Preferences", child=table), True, True, 0)
def tag_editing_vbox(self): """Returns a new VBox containing all tag editing widgets""" vbox = Gtk.VBox(spacing=6) cb = CCB(_("Auto-save tag changes"), 'editing', 'auto_save_changes', populate=True, tooltip=_("Save changes to tags without confirmation " "when editing multiple files")) vbox.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') e.set_tooltip_text( _("A list of separators to use when splitting tag values. " "The list is space-separated")) def do_revert_split(button, section, option): config.reset(section, option) e.set_text(config.get(section, option)) split_revert = Button(_("_Revert"), Icons.DOCUMENT_REVERT) split_revert.connect("clicked", do_revert_split, "editing", "split_on") l = Gtk.Label(label=_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) hb.pack_start(split_revert, False, True, 0) vbox.pack_start(hb, False, True, 0) return vbox
def __init__( self, parent, title, text, options=[], okbutton=gtk.STOCK_OPEN): super(GetStringDialog, self).__init__(title, parent) self.set_border_width(6) self.set_has_separator(False) self.set_resizable(False) self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, okbutton, gtk.RESPONSE_OK) self.vbox.set_spacing(6) self.set_default_response(gtk.RESPONSE_OK) box = gtk.VBox(spacing=6) lab = gtk.Label(text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(gtk.JUSTIFY_CENTER) box.pack_start(lab) if options: self._entry = gtk.combo_box_entry_new_text() for o in options: self._entry.append_text(o) self._val = self._entry.child box.pack_start(self._entry) else: self._val = UndoEntry() box.pack_start(self._val) self.vbox.pack_start(box) self.child.show_all()
def __init__(self, parent, title, text, button_label=_("_OK"), button_icon=Icons.DOCUMENT_OPEN, tooltip=None): super(GetStringDialog, self).__init__( title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_resizable(True) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(button_label, button_icon, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() if tooltip: self._val.set_tooltip_text(tooltip) self._val.set_max_width_chars(50) box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all()
def __init__(self, parent, error_text): main_text = _("Submit Error Report") secondary_text = _( "Various details regarding the error and your system will be send " "to a third party online service " "(<a href='https://www.sentry.io'>www.sentry.io</a>). You can " "review the data before sending it below.") secondary_text += u"\n\n" secondary_text += _( "(optional) Please provide a short description of what happened " "when the error occurred:") super(SubmitErrorDialog, self).__init__( modal=True, text=main_text, secondary_text=secondary_text, secondary_use_markup=True) self.set_transient_for(parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Send"), self.RESPONSE_SUBMIT) self.set_default_response(Gtk.ResponseType.CANCEL) area = self.get_message_area() self._entry = UndoEntry() self._entry.set_placeholder_text(_("Short description…")) area.pack_start(self._entry, False, True, 0) expand = TextExpander(_("Data to be sent:"), error_text) area.pack_start(expand, False, True, 0) area.show_all() self.get_widget_for_response(Gtk.ResponseType.CANCEL).grab_focus()
def PluginPreferences(klass, win): def entry_changed(entry): config.set('plugins', 'lastfmsync_username', entry.get_text()) label = Gtk.Label(label=_("_Username:"******"Account"), child=hbox)
def create_visible_columns_frame(): buttons = {} vbox = Gtk.VBox(spacing=12) table = Gtk.Table.new(3, 3, True) for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button( label=_(u"_Edit…"), use_underline=True) edit_button.connect("clicked", self.__config_cols, buttons) edit_button.set_tooltip_text( _("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) vbox.pack_start(hbox, False, True, 0) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(edit_button, True, True, 0) vbox.pack_start(b, True, True, 0) return qltk.Frame(_("Visible Columns"), child=vbox), buttons
def PluginPreferences(self, *args): grid = Gtk.Grid(row_spacing=6, column_spacing=6) label = Gtk.Label(label=_("_Database path:"), use_underline=True) label.set_alignment(0.0, 0.5) grid.attach(label, 0, 0, 1, 1) entry = UndoEntry() entry.set_hexpand(True) entry.set_text(BansheeImport.DEF_PATH) def path_activate(entry, *args): path = text2fsn(entry.get_text()) if BansheeImport.USR_PATH != path: BansheeImport.USR_PATH = path entry.connect_after("activate", path_activate) entry.connect_after("focus-out-event", path_activate) grid.attach_next_to(entry, label, Gtk.PositionType.RIGHT, 1, 1) path_revert = Gtk.Button() path_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) def path_revert_cb(button, entry): entry.set_text(BansheeImport.DEF_PATH) entry.emit("activate") path_revert.connect("clicked", path_revert_cb, entry) grid.attach_next_to(path_revert, entry, Gtk.PositionType.RIGHT, 1, 1) button = Gtk.Button(label=_("Start Import")) def clicked_cb(button): do_import(button, app.library) button.connect("clicked", clicked_cb) box = Gtk.VBox(spacing=12) box.pack_start(grid, True, True, 0) box.pack_start(button, False, False, 0) return box
def build_alternate_search_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) def on_entry_changed(entry, *args): self.Conf.alternate_search_url = entry.get_text() URL_entry = UndoEntry() URL_entry.set_text(self.Conf.alternate_search_url) URL_entry.connect("changed", on_entry_changed) l1 = ConfigLabel(_("URL:"), URL_entry) URL_revert = Gtk.Button() URL_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) URL_revert.set_tooltip_text(_("Revert to default")) connect_obj(URL_revert, "clicked", URL_entry.set_text, DEFAULT_ALTERNATE_SEARCH_URL) hb.pack_start(l1, False, True, 0) hb.pack_start(URL_entry, True, True, 0) hb.pack_start(URL_revert, False, True, 0) vb2.pack_start(hb, False, True, 0) def on_alternate_search_toggled(button, *args): self.Conf.alternate_search_enabled = button.get_active() alternate_search_enabled = Gtk.CheckButton( label=_("Search via above URL if the lyrics " "couldn't be found in LyricsWikia."), use_underline=True) alternate_search_enabled.set_active( self.Conf.alternate_search_enabled) alternate_search_enabled.connect("toggled", on_alternate_search_toggled) vb2.pack_start(alternate_search_enabled, False, True, 0) return vb2
def __init__(self): super(Preferences, self).__init__(spacing=12) correct_browser = not isinstance(app.browser, AudioFeeds) table = Gtk.Table(2, 2) table.set_col_spacings(6) table.set_row_spacings(6) labels = {} entries = {} for idx, key in enumerate( ["gpodder.net/name", "gpodder.net/password", "gpodder.net/device"]): text, tooltip = _SETTINGS[key][:2] label = Gtk.Label(label=text) entry = UndoEntry() entry.set_text(get_cfg(key)) if key == "gpodder.net/password": entry.set_visibility(False) entries[key] = entry labels[key] = label labels[key].set_mnemonic_widget(entry) label.set_tooltip_text(tooltip) label.set_alignment(0.0, 0.5) label.set_padding(0, 6) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) table.attach(entry, 1, 2, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) # value, lower, upper, step_increment, page_increment def gpodder_go(button): for key in entries: value = entries[key].get_text() set_cfg(key, value) name = get_cfg("gpodder.net/name") password = get_cfg("gpodder.net/password") device = get_cfg("gpodder.net/device") fetch_gpodder(name, password, device) button = Gtk.Button( label=_("Fetch!" if correct_browser else "(Fetch) Please switch to a different browser!"), sensitive=correct_browser) button.connect("pressed", gpodder_go) table.attach(button, 0, 2, idx + 1, idx + 2) self.pack_start(qltk.Frame("Preferences", child=table), True, True, 0)
def PluginPreferences(self, win): box = Gtk.VBox(spacing=12) # api key section def key_changed(entry, *args): config.set("plugins", "fingerprint_acoustid_api_key", entry.get_text()) button = Button(_("Request API key"), Gtk.STOCK_NETWORK) button.connect("clicked", lambda s: util.website("https://acoustid.org/api-key")) key_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(get_api_key()) entry.connect("changed", key_changed) label = Gtk.Label(label=_("API _key:")) label.set_use_underline(True) label.set_mnemonic_widget(entry) key_box.pack_start(label, False, True, 0) key_box.pack_start(entry, True, True, 0) key_box.pack_start(button, False, True, 0) box.pack_start(Frame(_("Acoustid Web Service"), child=key_box), True, True, 0) return box
def PluginPreferences(self, *args): vbox = Gtk.VBox(spacing=12) label = Gtk.Label(label=_("Visualiser executable:")) def edited(widget): self.executable = widget.get_text() entry = UndoEntry() entry.connect('changed', edited) entry.set_text(self.executable) hbox = Gtk.HBox(spacing=6) hbox.pack_start(label, False, False, 0) hbox.pack_start(entry, True, True, 0) vbox.pack_start(hbox, True, True, 0) def refresh_clicked(widget): self.disabled() self.enabled() refresh_button = Button(_("Reload"), Icons.VIEW_REFRESH) refresh_button.connect('clicked', refresh_clicked) vbox.pack_start(refresh_button, False, False, 0) return vbox
def __init__(self, parent): if self.is_not_unique(): return super(PreferencesWindow, self).__init__() self.set_title(_("Ex Falso Preferences")) self.set_border_width(12) self.set_resizable(False) self.set_transient_for(parent) vbox = gtk.VBox(spacing=6) hb = gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') l = gtk.Label(_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, expand=False) hb.pack_start(e) cb = ConfigCheckButton( _("Show _programmatic tags"), 'editing', 'alltags') cb.set_active(config.getboolean("editing", 'alltags')) vbox.pack_start(hb, expand=False) vbox.pack_start(cb, expand=False) f = qltk.Frame(_("Tag Editing"), child=vbox) close = gtk.Button(stock=gtk.STOCK_CLOSE) close.connect_object('clicked', lambda x: x.destroy(), self) button_box = gtk.HButtonBox() button_box.set_layout(gtk.BUTTONBOX_END) button_box.pack_start(close) main_vbox = gtk.VBox(spacing=12) main_vbox.pack_start(f) main_vbox.pack_start(button_box, expand=False) self.add(main_vbox) self.connect_object('destroy', PreferencesWindow.__destroy, self) self.show_all()
def __init__(self, parent): if self.is_not_unique(): return super(PreferencesWindow, self).__init__() self.set_title(_("Ex Falso Preferences")) self.set_border_width(12) self.set_resizable(False) self.set_transient_for(parent) vbox = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') l = Gtk.Label(label=_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vbox.pack_start(hb, False, True, 0) f = qltk.Frame(_("Tag Editing"), child=vbox) close = Button(_("_Close"), Icons.WINDOW_CLOSE) connect_obj(close, 'clicked', lambda x: x.destroy(), self) button_box = Gtk.HButtonBox() button_box.set_layout(Gtk.ButtonBoxStyle.END) button_box.pack_start(close, True, True, 0) main_vbox = Gtk.VBox(spacing=12) main_vbox.pack_start(f, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_vbox.pack_start(button_box, False, True, 0) self.add(main_vbox) connect_obj(self, 'destroy', PreferencesWindow.__destroy, self) self.get_child().show_all()
def config_table_for(self, config_data): t = Gtk.Table(n_rows=2, n_columns=len(config_data)) t.set_col_spacings(6) t.set_row_spacings(6) for i, (label, cfg, tooltip) in enumerate(config_data): entry = (ValidatingEntry( validator=validator) if self._is_pattern(cfg) else UndoEntry()) entry.set_text(str(self.config_get(*cfg))) entry.connect('changed', self._on_changed, cfg) lbl = Gtk.Label(label=label + ":") lbl.set_size_request(140, -1) lbl.set_alignment(xalign=0.0, yalign=0.5) entry.set_tooltip_markup(tooltip) lbl.set_mnemonic_widget(entry) t.attach(lbl, 0, 1, i, i + 1, xoptions=FILL) t.attach(entry, 1, 2, i, i + 1, xoptions=FILL | EXPAND) return t
def tag_editing_vbox(self): """Returns a new VBox containing all tag editing widgets""" vbox = Gtk.VBox(spacing=6) cb = CCB(_("Auto-save tag changes"), 'editing', 'auto_save_changes', populate=True, tooltip=_("Save changes to tags without confirmation " "when editing multiple files")) vbox.pack_start(cb, False, True, 0) cb = CCB(_("Show _programmatic tags"), 'editing', 'alltags', populate=True, tooltip=_("Access all tags, including machine-generated " "ones e.g. MusicBrainz or Replay Gain tags")) vbox.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') e.set_tooltip_text( _("A list of separators to use when splitting tag values. " "The list is space-separated")) def do_revert_split(button, section, option): config.reset(section, option) e.set_text(config.get(section, option)) split_revert = Gtk.Button() split_revert.add( Gtk.Image.new_from_stock(Gtk.STOCK_REVERT_TO_SAVED, Gtk.IconSize.MENU)) split_revert.connect("clicked", do_revert_split, "editing", "split_on") l = Gtk.Label(label=_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) hb.pack_start(split_revert, False, True, 0) vbox.pack_start(hb, False, True, 0) return vbox
def _config(section, option, label, tooltip, getter): def on_changed(entry, *args): config.set(section, option, entry.get_text()) entry = UndoEntry() entry.set_tooltip_text(tooltip) entry.set_text(decode(config.get(section, option))) entry.connect("changed", on_changed) def on_reverted(*args): config.reset(section, option) entry.set_text(decode(config.get(section, option))) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) return (Gtk.Label(label=label), entry, revert)
def PluginPreferences(cls, window): def key_changed(entry): cls.key_expression = None cls.config_set(cls._CFG_KEY_KEY, entry.get_text().strip()) vb = Gtk.VBox(spacing=10) vb.set_border_width(0) hbox = Gtk.HBox(spacing=6) # TODO: construct a decent validator and use ValidatingEntry e = UndoEntry() e.set_text(cls.get_key_expression()) e.connect("changed", key_changed) e.set_tooltip_markup( _("Accepts QL tag expressions like " "<tt>~artist~title</tt> or <tt>musicbrainz_track_id</tt>")) lbl = Gtk.Label(label=_("_Group duplicates by:")) lbl.set_mnemonic_widget(e) lbl.set_use_underline(True) hbox.pack_start(lbl, False, True, 0) hbox.pack_start(e, True, True, 0) frame = qltk.Frame(label=_("Duplicate Key"), child=hbox) vb.pack_start(frame, True, True, 0) # Matching Option toggles = [ (cls._CFG_REMOVE_WHITESPACE, _("Remove _Whitespace")), (cls._CFG_REMOVE_DIACRITICS, _("Remove _Diacritics")), (cls._CFG_REMOVE_PUNCTUATION, _("Remove _Punctuation")), (cls._CFG_CASE_INSENSITIVE, _("Case _Insensitive")), ] vb2 = Gtk.VBox(spacing=6) for key, label in toggles: ccb = ConfigCheckButton(label, 'plugins', cls._config_key(key)) ccb.set_active(cls.config_get_bool(key)) vb2.pack_start(ccb, True, True, 0) frame = qltk.Frame(label=_("Matching options"), child=vb2) vb.pack_start(frame, False, True, 0) vb.show_all() return vb
def _config(section, option, label, tooltip, getter): def on_changed(entry, *args): config.set(section, option, entry.get_text()) entry = UndoEntry() entry.set_tooltip_text(tooltip) entry.set_text(decode(config.get(section, option))) entry.connect("changed", on_changed) def on_reverted(*args): config.reset(section, option) entry.set_text(decode(config.get(section, option))) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) return (Gtk.Label(label=label), entry, revert)
def _config(section, option, label, tooltip=None, getter=None): def on_changed(entry, *args): config.settext(section, option, entry.get_text()) entry = UndoEntry() if tooltip: entry.set_tooltip_text(tooltip) entry.set_text(config.gettext(section, option)) entry.connect("changed", on_changed) def on_reverted(*args): config.reset(section, option) entry.set_text(config.gettext(section, option)) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) lbl = Gtk.Label(label=label, use_underline=True) lbl.set_mnemonic_widget(entry) return (lbl, entry, revert)
def _new_widget(self, key, val): """ Creates a Gtk.Entry subclass appropriate for a field named `key` with value `val` """ callback = signal = None if isinstance(val, bool): entry = Gtk.CheckButton() callback = self.__toggled_widget signal = "toggled" elif isinstance(val, int): adj = Gtk.Adjustment.new(0, 0, 9999, 1, 10, 0) entry = Gtk.SpinButton(adjustment=adj) entry.set_numeric(True) callback = self.__changed_numeric_widget elif "pattern" in key: entry = ValidatingEntry(validator=Query.validator) else: entry = UndoEntry() entry.connect(signal or "changed", callback or self.__changed_widget, key) return entry
def PluginPreferences(cls, window): def key_changed(entry): cls.key_expression = None cls.config_set(cls._CFG_KEY_KEY, entry.get_text().strip()) vb = Gtk.VBox(spacing=10) vb.set_border_width(0) hbox = Gtk.HBox(spacing=6) # TODO: construct a decent validator and use ValidatingEntry e = UndoEntry() e.set_text(cls.get_key_expression()) e.connect("changed", key_changed) e.set_tooltip_markup(_("Accepts QL tag expressions like " "<tt>~artist~title</tt> or <tt>musicbrainz_track_id</tt>")) lbl = Gtk.Label(label=_("_Group duplicates by:")) lbl.set_mnemonic_widget(e) lbl.set_use_underline(True) hbox.pack_start(lbl, False, True, 0) hbox.pack_start(e, True, True, 0) frame = qltk.Frame(label=_("Duplicate Key"), child=hbox) vb.pack_start(frame, True, True, 0) # Matching Option toggles = [ (cls._CFG_REMOVE_WHITESPACE, _("Remove _Whitespace")), (cls._CFG_REMOVE_DIACRITICS, _("Remove _Diacritics")), (cls._CFG_REMOVE_PUNCTUATION, _("Remove _Punctuation")), (cls._CFG_CASE_INSENSITIVE, _("Case _Insensitive")), ] vb2 = Gtk.VBox(spacing=6) for key, label in toggles: ccb = ConfigCheckButton(label, 'plugins', cls._config_key(key)) ccb.set_active(cls.config_get_bool(key)) vb2.pack_start(ccb, True, True, 0) frame = qltk.Frame(label=_("Matching options"), child=vb2) vb.pack_start(frame, False, True, 0) vb.show_all() return vb
def build_alternate_search_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) def on_entry_changed(entry, *args): self.Conf.alternate_search_url = entry.get_text() URL_entry = UndoEntry() URL_entry.set_text(self.Conf.alternate_search_url) URL_entry.connect("changed", on_entry_changed) l1 = ConfigLabel(_("URL:"), URL_entry) URL_revert = Gtk.Button() URL_revert.add( Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) URL_revert.set_tooltip_text(_("Revert to default")) connect_obj(URL_revert, "clicked", URL_entry.set_text, DEFAULT_ALTERNATE_SEARCH_URL) hb.pack_start(l1, False, True, 0) hb.pack_start(URL_entry, True, True, 0) hb.pack_start(URL_revert, False, True, 0) vb2.pack_start(hb, False, True, 0) def on_alternate_search_toggled(button, *args): self.Conf.alternate_search_enabled = button.get_active() alternate_search_enabled = Gtk.CheckButton(label=_( "Search via above URL if the lyrics " "couldn't be found in LyricsWikia."), use_underline=True) alternate_search_enabled.set_active( self.Conf.alternate_search_enabled) alternate_search_enabled.connect("toggled", on_alternate_search_toggled) vb2.pack_start(alternate_search_enabled, False, True, 0) return vb2
def __init__(self, parent, title, text, okbutton=Gtk.STOCK_OPEN): super(GetStringDialog, self).__init__( title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_default_size(width=self._WIDTH, height=0) self.set_resizable(True) self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, okbutton, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all()
def __init__(self, parent): if self.is_not_unique(): return super(PreferencesWindow, self).__init__() self.set_title(_("Ex Falso Preferences")) self.set_border_width(12) self.set_resizable(False) self.set_transient_for(parent) vbox = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') l = Gtk.Label(label=_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) cb = ConfigCheckButton( _("Show _programmatic tags"), 'editing', 'alltags', tooltip=_("Access all tags, including machine-generated " "ones e.g. MusicBrainz or Replay Gain tags")) cb.set_active(config.getboolean("editing", 'alltags')) vbox.pack_start(hb, False, True, 0) vbox.pack_start(cb, False, True, 0) f = qltk.Frame(_("Tag Editing"), child=vbox) close = Gtk.Button(stock=Gtk.STOCK_CLOSE) close.connect_object('clicked', lambda x: x.destroy(), self) button_box = Gtk.HButtonBox() button_box.set_layout(Gtk.ButtonBoxStyle.END) button_box.pack_start(close, True, True, 0) main_vbox = Gtk.VBox(spacing=12) main_vbox.pack_start(f, True, True, 0) main_vbox.pack_start(button_box, False, True, 0) self.add(main_vbox) self.connect_object('destroy', PreferencesWindow.__destroy, self) self.get_child().show_all()
def __init__(self, player, debug=False): super().__init__(spacing=6) e = UndoEntry() e.set_tooltip_text( _("The GStreamer output pipeline used for " "playback. Leave blank for the default pipeline. " "In case the pipeline contains a sink, " "it will be used instead of the default one.")) e.set_text(config.get('player', 'gst_pipeline')) def changed(entry): config.set('player', 'gst_pipeline', entry.get_text()) e.connect('changed', changed) pipe_label = Gtk.Label(label=_('_Output pipeline:')) pipe_label.set_use_underline(True) pipe_label.set_mnemonic_widget(e) apply_button = Button(_("_Apply")) def format_buffer(scale, value): return _("%.1f seconds") % value def scale_changed(scale): duration_msec = int(scale.get_value() * 1000) player._set_buffer_duration(duration_msec) duration = config.getfloat("player", "gst_buffer") scale = Gtk.HScale.new( Gtk.Adjustment(value=duration, lower=0.2, upper=10)) scale.set_value_pos(Gtk.PositionType.RIGHT) scale.set_show_fill_level(True) scale.connect('format-value', format_buffer) scale.connect('value-changed', scale_changed) buffer_label = Gtk.Label(label=_('_Buffer duration:')) buffer_label.set_use_underline(True) buffer_label.set_mnemonic_widget(scale) def rebuild_pipeline(*args): player._rebuild_pipeline() apply_button.connect('clicked', rebuild_pipeline) gapless_button = ConfigCheckButton( _('Disable _gapless playback'), "player", "gst_disable_gapless", populate=True, tooltip=_( "Disabling gapless playback can avoid track changing problems " "with some GStreamer versions")) jack_button = ConfigCheckButton( _('Use JACK for playback if available'), "player", "gst_use_jack", populate=True, tooltip=_( "Uses `jackaudiosink` for playbin sink if it can be detected")) jack_connect = ConfigCheckButton( _('Auto-connect to JACK output devices'), "player", "gst_jack_auto_connect", populate=True, tooltip=_("Tells `jackaudiosink` to auto-connect")) def _jack_toggled(widget: ConfigCheckButton) -> None: jack_connect.set_sensitive(widget.get_active()) jack_button.connect("clicked", _jack_toggled) _jack_toggled(jack_button) widgets = [(pipe_label, e, apply_button), (buffer_label, scale, None)] table = Gtk.Table(n_rows=len(widgets) + 3, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) for i, (left, middle, right) in enumerate(widgets): left.set_alignment(0.0, 0.5) table.attach(left, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) if right: table.attach(middle, 1, 2, i, i + 1) table.attach(right, 2, 3, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) else: table.attach(middle, 1, 3, i, i + 1) table.attach(gapless_button, 0, 3, 2, 3) table.attach(jack_button, 0, 3, 3, 4) table.attach(jack_connect, 0, 3, 4, 5) self.pack_start(table, True, True, 0) if debug: def print_bin(player): player._print_pipeline() b = Button("Print Pipeline", Icons.DIALOG_INFORMATION) connect_obj(b, 'clicked', print_bin, player) self.pack_start(b, True, True, 0)
def __init__(self, player, debug=False): super(GstPlayerPreferences, self).__init__(spacing=6) e = UndoEntry() e.set_tooltip_text(_("The GStreamer output pipeline used for " "playback. Leave blank for the default pipeline. " "In case the pipeline contains a sink, " "it will be used instead of the default one.")) e.set_text(config.get('player', 'gst_pipeline')) def changed(entry): config.set('player', 'gst_pipeline', entry.get_text()) e.connect('changed', changed) pipe_label = Gtk.Label(label=_('_Output pipeline:')) pipe_label.set_use_underline(True) pipe_label.set_mnemonic_widget(e) apply_button = Gtk.Button(stock=Gtk.STOCK_APPLY) def format_buffer(scale, value): return _("%.1f seconds") % value def scale_changed(scale): duration_msec = int(scale.get_value() * 1000) player._set_buffer_duration(duration_msec) duration = config.getfloat("player", "gst_buffer") scale = Gtk.HScale.new( Gtk.Adjustment(value=duration, lower=0.2, upper=10)) scale.set_value_pos(Gtk.PositionType.RIGHT) scale.set_show_fill_level(True) scale.connect('format-value', format_buffer) scale.connect('value-changed', scale_changed) buffer_label = Gtk.Label(label=_('_Buffer duration:')) buffer_label.set_use_underline(True) buffer_label.set_mnemonic_widget(scale) def rebuild_pipeline(*args): player._rebuild_pipeline() apply_button.connect('clicked', rebuild_pipeline) gapless_button = ConfigCheckButton( _('Disable _gapless playback'), "player", "gst_disable_gapless", populate=True) gapless_button.set_alignment(0.0, 0.5) gapless_button.set_tooltip_text( _("Disabling gapless playback can avoid track changing problems " "with some GStreamer versions.")) widgets = [(pipe_label, e, apply_button), (buffer_label, scale, None), ] table = Gtk.Table(n_rows=len(widgets), n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) for i, (left, middle, right) in enumerate(widgets): left.set_alignment(0.0, 0.5) table.attach(left, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) if right: table.attach(middle, 1, 2, i, i + 1) table.attach(right, 2, 3, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) else: table.attach(middle, 1, 3, i, i + 1) table.attach(gapless_button, 0, 3, 2, 3) self.pack_start(table, True, True, 0) if debug: def print_bin(player): player._print_pipeline() b = Button("Print Pipeline", Gtk.STOCK_DIALOG_INFO) connect_obj(b, 'clicked', print_bin, player) self.pack_start(b, True, True, 0)
def ratings_vbox(self): """Returns a new VBox containing all ratings widgets""" vb = Gtk.VBox(spacing=6) # Default Rating model = Gtk.ListStore(float) default_combo = Gtk.ComboBox(model=model) default_lab = Gtk.Label(label=_("_Default rating:")) default_lab.set_use_underline(True) default_lab.set_alignment(0, 0.5) def draw_rating(column, cell, model, it, data): num = model[it][0] text = "%0.2f: %s" % (num, util.format_rating(num)) cell.set_property('text', text) def default_rating_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.default = model[it][0] def populate_default_rating_model(combo, num): model = combo.get_model() model.clear() deltas = [] default = RATINGS.default precision = RATINGS.precision for i in range(0, num + 1): r = i * precision model.append(row=[r]) deltas.append((abs(default - r), i)) active = sorted(deltas)[0][1] print_d("Choosing #%d (%.2f), closest to current %.2f" % (active, precision * active, default)) combo.set_active(active) cell = Gtk.CellRendererText() default_combo.pack_start(cell, True) default_combo.set_cell_data_func(cell, draw_rating, None) default_combo.connect('changed', default_rating_changed, model) default_lab.set_mnemonic_widget(default_combo) def refresh_default_combo(num): populate_default_rating_model(default_combo, num) # Rating Scale model = Gtk.ListStore(int) scale_combo = Gtk.ComboBox(model=model) scale_lab = Gtk.Label(label=_("Rating _Scale:")) scale_lab.set_use_underline(True) scale_lab.set_mnemonic_widget(scale_combo) cell = Gtk.CellRendererText() scale_combo.pack_start(cell, False) num = RATINGS.number for i in [1, 2, 3, 4, 5, 6, 8, 10]: it = model.append(row=[i]) if i == num: scale_combo.set_active_iter(it) def draw_rating_scale(column, cell, model, it, data): num_stars = model[it][0] text = "%d: %s" % (num_stars, RATINGS.full_symbol * num_stars) cell.set_property('text', text) def rating_scale_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.number = num = model[it][0] refresh_default_combo(num) refresh_default_combo(RATINGS.number) scale_combo.set_cell_data_func(cell, draw_rating_scale, None) scale_combo.connect('changed', rating_scale_changed, model) default_align = Gtk.Alignment(xalign=0, xscale=0) default_align.add(default_lab) default_combo_align = Gtk.Alignment(xalign=0, xscale=0) default_combo_align.add(default_combo) scale_align = Gtk.Alignment(xalign=0, xscale=0) scale_align.add(scale_lab) grid = Gtk.Grid(column_spacing=6, row_spacing=6) grid.add(scale_align) grid.add(scale_combo) grid.attach(default_align, 0, 1, 1, 1) grid.attach(default_combo_align, 1, 1, 1, 1) vb.pack_start(grid, False, False, 6) # Bayesian Factor bayesian_factor = config.getfloat("settings", "bayesian_rating_factor", 0.0) adj = Gtk.Adjustment.new(bayesian_factor, 0.0, 10.0, 0.5, 0.5, 0.0) bayes_spin = Gtk.SpinButton(adjustment=adj, numeric=True) bayes_spin.set_digits(1) bayes_spin.connect('changed', self.__changed_and_signal_library, 'settings', 'bayesian_rating_factor') bayes_spin.set_tooltip_text( _("Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that " "albums with few tracks will have less extreme ratings. " "Changing this value triggers a re-calculation for all " "albums.")) bayes_label = Gtk.Label(label=_("_Bayesian averaging amount:")) bayes_label.set_use_underline(True) bayes_label.set_mnemonic_widget(bayes_spin) # Save Ratings hb = Gtk.HBox(spacing=6) hb.pack_start(bayes_label, False, True, 0) hb.pack_start(bayes_spin, False, True, 0) vb.pack_start(hb, True, True, 0) cb = CCB(_("Save ratings and play _counts"), "editing", "save_to_songs", populate=True) vb.pack_start(cb, True, True, 0) hb = Gtk.HBox(spacing=6) lab = Gtk.Label(label=_("_Email:")) entry = UndoEntry() entry.set_tooltip_text(_("Ratings and play counts will be set " "for this email address")) entry.set_text(config.get("editing", "save_email")) entry.connect('changed', self.__changed, 'editing', 'save_email') hb.pack_start(lab, False, True, 0) hb.pack_start(entry, True, True, 0) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb.pack_start(hb, True, True, 0) return vb
def __init__(self): super(PreferencesWindow.SongList, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") # Behaviour vbox = Gtk.VBox(spacing=6) c = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) vbox.pack_start(c, False, True, 0) frame = qltk.Frame(_("Behavior"), child=vbox) self.pack_start(frame, False, True, 0) # Columns vbox = Gtk.VBox(spacing=12) buttons = {} table = Gtk.Table.new(3, 3, True) cols = get_columns() for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) if k in cols: buttons[k].set_active(True) cols.remove(k) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) if "~current" in cols: cols.remove("~current") self.other_cols = cols # Other columns hbox = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Others:"), use_underline=True) hbox.pack_start(l, False, True, 0) self.others = others = UndoEntry() others.set_sensitive(False) # Stock edit doesn't have ellipsis chars. edit_button = Gtk.Button(label=_("_Edit..."), use_underline=True) edit_button.connect("clicked", self.__config_cols) edit_button.set_tooltip_text(_("Add or remove additional column " "headers")) l.set_mnemonic_widget(edit_button) l.set_use_underline(True) hbox.pack_start(others, True, True, 0) hbox.pack_start(edit_button, False, True, 0) vbox.pack_start(hbox, False, True, 0) frame = qltk.Frame(_("Visible Columns"), child=vbox) self.pack_start(frame, False, True, 0) # Column preferences tiv = Gtk.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] # Turn on the toggles if the toggled version is detected in config for (check, off, on) in self._toggle_data: if on in cols: buttons[off].set_active(True) check.set_active(True) cols.remove(on) # Update text once to exclude ticked columns, munged or not others.set_text(", ".join(cols)) t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) frame = qltk.Frame(_("Column Preferences"), child=t) self.pack_start(frame, False, True, 0) # Apply button vbox = Gtk.VBox(spacing=12) apply = Gtk.Button(stock=Gtk.STOCK_APPLY) apply.set_tooltip_text(_("Apply current configuration to song " "list, adding new columns to the end")) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(apply, True, True, 0) vbox.pack_start(b, True, True, 0) self.pack_start(vbox, True, True, 0) apply.connect('clicked', self.__apply, buttons, tiv, aip, fip, aio) # Apply on destroy, else config gets mangled self.connect('destroy', self.__apply, buttons, tiv, aip, fip, aio) for child in self.get_children(): child.show_all()
def PluginPreferences(self, parent): outer_vb = Gtk.VBox(spacing=12) vb = Gtk.VBox(spacing=12) # Playing hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_PAT_PLAYING, self.DEFAULT_PAT)) entry.connect('changed', self.config_entry_changed, self.CFG_PAT_PLAYING) lbl = Gtk.Label(label=_("Playing:")) entry.set_tooltip_markup(_("Status text when a song is started. " "Accepts QL Patterns e.g. %s") % util.monospace( util.escape("<~artist~title>"))) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Paused hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_PAT_PAUSED, self.DEFAULT_PAT_PAUSED)) entry.connect('changed', self.config_entry_changed, self.CFG_PAT_PAUSED) lbl = Gtk.Label(label=_("Paused:")) entry.set_tooltip_markup(_("Status text when a song is paused. " "Accepts QL Patterns e.g. %s") % util.monospace( util.escape("<~artist~title>"))) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # No Song hb = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(self.config_get(self.CFG_STATUS_SONGLESS, "")) entry.connect('changed', self.config_entry_changed, self.CFG_STATUS_SONGLESS) entry.set_tooltip_text( _("Plain text for status when there is no current song")) lbl = Gtk.Label(label=_("No song:")) lbl.set_mnemonic_widget(entry) hb.pack_start(lbl, False, True, 0) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, True, True, 0) # Frame frame = qltk.Frame(_("Status Patterns"), child=vb) outer_vb.pack_start(frame, False, True, 0) return outer_vb
def __init__(self): super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") # Search vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.is_valid_color) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action f = qltk.Frame(Q_("heading|Search"), child=vb) self.pack_start(f, False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) # Album Art vb = Gtk.VBox(spacing=6) c = CCB(_("_Use rounded corners on thumbnails"), 'albumart', 'round', populate=True, tooltip=_("Round the corners of album artwork thumbnail " "images. May require restart to take effect.")) vb.pack_start(c, False, True, 0) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def PluginPreferences(cls, parent): def value_changed(entry, key): if entry.get_property('sensitive'): cls.server.config[key] = entry.get_text() config.set("plugins", "squeezebox_" + key, entry.get_text()) vb = Gtk.VBox(spacing=12) if not cls.server: cls.init_server() cfg = cls.server.config # Server settings Frame cfg_frame = Gtk.Frame(label=_("<b>Squeezebox Server</b>")) cfg_frame.set_shadow_type(Gtk.ShadowType.NONE) cfg_frame.get_label_widget().set_use_markup(True) cfg_frame_align = Gtk.Alignment.new(0, 0, 1, 1) cfg_frame_align.set_padding(6, 6, 12, 12) cfg_frame.add(cfg_frame_align) # Tabulate all settings for neatness table = Gtk.Table(n_rows=3, n_columns=2) table.set_col_spacings(6) table.set_row_spacings(6) rows = [] ve = UndoEntry() ve.set_text(cfg["hostname"]) ve.connect('changed', value_changed, 'server_hostname') rows.append((Gtk.Label(label=_("Hostname:")), ve)) ve = UndoEntry() ve.set_width_chars(5) ve.set_text(str(cfg["port"])) ve.connect('changed', value_changed, 'server_port') rows.append((Gtk.Label(label=_("Port:")), ve)) ve = UndoEntry() ve.set_text(cfg["user"]) ve.connect('changed', value_changed, 'server_user') rows.append((Gtk.Label(label=_("Username:"******"password"])) ve.connect('changed', value_changed, 'server_password') rows.append((Gtk.Label(label=_("Password:"******"library_dir"])) ve.set_tooltip_text(_("Library directory the server connects to.")) ve.connect('changed', value_changed, 'server_library_dir') rows.append((Gtk.Label(label=_("Library path:")), ve)) for (row, (label, entry)) in enumerate(rows): label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, row, row + 1, xoptions=Gtk.AttachOptions.FILL) table.attach(entry, 1, 2, row, row + 1) # Add verify button button = Gtk.Button(label=_("_Verify settings"), use_underline=True) button.set_sensitive(cls.server is not None) button.connect('clicked', cls.check_settings) table.attach(button, 0, 2, row + 1, row + 2) cfg_frame_align.add(table) vb.pack_start(cfg_frame, True, True, 0) debug = cls.ConfigCheckButton(_("Debug"), "debug") vb.pack_start(debug, True, True, 0) return vb
def ratings_vbox(self): """Returns a new VBox containing all ratings widgets""" vb = Gtk.VBox(spacing=6) # Default Rating model = Gtk.ListStore(float) default_combo = Gtk.ComboBox(model=model) default_lab = Gtk.Label(label=_("_Default rating:")) default_lab.set_use_underline(True) default_lab.set_alignment(0, 0.5) def draw_rating(column, cell, model, it, data): num = model[it][0] text = "%0.2f: %s" % (num, util.format_rating(num)) cell.set_property('text', text) def default_rating_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.default = model[it][0] qltk.redraw_all_toplevels() def populate_default_rating_model(combo, num): model = combo.get_model() model.clear() deltas = [] default = RATINGS.default precision = RATINGS.precision for i in range(0, num + 1): r = i * precision model.append(row=[r]) deltas.append((abs(default - r), i)) active = sorted(deltas)[0][1] print_d("Choosing #%d (%.2f), closest to current %.2f" % (active, precision * active, default)) combo.set_active(active) cell = Gtk.CellRendererText() default_combo.pack_start(cell, True) default_combo.set_cell_data_func(cell, draw_rating, None) default_combo.connect('changed', default_rating_changed, model) default_lab.set_mnemonic_widget(default_combo) def refresh_default_combo(num): populate_default_rating_model(default_combo, num) # Rating Scale model = Gtk.ListStore(int) scale_combo = Gtk.ComboBox(model=model) scale_lab = Gtk.Label(label=_("Rating _scale:")) scale_lab.set_use_underline(True) scale_lab.set_mnemonic_widget(scale_combo) cell = Gtk.CellRendererText() scale_combo.pack_start(cell, False) num = RATINGS.number for i in [1, 2, 3, 4, 5, 6, 8, 10]: it = model.append(row=[i]) if i == num: scale_combo.set_active_iter(it) def draw_rating_scale(column, cell, model, it, data): num_stars = model[it][0] text = "%d: %s" % (num_stars, RATINGS.full_symbol * num_stars) cell.set_property('text', text) def rating_scale_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.number = num = model[it][0] refresh_default_combo(num) refresh_default_combo(RATINGS.number) scale_combo.set_cell_data_func(cell, draw_rating_scale, None) scale_combo.connect('changed', rating_scale_changed, model) default_align = Align(halign=Gtk.Align.START) default_align.add(default_lab) scale_align = Align(halign=Gtk.Align.START) scale_align.add(scale_lab) grid = Gtk.Grid(column_spacing=6, row_spacing=6) grid.add(scale_align) grid.add(scale_combo) grid.attach(default_align, 0, 1, 1, 1) grid.attach(default_combo, 1, 1, 1, 1) vb.pack_start(grid, False, False, 6) # Bayesian Factor bayesian_factor = config.getfloat("settings", "bayesian_rating_factor", 0.0) adj = Gtk.Adjustment.new(bayesian_factor, 0.0, 10.0, 0.5, 0.5, 0.0) bayes_spin = Gtk.SpinButton(adjustment=adj, numeric=True) bayes_spin.set_digits(1) bayes_spin.connect('changed', self.__changed_and_signal_library, 'settings', 'bayesian_rating_factor') bayes_spin.set_tooltip_text( _("Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that " "albums with few tracks will have less extreme ratings. " "Changing this value triggers a re-calculation for all " "albums.")) bayes_label = Gtk.Label(label=_("_Bayesian averaging amount:")) bayes_label.set_use_underline(True) bayes_label.set_mnemonic_widget(bayes_spin) # Save Ratings hb = Gtk.HBox(spacing=6) hb.pack_start(bayes_label, False, True, 0) hb.pack_start(bayes_spin, False, True, 0) vb.pack_start(hb, True, True, 0) cb = CCB(_("Save ratings and play _counts"), "editing", "save_to_songs", populate=True) vb.pack_start(cb, True, True, 0) hb = Gtk.HBox(spacing=6) lab = Gtk.Label(label=_("_Email:")) entry = UndoEntry() entry.set_tooltip_text(_("Ratings and play counts will be set " "for this email address")) entry.set_text(config.get("editing", "save_email")) entry.connect('changed', self.__changed, 'editing', 'save_email') hb.pack_start(lab, False, True, 0) hb.pack_start(entry, True, True, 0) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb.pack_start(hb, True, True, 0) return vb
def PluginPreferences(self, parent): def changed(entry, key): if entry.get_property('sensitive'): plugin_config.set(key, entry.get_text()) def combo_changed(widget, urlent): service = widget.get_active_text() plugin_config.set("service", service) urlent.set_sensitive((service not in SERVICES)) urlent.set_text(config_get_url()) def check_login(*args): queue = QLSubmitQueue() queue.changed() status = queue.send_handshake(show_dialog=True) if status: queue.quick_dialog(_("Authentication successful."), Gtk.MessageType.INFO) box = Gtk.VBox(spacing=12) # first frame table = Gtk.Table(n_rows=5, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = [] label_names = [_("_Service:"), _("_URL:"), _("User_name:"), _("_Password:"******"Other…") for idx, serv in enumerate(sorted(SERVICES.keys()) + [other_label]): service_combo.append_text(serv) if cur_service == serv: service_combo.set_active(idx) if service_combo.get_active() == -1: service_combo.set_active(0) labels[row].set_mnemonic_widget(service_combo) row += 1 # url entry = UndoEntry() entry.set_text(plugin_config.get('url')) entry.connect('changed', changed, 'url') service_combo.connect('changed', combo_changed, entry) service_combo.emit('changed') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # username entry = UndoEntry() entry.set_text(plugin_config.get('username')) entry.connect('changed', changed, 'username') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # password entry = UndoEntry() entry.set_text(plugin_config.get('password')) entry.set_visibility(False) entry.connect('changed', changed, 'password') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # verify data button = qltk.Button(_("_Verify account data"), Icons.DIALOG_INFORMATION) button.connect('clicked', check_login) table.attach(button, 0, 2, 4, 5) box.pack_start(qltk.Frame(_("Account"), child=table), True, True, 0) # second frame table = Gtk.Table(n_rows=4, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) label_names = [_("_Artist pattern:"), _("_Title pattern:"), _("Exclude _filter:")] labels = [] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # artist pattern entry = UndoEntry() entry.set_text(plugin_config.get('artistpat')) entry.connect('changed', changed, 'artistpat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the artist name for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # title pattern entry = UndoEntry() entry.set_text(plugin_config.get('titlepat')) entry.connect('changed', changed, 'titlepat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text(_("The pattern used to format " "the title for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # exclude filter entry = ValidatingEntry(Query.validator) entry.set_text(plugin_config.get('exclude')) entry.set_tooltip_text( _("Songs matching this filter will not be submitted.")) entry.connect('changed', changed, 'exclude') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # offline mode offline = plugin_config.ConfigCheckButton( _("_Offline mode (don't submit anything)"), 'offline', populate=True) table.attach(offline, 0, 2, row, row + 1) box.pack_start(qltk.Frame(_("Submission"), child=table), True, True, 0) return box
def __init__(self): def create_display_frame(): vbox = Gtk.VBox(spacing=6) model = Gtk.ListStore(str, str) def on_changed(combo): it = combo.get_active_iter() if it is None: return DURATION.format = model[it][0] app.window.songlist.info.refresh() app.window.qexpander.refresh() # TODO: refresh info windows ideally too (but see #2019) def draw_duration(column, cell, model, it, data): df, example = model[it] cell.set_property('text', example) for df in sorted(DurationFormat.values): # 4954s == longest ever CD, FWIW model.append([df, format_time_preferred(4954, df)]) duration = Gtk.ComboBox(model=model) cell = Gtk.CellRendererText() duration.pack_start(cell, True) duration.set_cell_data_func(cell, draw_duration, None) index = sorted(DurationFormat.values).index(DURATION.format) duration.set_active(index) duration.connect('changed', on_changed) hbox = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("Duration totals") + ":", use_underline=True) label.set_mnemonic_widget(duration) hbox.pack_start(label, False, True, 0) hbox.pack_start(duration, False, True, 0) vbox.pack_start(hbox, False, True, 0) return qltk.Frame(_("Display"), child=vbox) def create_search_frame(): vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.validator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text( _("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action return qltk.Frame(C_("heading", "Search"), child=vb) super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") self.pack_start(create_search_frame(), False, True, 0) self.pack_start(create_display_frame(), False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def __init__(self, parent, plugin_instance): GObject.GObject.__init__(self, spacing=12) self.plugin_instance = plugin_instance # notification text settings table = Gtk.Table(n_rows=2, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) text_frame = qltk.Frame(_("Notification text"), child=table) title_entry = UndoEntry() title_entry.set_text(pconfig.gettext("titlepattern")) def on_entry_changed(entry, cfgname): pconfig.settext(cfgname, entry.get_text()) title_entry.connect("changed", on_entry_changed, "titlepattern") table.attach(title_entry, 1, 2, 0, 1) title_label = Gtk.Label(label=_("_Title:")) title_label.set_use_underline(True) title_label.set_alignment(0, 0.5) title_label.set_mnemonic_widget(title_entry) table.attach(title_label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) title_revert = Gtk.Button() title_revert.add( Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) title_revert.set_tooltip_text(_("Revert to default pattern")) title_revert.connect( "clicked", lambda *x: title_entry.set_text( pconfig.defaults.gettext("titlepattern"))) table.attach(title_revert, 2, 3, 0, 1, xoptions=Gtk.AttachOptions.SHRINK) body_textbuffer = TextBuffer() body_textview = TextView(buffer=body_textbuffer) body_textview.set_size_request(-1, 85) body_textview.get_buffer().set_text(pconfig.gettext("bodypattern")) def on_textbuffer_changed(text_buffer, cfgname): start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, True) pconfig.settext(cfgname, text) body_textbuffer.connect("changed", on_textbuffer_changed, "bodypattern") body_scrollarea = Gtk.ScrolledWindow() body_scrollarea.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) body_scrollarea.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) body_scrollarea.add(body_textview) table.attach(body_scrollarea, 1, 2, 1, 2) body_label = Gtk.Label(label=_("_Body:")) body_label.set_padding(0, 3) body_label.set_use_underline(True) body_label.set_alignment(0, 0) body_label.set_mnemonic_widget(body_textview) table.attach(body_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.SHRINK) body_revert = Gtk.Button() body_revert.add( Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) body_revert.set_tooltip_text(_("Revert to default pattern")) body_revert.connect( "clicked", lambda *x: body_textbuffer.set_text( pconfig.defaults.gettext("bodypattern"))) table.attach(body_revert, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.SHRINK, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) # preview button preview_button = qltk.Button(_("_Show notification"), Icons.SYSTEM_RUN) preview_button.set_sensitive(app.player.info is not None) preview_button.connect("clicked", self.on_preview_button_clicked) self.qlplayer_connected_signals = [ app.player.connect("paused", self.on_player_state_changed, preview_button), app.player.connect("unpaused", self.on_player_state_changed, preview_button), ] table.attach(preview_button, 0, 3, 2, 3, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) self.pack_start(text_frame, True, True, 0) # notification display settings display_box = Gtk.VBox(spacing=12) display_frame = qltk.Frame(_("Show notifications"), child=display_box) radio_box = Gtk.VBox(spacing=6) display_box.pack_start(radio_box, True, True, 0) only_user_radio = Gtk.RadioButton( label=_("Only on <i>_manual</i> song changes"), use_underline=True) only_user_radio.get_child().set_use_markup(True) only_user_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "user") radio_box.pack_start(only_user_radio, True, True, 0) only_auto_radio = Gtk.RadioButton( group=only_user_radio, label=_("Only on <i>_automatic</i> song changes"), use_underline=True) only_auto_radio.get_child().set_use_markup(True) only_auto_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "auto") radio_box.pack_start(only_auto_radio, True, True, 0) all_radio = Gtk.RadioButton(group=only_user_radio, label=_("On <i>a_ll</i> song changes"), use_underline=True) all_radio.get_child().set_use_markup(True) all_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "all") radio_box.pack_start(all_radio, True, True, 0) { "user": only_user_radio, "auto": only_auto_radio, "all": all_radio }.get(pconfig.gettext("show_notifications"), all_radio).set_active(True) focus_check = Gtk.CheckButton( label=_("Only when the main window is not _focused"), use_underline=True) focus_check.set_active(pconfig.getboolean("show_only_when_unfocused")) focus_check.connect("toggled", self.on_checkbutton_toggled, "show_only_when_unfocused") display_box.pack_start(focus_check, True, True, 0) show_next = Gtk.CheckButton(label=_("Show \"_Next\" button"), use_underline=True) show_next.set_active(pconfig.getboolean("show_next_button")) show_next.connect("toggled", self.on_checkbutton_toggled, "show_next_button") display_box.pack_start(show_next, True, True, 0) self.pack_start(display_frame, True, True, 0) self.show_all() self.connect("destroy", self.on_destroyed)
def PluginPreferences(self, parent): table = Gtk.Table(n_rows=2, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) label = Gtk.Label(label=_("_Port:"), use_underline=True) label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) entry = UndoEntry() entry.set_text(str(get_port_num())) def validate_port(entry, text, *args): try: int(text) except ValueError: entry.stop_emission("insert-text") entry.connect("insert-text", validate_port) def port_activate(entry, *args): try: port_num = int(entry.get_text()) except ValueError as e: print_w(str(e)) else: if get_port_num() != port_num: set_port_num(port_num) self._refresh() entry.connect_after("activate", port_activate) entry.connect_after("focus-out-event", port_activate) table.attach(entry, 1, 2, 0, 1) port_revert = Gtk.Button() port_revert.add(Gtk.Image.new_from_stock(Gtk.STOCK_REVERT_TO_SAVED, Gtk.IconSize.MENU)) def port_revert_cb(button, entry): entry.set_text(str(DEFAULT_PORT)) entry.emit("activate") port_revert.connect("clicked", port_revert_cb, entry) table.attach(port_revert, 2, 3, 0, 1, xoptions=Gtk.AttachOptions.SHRINK) label = Gtk.Label(label=_("Local _IP:"), use_underline=True) label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) entry = UndoEntry() entry.set_text("...") entry.set_editable(False) table.attach(entry, 1, 3, 1, 2) threading.Thread(target=fill_ip, args=(entry,)).start() box = Gtk.VBox(spacing=12) clients = Gtk.Label() clients.set_padding(6, 6) clients.set_markup( u"""\ \u2022 <a href="https://play.google.com/store/apps/details?id=com.\ namelessdev.mpdroid">MPDroid 1.06</a> (Android)<small> </small>\u2022 <a href="http://sonata.berlios.de/">Sonata 1.6</a> (Linux)\ """ ) clients.set_alignment(0, 0) box.pack_start(qltk.Frame(_("Connection"), child=table), False, True, 0) box.pack_start(qltk.Frame(_("Tested Clients"), child=clients), True, True, 0) return box
def __init__(self): super(PreferencesWindow.Tagging, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Tags") vbox = gtk.VBox(spacing=6) cb = ConfigCheckButton(_("Auto-save tag changes"), 'editing', 'auto_save_changes', populate=True) cb.set_tooltip_text(_("Save changes to tags without confirmation " "when editing multiple files")) vbox.pack_start(cb, expand=False) cb = ConfigCheckButton(_("Show _programmatic tags"), 'editing', 'alltags', populate=True) cb.set_tooltip_text( _("Access all tags, including machine-generated ones " "e.g. MusicBrainz or Replay Gain tags")) vbox.pack_start(cb, expand=False) hb = gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("editing", "split_on")) e.connect('changed', self.__changed, 'editing', 'split_on') e.set_tooltip_text( _("A list of separators to use when splitting tag values. " "The list is space-separated")) l = gtk.Label(_("Split _on:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, expand=False) hb.pack_start(e) vbox.pack_start(hb, expand=False) vb2 = gtk.VBox(spacing=6) cb = ConfigCheckButton(_("Save ratings and play _counts"), "editing", "save_to_songs", populate=True) vb2.pack_start(cb) hb = gtk.HBox(spacing=6) lab = gtk.Label(_("_Email:")) entry = UndoEntry() entry.set_tooltip_text(_("Ratings and play counts will be set " "for this email address")) entry.set_text(config.get("editing", "save_email")) entry.connect('changed', self.__changed, 'editing', 'save_email') hb.pack_start(lab, expand=False) hb.pack_start(entry) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb2.pack_start(hb) f = qltk.Frame(_("Tag Editing"), child=vbox) self.pack_start(f, expand=False) f = qltk.Frame(_("Ratings"), child=vb2) self.pack_start(f, expand=False) self.show_all()
def __init__(self): super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") # Search vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(QueryValidator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action f = qltk.Frame(C_("heading", "Search"), child=vb) self.pack_start(f, False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def setUp(self): self.entry = UndoEntry()
class GetStringDialog(Dialog): """Simple dialog to return a string from the user""" _WIDTH = 300 def __init__(self, parent, title, text, okbutton=Gtk.STOCK_OPEN): super(GetStringDialog, self).__init__(title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_default_size(width=self._WIDTH, height=0) self.set_resizable(True) self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, okbutton, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all() def _verify_clipboard(self, text): """Return an altered text or None if the content was invalid.""" return def run(self, text="", clipboard=False, test=False): """Shows the dialog and returns the entered value. If clipboard is set, the initial value will be pulled from the clipboard and can be verified/altered by _verify_clipboard. In case the verification fails text will be used as fallback""" self.show() if clipboard: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clip = clipboard.wait_for_text() if clip is not None: clip = self._verify_clipboard(clip) if clip is not None: text = clip self._val.set_text(text) self._val.set_activates_default(True) self._val.grab_focus() resp = Gtk.ResponseType.OK if not test: resp = super(GetStringDialog, self).run() if resp == Gtk.ResponseType.OK: value = self._val.get_text() else: value = None self.destroy() return value
def __init__(self, parent, plugin_instance): GObject.GObject.__init__(self, spacing=12) self.plugin_instance = plugin_instance # notification text settings table = Gtk.Table(n_rows=2, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) text_frame = qltk.Frame(_("Notification text"), child=table) title_entry = UndoEntry() title_entry.set_text(pconfig.gettext("titlepattern")) def on_entry_changed(entry, cfgname): pconfig.settext(cfgname, entry.get_text()) title_entry.connect("changed", on_entry_changed, "titlepattern") table.attach(title_entry, 1, 2, 0, 1) title_label = Gtk.Label(label=_("_Title:")) title_label.set_use_underline(True) title_label.set_alignment(0, 0.5) title_label.set_mnemonic_widget(title_entry) table.attach(title_label, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) title_revert = Gtk.Button() title_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) title_revert.set_tooltip_text(_("Revert to default pattern")) title_revert.connect( "clicked", lambda *x: title_entry.set_text( pconfig.defaults.gettext("titlepattern"))) table.attach(title_revert, 2, 3, 0, 1, xoptions=Gtk.AttachOptions.SHRINK) body_textbuffer = TextBuffer() body_textview = TextView(buffer=body_textbuffer) body_textview.set_size_request(-1, 85) body_textview.get_buffer().set_text(pconfig.gettext("bodypattern")) def on_textbuffer_changed(text_buffer, cfgname): start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, True) pconfig.settext(cfgname, text) body_textbuffer.connect("changed", on_textbuffer_changed, "bodypattern") body_scrollarea = Gtk.ScrolledWindow() body_scrollarea.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) body_scrollarea.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) body_scrollarea.add(body_textview) table.attach(body_scrollarea, 1, 2, 1, 2) body_label = Gtk.Label(label=_("_Body:")) body_label.set_padding(0, 3) body_label.set_use_underline(True) body_label.set_alignment(0, 0) body_label.set_mnemonic_widget(body_textview) table.attach(body_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.SHRINK) body_revert = Gtk.Button() body_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) body_revert.set_tooltip_text(_("Revert to default pattern")) body_revert.connect("clicked", lambda *x: body_textbuffer.set_text(pconfig.defaults.gettext("bodypattern"))) table.attach( body_revert, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.SHRINK, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) # preview button preview_button = qltk.Button( _("_Show notification"), Icons.SYSTEM_RUN) preview_button.set_sensitive(app.player.info is not None) preview_button.connect("clicked", self.on_preview_button_clicked) self.qlplayer_connected_signals = [ app.player.connect("paused", self.on_player_state_changed, preview_button), app.player.connect("unpaused", self.on_player_state_changed, preview_button), ] table.attach( preview_button, 0, 3, 2, 3, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) self.pack_start(text_frame, True, True, 0) # notification display settings display_box = Gtk.VBox(spacing=12) display_frame = qltk.Frame(_("Show notifications"), child=display_box) radio_box = Gtk.VBox(spacing=6) display_box.pack_start(radio_box, True, True, 0) only_user_radio = Gtk.RadioButton(label=_( "Only on <i>_manual</i> song changes" ), use_underline=True) only_user_radio.get_child().set_use_markup(True) only_user_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "user") radio_box.pack_start(only_user_radio, True, True, 0) only_auto_radio = Gtk.RadioButton(group=only_user_radio, label=_( "Only on <i>_automatic</i> song changes" ), use_underline=True) only_auto_radio.get_child().set_use_markup(True) only_auto_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "auto") radio_box.pack_start(only_auto_radio, True, True, 0) all_radio = Gtk.RadioButton(group=only_user_radio, label=_( "On <i>a_ll</i> song changes" ), use_underline=True) all_radio.get_child().set_use_markup(True) all_radio.connect("toggled", self.on_radiobutton_toggled, "show_notifications", "all") radio_box.pack_start(all_radio, True, True, 0) { "user": only_user_radio, "auto": only_auto_radio, "all": all_radio }.get(pconfig.gettext("show_notifications"), all_radio).set_active(True) focus_check = Gtk.CheckButton( label=_("Only when the main window is not _focused"), use_underline=True) focus_check.set_active(pconfig.getboolean("show_only_when_unfocused")) focus_check.connect("toggled", self.on_checkbutton_toggled, "show_only_when_unfocused") display_box.pack_start(focus_check, True, True, 0) show_next = Gtk.CheckButton( label=_("Show \"_Next\" button"), use_underline=True) show_next.set_active(pconfig.getboolean("show_next_button")) show_next.connect("toggled", self.on_checkbutton_toggled, "show_next_button") display_box.pack_start(show_next, True, True, 0) self.pack_start(display_frame, True, True, 0) self.show_all() self.connect("destroy", self.on_destroyed)
class GetStringDialog(Dialog): """Simple dialog to return a string from the user""" def __init__(self, parent, title, text, button_label=_("_OK"), button_icon=Icons.DOCUMENT_OPEN, tooltip=None): super(GetStringDialog, self).__init__( title=title, transient_for=parent, use_header_bar=True) self.set_border_width(6) self.set_resizable(True) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(button_label, button_icon, Gtk.ResponseType.OK) self.vbox.set_spacing(6) self.set_default_response(Gtk.ResponseType.OK) box = Gtk.VBox(spacing=6) lab = Gtk.Label(label=text) box.set_border_width(6) lab.set_line_wrap(True) lab.set_justify(Gtk.Justification.CENTER) box.pack_start(lab, True, True, 0) self._val = UndoEntry() if tooltip: self._val.set_tooltip_text(tooltip) self._val.set_max_width_chars(50) box.pack_start(self._val, True, True, 0) self.vbox.pack_start(box, True, True, 0) self.get_child().show_all() def _verify_clipboard(self, text): """Return an altered text or None if the content was invalid.""" return def run(self, text="", clipboard=False, test=False): """Shows the dialog and returns the entered value. If clipboard is set, the initial value will be pulled from the clipboard and can be verified/altered by _verify_clipboard. In case the verification fails text will be used as fallback""" self.show() if clipboard: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clip = clipboard.wait_for_text() if clip is not None: clip = self._verify_clipboard(clip) if clip is not None: text = clip self._val.set_text(text) self._val.set_activates_default(True) self._val.grab_focus() resp = Gtk.ResponseType.OK if not test: resp = super(GetStringDialog, self).run() if resp == Gtk.ResponseType.OK: value = self._val.get_text() else: value = None self.destroy() return value
def PluginPreferences(self, parent): def changed(entry, key): if entry.get_property('sensitive'): plugin_config.set(key, entry.get_text()) def combo_changed(widget, urlent): service = widget.get_active_text() plugin_config.set("service", service) urlent.set_sensitive((service not in SERVICES)) urlent.set_text(config_get_url()) def check_login(*args): queue = QLSubmitQueue() queue.changed() status = queue.send_handshake(show_dialog=True) if status: queue.quick_dialog(_("Authentication successful."), Gtk.MessageType.INFO) box = Gtk.VBox(spacing=12) # first frame table = Gtk.Table(n_rows=5, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) labels = [] label_names = [ _("_Service:"), _("_URL:"), _("User_name:"), _("_Password:"******"Other…") for idx, serv in enumerate(sorted(SERVICES.keys()) + [other_label]): service_combo.append_text(serv) if cur_service == serv: service_combo.set_active(idx) if service_combo.get_active() == -1: service_combo.set_active(0) labels[row].set_mnemonic_widget(service_combo) row += 1 # url entry = UndoEntry() entry.set_text(plugin_config.get('url')) entry.connect('changed', changed, 'url') service_combo.connect('changed', combo_changed, entry) service_combo.emit('changed') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # username entry = UndoEntry() entry.set_text(plugin_config.get('username')) entry.connect('changed', changed, 'username') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # password entry = UndoEntry() entry.set_text(plugin_config.get('password')) entry.set_visibility(False) entry.connect('changed', changed, 'password') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # verify data button = qltk.Button(_("_Verify account data"), Icons.DIALOG_INFORMATION) button.connect('clicked', check_login) table.attach(button, 0, 2, 4, 5) box.pack_start(qltk.Frame(_("Account"), child=table), True, True, 0) # second frame table = Gtk.Table(n_rows=4, n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) label_names = [ _("_Artist pattern:"), _("_Title pattern:"), _("Exclude _filter:") ] labels = [] for idx, name in enumerate(label_names): label = Gtk.Label(label=name) label.set_alignment(0.0, 0.5) label.set_use_underline(True) table.attach(label, 0, 1, idx, idx + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) labels.append(label) row = 0 # artist pattern entry = UndoEntry() entry.set_text(plugin_config.get('artistpat')) entry.connect('changed', changed, 'artistpat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text( _("The pattern used to format " "the artist name for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # title pattern entry = UndoEntry() entry.set_text(plugin_config.get('titlepat')) entry.connect('changed', changed, 'titlepat') table.attach(entry, 1, 2, row, row + 1) entry.set_tooltip_text( _("The pattern used to format " "the title for submission. Leave blank for default.")) labels[row].set_mnemonic_widget(entry) row += 1 # exclude filter entry = ValidatingEntry(Query.validator) entry.set_text(plugin_config.get('exclude')) entry.set_tooltip_text( _("Songs matching this filter will not be submitted.")) entry.connect('changed', changed, 'exclude') table.attach(entry, 1, 2, row, row + 1) labels[row].set_mnemonic_widget(entry) row += 1 # offline mode offline = plugin_config.ConfigCheckButton( _("_Offline mode (don't submit anything)"), 'offline', populate=True) table.attach(offline, 0, 2, row, row + 1) box.pack_start(qltk.Frame(_("Submission"), child=table), True, True, 0) return box
class TUndoEntry(TestCase): def setUp(self): self.entry = UndoEntry() def __equal(self, value): entry_val = self.entry.get_text().decode("utf-8") self.failUnlessEqual(value, entry_val) def __insert(self, text, pos): self.entry.insert_text(text, position=pos) self.entry.set_position(pos + len(text)) def __delete_left(self, start, end): self.entry.set_position(start) self.entry.delete_text(start, end) self.entry.set_position(start) def __delete_right(self, start, end): self.entry.set_position(end) self.entry.delete_text(start, end) self.entry.set_position(start) def test_undo_reset(self): entry = self.entry self.__insert("foo", 0) self.__insert("bar", 0) entry.reset_undo() entry.undo() entry.undo() entry.undo() self.__equal("barfoo") def test_undo_norm(self): entry = self.entry self.__insert("foo", 0) entry.undo() self.__equal("") entry.redo() self.__equal("foo") def test_undo_space(self): entry = self.entry self.__insert("f", 0) self.__insert(" ", 1) self.__insert("o", 2) entry.undo() self.__equal("f ") entry.undo() self.__equal("") def test_undo_insert_end(self): entry = self.entry self.__insert("f", 0) self.__insert("o", 1) self.__insert("o", 2) entry.undo() self.__equal("") entry.redo() self.__equal("foo") def test_undo_insert_end_2(self): entry = self.entry self.__insert("f", 0) self.__insert("o", 1) self.__insert("o", 2) self.__insert("bar", 3) entry.undo() self.__equal("foo") entry.redo() self.__equal("foobar") def test_undo_insert_middle(self): entry = self.entry self.__insert("foo", 0) self.__insert("b", 1) self.__equal("fboo") entry.undo() self.__equal("foo") entry.undo() self.__equal("") def test_undo_delete(self): entry = self.entry self.__insert("foobar", 0) self.__delete_left(3, 4) self.__equal("fooar") self.__delete_right(1, 3) self.__equal("far") entry.undo() self.__equal("fooar") entry.undo() self.__equal("foobar") def test_undo_delete_space(self): entry = self.entry self.__insert("foob ar", 0) self.__delete_right(6, 7) self.__equal("foob a") self.__delete_right(5, 6) self.__delete_right(4, 5) self.__delete_right(3, 4) self.__delete_right(2, 3) entry.undo() self.__equal("foob") def tearDown(self): self.entry.destroy()