def __init__(self, *args): QWidget.__init__(self, *args) lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(5) # type selector self.wtypesel = QComboBox(self) for i, tp in enumerate(self.ValueTypes): self.wtypesel.addItem(tp.__name__) QObject.connect(self.wtypesel, SIGNAL("activated(int)"), self._selectTypeNum) typesel_lab = QLabel("&Type:", self) typesel_lab.setBuddy(self.wtypesel) lo.addWidget(typesel_lab, 0) lo.addWidget(self.wtypesel, 0) self.wvalue = QLineEdit(self) self.wvalue_lab = QLabel("&Value:", self) self.wvalue_lab.setBuddy(self.wvalue) self.wbool = QComboBox(self) self.wbool.addItems(["false", "true"]) self.wbool.setCurrentIndex(1) lo.addWidget(self.wvalue_lab, 0) lo.addWidget(self.wvalue, 1) lo.addWidget(self.wbool, 1) self.wvalue.hide() # make input validators self._validators = {int: QIntValidator(self), float: QDoubleValidator(self)} # select bool type initially self._selectTypeNum(0)
def create_widgets(self, opt): val = self.plugin.prefs[opt.name] if opt.type == 'number': c = QSpinBox if isinstance(opt.default, int) else QDoubleSpinBox widget = c(self) widget.setValue(val) elif opt.type == 'string': widget = QLineEdit(self) widget.setText(val if val else '') elif opt.type == 'bool': widget = QCheckBox(opt.label, self) widget.setChecked(bool(val)) elif opt.type == 'choices': widget = QComboBox(self) for key, label in opt.choices.iteritems(): widget.addItem(label, QVariant(key)) idx = widget.findData(QVariant(val)) widget.setCurrentIndex(idx) widget.opt = opt widget.setToolTip(textwrap.fill(opt.desc)) self.widgets.append(widget) r = self.l.rowCount() if opt.type == 'bool': self.l.addWidget(widget, r, 0, 1, self.l.columnCount()) else: l = QLabel(opt.label) l.setToolTip(widget.toolTip()) self.memory.append(l) l.setBuddy(widget) self.l.addWidget(l, r, 0, 1, 1) self.l.addWidget(widget, r, 1, 1, 1)
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.oldest_articlel = QLabel('Oldest article:') self.l.addWidget(self.oldest_articlel) self.oldest_article_msg = QLineEdit(self) self.oldest_article_msg.setText(prefs['oldest_article']) self.l.addWidget(self.oldest_article_msg) self.oldest_articlel.setBuddy(self.oldest_article_msg) self.max_articlesl = QLabel('Max articles:') self.l.addWidget(self.max_articlesl) self.max_articles_msg = QLineEdit(self) self.max_articles_msg.setText(prefs['max_articles']) self.l.addWidget(self.max_articles_msg) self.max_articlesl.setBuddy(self.max_articles_msg) def save_settings(self): prefs['oldest_article'] = unicode(self.oldest_article_msg.text()) prefs['max_articles'] = unicode(self.max_articles_msg.text())
class ConfigWidget(QWidget): 'Configuration widget' def __init__(self): QWidget.__init__(self) self.layout = QHBoxLayout() self.setLayout(self.layout) self.key_label = QLabel('&api key:') self.layout.addWidget(self.key_label) self.key_msg = QLineEdit(self) self.key_msg.setText(PREFS['api_key']) self.layout.addWidget(self.key_msg) self.key_label.setBuddy(self.key_msg) self.threads_label = QLabel('&worker_threads:') self.layout.addWidget(self.threads_label) self.threads_msg = QLineEdit(self) self.threads_msg.setText(str(PREFS['worker_threads'])) self.layout.addWidget(self.threads_msg) self.key_label.setBuddy(self.key_msg) def save_settings(self): 'Apply new settings value' PREFS['api_key'] = unicode(self.key_msg.text()) PREFS['worker_threads'] = int(self.threads_msg.text()) pycomicvine.api_key = PREFS['api_key']
def setup_ui(self): self.l = l = QGridLayout() self.setLayout(l) self.la = la = QLabel(_( 'Arrange the files in this book into sub-folders based on their types.' ' If you leave a folder blank, the files will be placed in the root.')) la.setWordWrap(True) l.addWidget(la, 0, 0, 1, -1) folders = tprefs['folders_for_types'] for i, (typ, text) in enumerate(self.TYPE_MAP): la = QLabel('&' + text) setattr(self, '%s_label' % typ, la) le = QLineEdit(self) setattr(self, '%s_folder' % typ, le) val = folders.get(typ, '') if val and not val.endswith('/'): val += '/' le.setText(val) la.setBuddy(le) l.addWidget(la, i + 1, 0) l.addWidget(le, i + 1, 1) self.la2 = la = QLabel(_( 'Note that this will only arrange files inside the book,' ' it will not affect how they are displayed in the Files Browser')) la.setWordWrap(True) l.addWidget(la, i + 2, 0, 1, -1) l.addWidget(self.bb, i + 3, 0, 1, -1)
class AddBookDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None, mi = None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:add book dialog') self.setWindowTitle('Add text to Casanova:') self.gui = parent self.mm = mm self.mi = mi self.one_line_description = '' layout = QVBoxLayout(self) self.setLayout(layout) self.one_liner_label = QLabel('Enter a short description (255 chars max) before pressing OK') layout.addWidget(self.one_liner_label) self.one_liner_str = QLineEdit(self) self.one_liner_str.setText('') layout.addWidget(self.one_liner_str) self.one_liner_label.setBuddy(self.one_liner_str) self.values_label = QLabel('Below are potential matches of texts that already exist - please make sure you are adding something new') layout.addWidget(self.values_label) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_choices() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self): self.values_list.clear() choices = self.mm.search(self.mi.title) if choices is None or len(choices)==0: item = QListWidgetItem(get_icon('images/books.png'), _('there seem to be no matches'), self.values_list) self.values_list.addItem(item) for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id,)) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() one_liner = unicode(self.one_liner_str.text()) if one_liner=='': self.values_list.clear() item = QListWidgetItem(get_icon('images/books.png'), _('you need to enter a short description'), self.values_list) self.values_list.addItem(item) else: self.one_line_description = one_liner self.accept()
class SearchDialog(SizePersistedDialog): def __init__(self, parent=None, func=None, title="Search"): SizePersistedDialog.__init__(self, parent, 'arg plugin:search dialog') self.setWindowTitle(title) self.gui = parent self.func = func layout = QVBoxLayout(self) self.setLayout(layout) self.search_label = QLabel(title) layout.addWidget(self.search_label) self.search_str = QLineEdit(self) self.search_str.setText('') layout.addWidget(self.search_str) self.search_label.setBuddy(self.search_str) self.find_button = QPushButton("&Find") self.search_button_box = QDialogButtonBox(Qt.Horizontal) self.search_button_box.addButton(self.find_button, QDialogButtonBox.ActionRole) self.search_button_box.clicked.connect(self._find_clicked) layout.addWidget(self.search_button_box) self.values_list = QListWidget(self) # for multiple selection #self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self, choices): self.values_list.clear() for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id,)) self.values_list.addItem(item) def _find_clicked(self): query = unicode(self.search_str.text()) self._display_choices(self.func(query)) def _accept_clicked(self): #self._save_preferences() self.selected_result = None if self.values_list.currentItem(): i = self.values_list.currentItem() self.selected_result = (i.data(1)[0], i.text()) self.accept()
class DaysOfMonth(Base): HELP = _('''\ Download this periodical every month, on the specified days. The download will happen as soon after the specified time as possible on the specified days of each month. For example, if you choose the 1st and the 15th after 9:00 AM, the periodical will be downloaded on the 1st and 15th of every month, as soon after 9:00 AM as possible. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.l1 = QLabel(_('&Days of the month:')) self.days = QLineEdit(self) self.days.setToolTip( _('Comma separated list of days of the month.' ' For example: 1, 15')) self.l1.setBuddy(self.days) self.l2 = QLabel(_('Download &after:')) self.time = QTimeEdit(self) self.time.setDisplayFormat('hh:mm AP') self.l2.setBuddy(self.time) self.l.addWidget(self.l1, 0, 0, 1, 1) self.l.addWidget(self.days, 0, 1, 1, 1) self.l.addWidget(self.l2, 1, 0, 1, 1) self.l.addWidget(self.time, 1, 1, 1, 1) def initialize(self, typ=None, val=None): if val is None: val = ((1, ), 6, 0) days_of_month, hour, minute = val self.days.setText(', '.join(map(str, map(int, days_of_month)))) self.time.setTime(QTime(hour, minute)) @property def schedule(self): parts = [ x.strip() for x in unicode(self.days.text()).split(',') if x.strip() ] try: days_of_month = tuple(map(int, parts)) except: days_of_month = (1, ) if not days_of_month: days_of_month = (1, ) t = self.time.time() hour, minute = t.hour(), t.minute() return 'days_of_month', (days_of_month, int(hour), int(minute))
class DaysOfWeek(Base): HELP = _('''\ Download this periodical every week on the specified days after the specified time. For example, if you choose: Monday after 9:00 AM, then the periodical will be download every Monday as soon after 9:00 AM as possible. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.days = [ QCheckBox(force_unicode(calendar.day_abbr[d]), self) for d in xrange(7) ] for i, cb in enumerate(self.days): row = i % 2 col = i // 2 self.l.addWidget(cb, row, col, 1, 1) self.time = QTimeEdit(self) self.time.setDisplayFormat('hh:mm AP') if canonicalize_lang(get_lang()) in {'deu', 'nds'}: self.time.setDisplayFormat('HH:mm') self.hl = QHBoxLayout() self.l1 = QLabel(_('&Download after:')) self.l1.setBuddy(self.time) self.hl.addWidget(self.l1) self.hl.addWidget(self.time) self.l.addLayout(self.hl, 1, 3, 1, 1) self.initialize() def initialize(self, typ=None, val=None): if typ is None: typ = 'day/time' val = (-1, 6, 0) if typ == 'day/time': val = convert_day_time_schedule(val) days_of_week, hour, minute = val for i, d in enumerate(self.days): d.setChecked(i in days_of_week) self.time.setTime(QTime(hour, minute)) @property def schedule(self): days_of_week = tuple( [i for i, d in enumerate(self.days) if d.isChecked()]) t = self.time.time() hour, minute = t.hour(), t.minute() return 'days_of_week', (days_of_week, int(hour), int(minute))
class DaysOfMonth(Base): HELP = _('''\ Download this periodical every month, on the specified days. The download will happen as soon after the specified time as possible on the specified days of each month. For example, if you choose the 1st and the 15th after 9:00 AM, the periodical will be downloaded on the 1st and 15th of every month, as soon after 9:00 AM as possible. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.l1 = QLabel(_('&Days of the month:')) self.days = QLineEdit(self) self.days.setToolTip(_('Comma separated list of days of the month.' ' For example: 1, 15')) self.l1.setBuddy(self.days) self.l2 = QLabel(_('Download &after:')) self.time = QTimeEdit(self) self.time.setDisplayFormat('hh:mm AP') self.l2.setBuddy(self.time) self.l.addWidget(self.l1, 0, 0, 1, 1) self.l.addWidget(self.days, 0, 1, 1, 1) self.l.addWidget(self.l2, 1, 0, 1, 1) self.l.addWidget(self.time, 1, 1, 1, 1) def initialize(self, typ=None, val=None): if val is None: val = ((1,), 6, 0) days_of_month, hour, minute = val self.days.setText(', '.join(map(str, map(int, days_of_month)))) self.time.setTime(QTime(hour, minute)) @property def schedule(self): parts = [x.strip() for x in unicode(self.days.text()).split(',') if x.strip()] try: days_of_month = tuple(map(int, parts)) except: days_of_month = (1,) if not days_of_month: days_of_month = (1,) t = self.time.time() hour, minute = t.hour(), t.minute() return 'days_of_month', (days_of_month, int(hour), int(minute))
class DaysOfWeek(Base): HELP = _('''\ Download this periodical every week on the specified days after the specified time. For example, if you choose: Monday after 9:00 AM, then the periodical will be download every Monday as soon after 9:00 AM as possible. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.days = [QCheckBox(force_unicode(calendar.day_abbr[d]), self) for d in xrange(7)] for i, cb in enumerate(self.days): row = i % 2 col = i // 2 self.l.addWidget(cb, row, col, 1, 1) self.time = QTimeEdit(self) self.time.setDisplayFormat('hh:mm AP') if canonicalize_lang(get_lang()) in {'deu', 'nds'}: self.time.setDisplayFormat('HH:mm') self.hl = QHBoxLayout() self.l1 = QLabel(_('&Download after:')) self.l1.setBuddy(self.time) self.hl.addWidget(self.l1) self.hl.addWidget(self.time) self.l.addLayout(self.hl, 1, 3, 1, 1) self.initialize() def initialize(self, typ=None, val=None): if typ is None: typ = 'day/time' val = (-1, 6, 0) if typ == 'day/time': val = convert_day_time_schedule(val) days_of_week, hour, minute = val for i, d in enumerate(self.days): d.setChecked(i in days_of_week) self.time.setTime(QTime(hour, minute)) @property def schedule(self): days_of_week = tuple([i for i, d in enumerate(self.days) if d.isChecked()]) t = self.time.time() hour, minute = t.hour(), t.minute() return 'days_of_week', (days_of_week, int(hour), int(minute))
def __init__(self, service, parent): QDialog.__init__(self, parent) self.l = l = QGridLayout() self.setLayout(l) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.tl = QLabel(('<p>' + _( 'Setup sending email using' ) + ' <b>{name}</b><p>' + _( 'If you don\'t have an account, you can sign up for a free {name} email ' 'account at <a href="http://{url}">http://{url}</a>. {extra}') ).format(**service)) l.addWidget(self.tl, 0, 0, 3, 0) self.tl.setWordWrap(True) self.tl.setOpenExternalLinks(True) for name, label in ( ['from_', _('Your %s &email address:')], ['username', _('Your %s &username:'******'password', _('Your %s &password:'******'name']) le = QLineEdit(self) setattr(self, name, le) setattr(self, name + '_label', la) r = l.rowCount() l.addWidget(la, r, 0) l.addWidget(le, r, 1) la.setBuddy(le) if name == 'password': self.ptoggle = QCheckBox(_('&Show password'), self) l.addWidget(self.ptoggle, r, 2) self.ptoggle.stateChanged.connect( lambda s: self.password.setEchoMode( self.password.Normal if s == Qt.Checked else self.password.Password)) self.username.setText(service['username']) self.password.setEchoMode(self.password.Password) self.bl = QLabel('<p>' + _( 'If you plan to use email to send books to your Kindle, remember to' ' add the your %s email address to the allowed email addresses in your ' 'Amazon.com Kindle management page.') % service['name']) self.bl.setWordWrap(True) l.addWidget(self.bl, l.rowCount(), 0, 3, 0) l.addWidget(bb, l.rowCount(), 0, 3, 0) self.setWindowTitle(_('Setup') + ' ' + service['name']) self.resize(self.sizeHint()) self.service = service
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.l5 = QHBoxLayout() self.server_prefix_label = QLabel('Server prefix:') self.l5.addWidget(self.server_prefix_label) self.server_prefix = QLineEdit(self) self.server_prefix.setText(prefs['server_prefix']) self.l5.addWidget(self.server_prefix) self.server_prefix_label.setBuddy(self.server_prefix) self.l.addLayout(self.l5) self.ll = QHBoxLayout() self.server_label = QLabel('Server:') self.ll.addWidget(self.server_label) self.lsb_server = QLineEdit(self) self.lsb_server.setText(prefs['lsb_server']) self.ll.addWidget(self.lsb_server) self.server_label.setBuddy(self.lsb_server) self.l.addLayout(self.ll) self.lll = QHBoxLayout() self.librarian_label = QLabel('Librarian:') self.lll.addWidget(self.librarian_label) self.librarian = QLineEdit(self) self.librarian.setText(prefs['librarian']['name']) self.lll.addWidget(self.librarian) self.librarian_label.setBuddy(self.librarian) self.l.addLayout(self.lll) self.llll = QHBoxLayout() self.library_uuid_label = QLabel('Library ID:') self.llll.addWidget(self.library_uuid_label) self.library_uuid_button = QPushButton("New unique Library ID") self.library_uuid_button.clicked.connect(self.new_library_uuid) self.library_uuid = QLabel(self) self.library_uuid.setText(prefs['library_uuid']) self.llll.addWidget(self.library_uuid) self.llll.addWidget(self.library_uuid_button) self.library_uuid_label.setBuddy(self.library_uuid) self.l.addLayout(self.llll) def new_library_uuid(self): self.library_uuid.setText(str(uuid.uuid4())) def save_settings(self): prefs['lsb_server'] = unicode(self.lsb_server.text()) prefs['server_prefix'] = unicode(self.server_prefix.text()) prefs['librarian'] = {'name': unicode(self.librarian.text()), 'saved': True} prefs['library_uuid'] = self.library_uuid.text()
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.label = QLabel("Server:") self.l.addWidget(self.label) self.msg = QLineEdit(self) self.msg.setText(prefs["lsb_server"]) self.l.addWidget(self.msg) self.label.setBuddy(self.msg) def save_settings(self): prefs["lsb_server"] = unicode(self.msg.text())
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.label = QLabel('Hello world &message:') self.l.addWidget(self.label) self.msg = QLineEdit(self) self.msg.setText(prefs['hello_world_msg']) self.l.addWidget(self.msg) self.label.setBuddy(self.msg) def save_settings(self): prefs['hello_world_msg'] = unicode(self.msg.text())
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.label = QLabel("Hello world &message:") self.l.addWidget(self.label) self.msg = QLineEdit(self) self.msg.setText(prefs["hello_world_msg"]) self.l.addWidget(self.msg) self.label.setBuddy(self.msg) def save_settings(self): None
def __init__(self, service, parent): QDialog.__init__(self, parent) self.l = l = QGridLayout() self.setLayout(l) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.tl = QLabel(('<p>'+_('Setup sending email using') + ' <b>{name}</b><p>' + _('If you don\'t have an account, you can sign up for a free {name} email ' 'account at <a href="http://{url}">http://{url}</a>. {extra}')).format( **service)) l.addWidget(self.tl, 0, 0, 3, 0) self.tl.setWordWrap(True) self.tl.setOpenExternalLinks(True) for name, label in ( ['from_', _('Your %s &email address:')], ['username', _('Your %s &username:'******'password', _('Your %s &password:'******'name']) le = QLineEdit(self) setattr(self, name, le) setattr(self, name+'_label', la) r = l.rowCount() l.addWidget(la, r, 0) l.addWidget(le, r, 1) la.setBuddy(le) if name == 'password': self.ptoggle = QCheckBox(_('&Show password'), self) l.addWidget(self.ptoggle, r, 2) self.ptoggle.stateChanged.connect( lambda s: self.password.setEchoMode(self.password.Normal if s == Qt.Checked else self.password.Password)) self.username.setText(service['username']) self.password.setEchoMode(self.password.Password) self.bl = QLabel('<p>' + _( 'If you plan to use email to send books to your Kindle, remember to' ' add the your %s email address to the allowed email addresses in your ' 'Amazon.com Kindle management page.')%service['name']) self.bl.setWordWrap(True) l.addWidget(self.bl, l.rowCount(), 0, 3, 0) l.addWidget(bb, l.rowCount(), 0, 3, 0) self.setWindowTitle(_('Setup') + ' ' + service['name']) self.resize(self.sizeHint()) self.service = service
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.label = QLabel('Message header:') self.l.addWidget(self.label) self.msg = QLineEdit(self) self.msg.setText(prefs['my_msg_header']) self.l.addWidget(self.msg) self.label.setBuddy(self.msg) def save_settings(self): prefs['my_msg_header'] = unicode(self.msg.text())
def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off + which, 0, 1, 3) setattr(self, 'label%d' % which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.keyPressEvent = partial(self.key_press_event, which=which) setattr(self, 'button%d' % which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d' % which, clear) l.addWidget(button, off + which, 1, 1, 1) l.addWidget(clear, off + which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda: self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False)
def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFocusPolicy(Qt.StrongFocus) self.setAutoFillBackground(True) self.capture = 0 self.setFrameShape(self.StyledPanel) self.setFrameShadow(self.Raised) self._layout = l = QGridLayout(self) self.setLayout(l) self.header = QLabel('') l.addWidget(self.header, 0, 0, 1, 2) self.use_default = QRadioButton('') self.use_custom = QRadioButton(_('Custom')) l.addWidget(self.use_default, 1, 0, 1, 3) l.addWidget(self.use_custom, 2, 0, 1, 3) self.use_custom.toggled.connect(self.custom_toggled) off = 2 for which in (1, 2): text = _('&Shortcut:') if which == 1 else _('&Alternate shortcut:') la = QLabel(text) la.setStyleSheet('QLabel { margin-left: 1.5em }') l.addWidget(la, off+which, 0, 1, 3) setattr(self, 'label%d'%which, la) button = QPushButton(_('None'), self) button.clicked.connect(partial(self.capture_clicked, which=which)) button.keyPressEvent = partial(self.key_press_event, which=which) setattr(self, 'button%d'%which, button) clear = QToolButton(self) clear.setIcon(QIcon(I('clear_left.png'))) clear.clicked.connect(partial(self.clear_clicked, which=which)) setattr(self, 'clear%d'%which, clear) l.addWidget(button, off+which, 1, 1, 1) l.addWidget(clear, off+which, 2, 1, 1) la.setBuddy(button) self.done_button = doneb = QPushButton(_('Done'), self) l.addWidget(doneb, 0, 2, 1, 1) doneb.clicked.connect(lambda : self.editing_done.emit(self)) l.setColumnStretch(0, 100) self.custom_toggled(False)
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.ll = QHBoxLayout() self.server_label = QLabel('Gphoto2 server address:') self.ll.addWidget(self.server_label) self.gphoto2_server = QLineEdit(self) self.gphoto2_server.setText(prefs['gphoto2_server']) self.ll.addWidget(self.gphoto2_server) self.server_label.setBuddy(self.gphoto2_server) self.l.addLayout(self.ll) def save_settings(self): prefs['gphoto2_server'] = self.gphoto2_server.text()
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.ll = QHBoxLayout() self.server_label = QLabel('Gphoto2 server address:') self.ll.addWidget(self.server_label) self.gphoto2_server = QLineEdit(self) self.gphoto2_server.setText(prefs['gphoto2_server']) self.ll.addWidget(self.gphoto2_server) self.server_label.setBuddy(self.gphoto2_server) self.l.addLayout(self.ll) def save_settings(self): prefs['gphoto2_server'] = self.gphoto2_server.text()
def __init__(self, plugin): super(ConfigWidget, self).__init__() self.vlayout = QVBoxLayout() self.setLayout(self.vlayout) self.dcinput = {} for key in prefs.defaults: hlayout = QHBoxLayout() txtlabel = QLabel(key.replace("_", " ")) txtinput = QLineEdit() txtinput.setText(str(prefs[key])) txtlabel.setBuddy(txtinput) self.dcinput[key] = txtinput hlayout.addWidget(txtlabel) hlayout.addWidget(txtinput) self.vlayout.addLayout(hlayout)
def __init__(self, parent, modal=True, flags=Qt.WindowFlags()): QDialog.__init__(self, parent, flags) self.setModal(modal) self.setWindowTitle("Add Tag") lo = QVBoxLayout(self) lo.setMargin(10) lo.setSpacing(5) # tag selector lo1 = QHBoxLayout() lo.addLayout(lo1) lo1.setSpacing(5) self.wtagsel = QComboBox(self) self.wtagsel.setEditable(True) wtagsel_lbl = QLabel("&Tag:", self) wtagsel_lbl.setBuddy(self.wtagsel) lo1.addWidget(wtagsel_lbl, 0) lo1.addWidget(self.wtagsel, 1) QObject.connect(self.wtagsel, SIGNAL("activated(int)"), self._check_tag) QObject.connect(self.wtagsel, SIGNAL("editTextChanged(const QString &)"), self._check_tag_text) # value editor self.valedit = ValueTypeEditor(self) lo.addWidget(self.valedit) # buttons lo.addSpacing(10) lo2 = QHBoxLayout() lo.addLayout(lo2) lo2.setContentsMargins(0, 0, 0, 0) lo2.setMargin(5) self.wokbtn = QPushButton("OK", self) self.wokbtn.setMinimumWidth(128) QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept) self.wokbtn.setEnabled(False) cancelbtn = QPushButton("Cancel", self) cancelbtn.setMinimumWidth(128) QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject) lo2.addWidget(self.wokbtn) lo2.addStretch(1) lo2.addWidget(cancelbtn) self.setMinimumWidth(384)
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.l5 = QHBoxLayout() self.server_prefix_label = QLabel('Server prefix:') self.l5.addWidget(self.server_prefix_label) self.server_prefix = QLineEdit(self) self.server_prefix.setText(prefs['server_prefix']) self.l5.addWidget(self.server_prefix) self.server_prefix_label.setBuddy(self.server_prefix) self.l.addLayout(self.l5) self.ll = QHBoxLayout() self.server_label = QLabel('Server:') self.ll.addWidget(self.server_label) self.lsb_server = QLineEdit(self) self.lsb_server.setText(prefs['lsb_server']) self.ll.addWidget(self.lsb_server) self.server_label.setBuddy(self.lsb_server) self.l.addLayout(self.ll) self.lll = QHBoxLayout() self.librarian_label = QLabel('Librarian:') self.lll.addWidget(self.librarian_label) self.librarian = QLineEdit(self) self.librarian.setText(prefs['librarian']) self.lll.addWidget(self.librarian) self.librarian_label.setBuddy(self.librarian) self.l.addLayout(self.lll) self.llll = QHBoxLayout() self.library_uuid_label = QLabel('Library ID:') self.llll.addWidget(self.library_uuid_label) self.library_uuid = QLabel(self) self.library_uuid.setText(prefs['library_uuid']) self.llll.addWidget(self.library_uuid) self.library_uuid_label.setBuddy(self.library_uuid) self.l.addLayout(self.llll) def save_settings(self): prefs['lsb_server'] = unicode(self.lsb_server.text()) prefs['server_prefix'] = unicode(self.server_prefix.text()) prefs['librarian'] = unicode(self.librarian.text()) prefs['library_uuid'] = prefs['library_uuid']
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.l5 = QHBoxLayout() self.server_prefix_label = QLabel('Server prefix:') self.l5.addWidget(self.server_prefix_label) self.server_prefix = QLineEdit(self) self.server_prefix.setText(prefs['server_prefix']) self.l5.addWidget(self.server_prefix) self.server_prefix_label.setBuddy(self.server_prefix) self.l.addLayout(self.l5) self.ll = QHBoxLayout() self.server_label = QLabel('Server:') self.ll.addWidget(self.server_label) self.lsb_server = QLineEdit(self) self.lsb_server.setText(prefs['lsb_server']) self.ll.addWidget(self.lsb_server) self.server_label.setBuddy(self.lsb_server) self.l.addLayout(self.ll) self.lll = QHBoxLayout() self.librarian_label = QLabel('Librarian:') self.lll.addWidget(self.librarian_label) self.librarian = QLabel(self) self.librarian.setText(prefs['librarian']) self.lll.addWidget(self.librarian) self.librarian_label.setBuddy(self.librarian) self.l.addLayout(self.lll) self.llll = QHBoxLayout() self.library_uuid_label = QLabel('Library ID:') self.llll.addWidget(self.library_uuid_label) self.library_uuid = QLabel(self) self.library_uuid.setText(prefs['library_uuid']) self.llll.addWidget(self.library_uuid) self.library_uuid_label.setBuddy(self.library_uuid) self.l.addLayout(self.llll) def save_settings(self): prefs['lsb_server'] = unicode(self.lsb_server.text()) prefs['server_prefix'] = unicode(self.server_prefix.text()) prefs['librarian'] = prefs['librarian'] prefs['library_uuid'] = prefs['library_uuid']
def __init__(self, parent, modal=True, flags=Qt.WindowFlags()): QDialog.__init__(self, parent, flags) self.setModal(modal) self.setWindowTitle("Add Tag") lo = QVBoxLayout(self) lo.setMargin(10) lo.setSpacing(5) # tag selector lo1 = QHBoxLayout() lo.addLayout(lo1) lo1.setSpacing(5) self.wtagsel = QComboBox(self) self.wtagsel.setEditable(True) wtagsel_lbl = QLabel("&Tag:", self) wtagsel_lbl.setBuddy(self.wtagsel) lo1.addWidget(wtagsel_lbl, 0) lo1.addWidget(self.wtagsel, 1) QObject.connect(self.wtagsel, SIGNAL("activated(int)"), self._check_tag) QObject.connect(self.wtagsel, SIGNAL("editTextChanged(const QString &)"), self._check_tag_text) # value editor self.valedit = ValueTypeEditor(self) lo.addWidget(self.valedit) # buttons lo.addSpacing(10) lo2 = QHBoxLayout() lo.addLayout(lo2) lo2.setContentsMargins(0, 0, 0, 0) lo2.setMargin(5) self.wokbtn = QPushButton("OK", self) self.wokbtn.setMinimumWidth(128) QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept) self.wokbtn.setEnabled(False) cancelbtn = QPushButton("Cancel", self) cancelbtn.setMinimumWidth(128) QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject) lo2.addWidget(self.wokbtn) lo2.addStretch(1) lo2.addWidget(cancelbtn) self.setMinimumWidth(384)
class EveryXDays(Base): HELP = _('''\ Download this periodical every x days. For example, if you choose 30 days, the periodical will be downloaded every 30 days. Note that you can set periods of less than a day, like 0.1 days to download a periodical more than once a day. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.l1 = QLabel(_('&Download every:')) self.interval = QDoubleSpinBox(self) self.interval.setMinimum(0.04) self.interval.setSpecialValueText(_('every hour')) self.interval.setMaximum(1000.0) self.interval.setValue(31.0) self.interval.setSuffix(' ' + _('days')) self.interval.setSingleStep(1.0) self.interval.setDecimals(2) self.l1.setBuddy(self.interval) self.l2 = QLabel( _('Note: You can set intervals of less than a day,' ' by typing the value manually.')) self.l2.setWordWrap(True) self.l.addWidget(self.l1, 0, 0, 1, 1) self.l.addWidget(self.interval, 0, 1, 1, 1) self.l.addWidget(self.l2, 1, 0, 1, -1) def initialize(self, typ=None, val=None): if val is None: val = 31.0 self.interval.setValue(val) @property def schedule(self): schedule = self.interval.value() return 'interval', schedule
class EveryXDays(Base): HELP = _('''\ Download this periodical every x days. For example, if you choose 30 days, the periodical will be downloaded every 30 days. Note that you can set periods of less than a day, like 0.1 days to download a periodical more than once a day. ''') def __init__(self, parent=None): Base.__init__(self, parent) self.l1 = QLabel(_('&Download every:')) self.interval = QDoubleSpinBox(self) self.interval.setMinimum(0.04) self.interval.setSpecialValueText(_('every hour')) self.interval.setMaximum(1000.0) self.interval.setValue(31.0) self.interval.setSuffix(' ' + _('days')) self.interval.setSingleStep(1.0) self.interval.setDecimals(2) self.l1.setBuddy(self.interval) self.l2 = QLabel(_('Note: You can set intervals of less than a day,' ' by typing the value manually.')) self.l2.setWordWrap(True) self.l.addWidget(self.l1, 0, 0, 1, 1) self.l.addWidget(self.interval, 0, 1, 1, 1) self.l.addWidget(self.l2, 1, 0, 1, -1) def initialize(self, typ=None, val=None): if val is None: val = 31.0 self.interval.setValue(val) @property def schedule(self): schedule = self.interval.value() return 'interval', schedule
def __init__(self, parent=None): super(IPETLogFileView, self).__init__(parent) vlayout = QVBoxLayout(self) self.textbrowser = QTextEdit(self) self.textbrowser.setReadOnly(True) self.testrunselection = OptionsComboBox(self) self.problemselection = OptionsComboBox(self) vlayout.addWidget(self.textbrowser) self.setStyleSheet(self.StyleSheet) hlayout = QHBoxLayout() testrunselectionlabel = QLabel("Select a test run", self) problemselectionlabel = QLabel("Select an instance", self) testrunselectionlabel.setBuddy(self.testrunselection) problemselectionlabel.setBuddy(self.problemselection) for l, s in [(testrunselectionlabel, self.testrunselection), (problemselectionlabel, self.problemselection)]: v = QVBoxLayout(self) v.addWidget(l) v.addWidget(s) hlayout.addLayout(v) vlayout.addLayout(hlayout) self.setLayout(vlayout) self.initConnections()
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.serialLabel = QLabel('eInk Kindle Serial numbers (First character B, 16 characters, use commas if more than one)') self.l.addWidget(self.serialLabel) self.serials = QLineEdit(self) self.serials.setText(prefs['serials']) self.l.addWidget(self.serials) self.serialLabel.setBuddy(self.serials) self.pidLabel = QLabel('Mobipocket PIDs (8 or 10 characters, use commas if more than one)') self.l.addWidget(self.pidLabel) self.pids = QLineEdit(self) self.pids.setText(prefs['pids']) self.l.addWidget(self.pids) self.pidLabel.setBuddy(self.serials) self.wpLabel = QLabel('For Linux only: WINEPREFIX (enter absolute path)') self.l.addWidget(self.wpLabel) self.wineprefix = QLineEdit(self) wineprefix = prefs['WINEPREFIX'] if wineprefix is not None: self.wineprefix.setText(wineprefix) else: self.wineprefix.setText('') self.l.addWidget(self.wineprefix) self.wpLabel.setBuddy(self.wineprefix) def save_settings(self): prefs['pids'] = str(self.pids.text()).replace(" ","") prefs['serials'] = str(self.serials.text()).replace(" ","") winepref=str(self.wineprefix.text()) if winepref.strip() != '': prefs['WINEPREFIX'] = winepref else: prefs['WINEPREFIX'] = None
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.ll = QHBoxLayout() self.server_label = QLabel("Server:") self.ll.addWidget(self.server_label) self.lsb_server = QLineEdit(self) self.lsb_server.setText(prefs["lsb_server"]) self.ll.addWidget(self.lsb_server) self.server_label.setBuddy(self.lsb_server) self.l.addLayout(self.ll) self.lll = QHBoxLayout() self.librarian_label = QLabel("Librarian:") self.lll.addWidget(self.librarian_label) self.librarian = QLineEdit(self) self.librarian.setText(prefs["librarian"]) self.lll.addWidget(self.librarian) self.librarian_label.setBuddy(self.librarian) self.l.addLayout(self.lll) self.llll = QHBoxLayout() self.library_uuid_label = QLabel("Library ID:") self.llll.addWidget(self.library_uuid_label) self.library_uuid = QLabel(self) self.library_uuid.setText(prefs["library_uuid"]) self.llll.addWidget(self.library_uuid) self.library_uuid_label.setBuddy(self.library_uuid) self.l.addLayout(self.llll) def save_settings(self): prefs["lsb_server"] = unicode(self.lsb_server.text()) prefs["librarian"] = unicode(self.librarian.text()) prefs["library_uuid"] = prefs["library_uuid"]
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.url_label = QLabel('Casanova server:') self.l.addWidget(self.url_label) self.url_msg = QLineEdit(self) self.url_msg.setText(prefs['base_url']) self.l.addWidget(self.url_msg) self.url_label.setBuddy(self.url_msg) self.username_label = QLabel('Username:'******'username']) self.l.addWidget(self.username_msg) self.username_label.setBuddy(self.username_msg) self.password_label = QLabel('password:'******'password']) self.l.addWidget(self.password_msg) self.password_label.setBuddy(self.password_msg) def save_settings(self): prefs['base_url'] = unicode(self.url_msg.text()) prefs['username'] = unicode(self.username_msg.text()) prefs['password'] = unicode(self.password_msg.text())
def __init__(self, plugin_action): QWidget.__init__(self) self.plugin_action = plugin_action layout = QVBoxLayout(self) self.setLayout(layout) c = plugin_prefs[STORE_NAME] avail_columns = self.get_custom_columns() library_config = get_library_config(self.plugin_action.gui.current_db) pages_algorithm = library_config.get(KEY_PAGES_ALGORITHM, DEFAULT_LIBRARY_VALUES[KEY_PAGES_ALGORITHM]) button_default = c.get(KEY_BUTTON_DEFAULT, DEFAULT_STORE_VALUES[KEY_BUTTON_DEFAULT]) # Fudge the button default to cater for the options no longer supported by plugin as of 1.5 if button_default in ['Estimate', 'EstimatePage', 'EstimateWord']: button_default = 'Estimate' else: button_default = 'Goodreads' overwrite_existing = c.get(KEY_OVERWRITE_EXISTING, DEFAULT_STORE_VALUES[KEY_OVERWRITE_EXISTING]) # --- Pages --- page_group_box = QGroupBox('Page count options:', self) layout.addWidget(page_group_box) page_group_box_layout = QGridLayout() page_group_box.setLayout(page_group_box_layout) page_column_label = QLabel('&Custom column:', self) page_column_label.setToolTip('Leave this blank if you do not want to count pages') page_col = library_config.get(KEY_PAGES_CUSTOM_COLUMN, '') self.page_column_combo = CustomColumnComboBox(self, avail_columns, page_col) page_column_label.setBuddy(self.page_column_combo) page_group_box_layout.addWidget(page_column_label, 0, 0, 1, 1) page_group_box_layout.addWidget(self.page_column_combo, 0, 1, 1, 2) page_algorithm_label = QLabel('&Algorithm:', self) page_algorithm_label.setToolTip('Choose which algorithm to use if you have specified a page count column') self.page_algorithm_combo = AlgorithmComboBox(self, PAGE_ALGORITHMS, pages_algorithm) page_algorithm_label.setBuddy(self.page_algorithm_combo) page_group_box_layout.addWidget(page_algorithm_label, 1, 0, 1, 1) page_group_box_layout.addWidget(self.page_algorithm_combo, 1, 1, 1, 2) # --- Words --- layout.addSpacing(5) word_group_box = QGroupBox('Word count options:', self) layout.addWidget(word_group_box) word_group_box_layout = QGridLayout() word_group_box.setLayout(word_group_box_layout) word_column_label = QLabel('C&ustom column:', self) word_column_label.setToolTip('Leave this blank if you do not want to count words') word_col = library_config.get(KEY_WORDS_CUSTOM_COLUMN, '') self.word_column_combo = CustomColumnComboBox(self, avail_columns, word_col) word_column_label.setBuddy(self.word_column_combo) word_group_box_layout.addWidget(word_column_label, 0, 0, 1, 1) word_group_box_layout.addWidget(self.word_column_combo, 0, 1, 1, 2) # --- Readability --- layout.addSpacing(5) readability_group_box = QGroupBox('Readability options:', self) layout.addWidget(readability_group_box) readability_layout = QGridLayout() readability_group_box.setLayout(readability_layout) readability_label = QLabel('Readability statistics available are <a href="http://en.wikipedia.org/wiki/Flesch–Kincaid_readability_test">Flesch-Kincaid</a> ' 'or <a href="http://en.wikipedia.org/wiki/Gunning_fog_index">Gunning Fog Index</a>.', self) readability_layout.addWidget(readability_label, 0, 0, 1, 3) readability_label.linkActivated.connect(self._link_activated) flesch_reading_column_label = QLabel('&Flesch Reading Ease:', self) flesch_reading_column_label.setToolTip('Specify the custom column to store a computed Flesch Reading Ease score.\n' 'Leave this blank if you do not want to calculate it') flesch_reading_col = library_config.get(KEY_FLESCH_READING_CUSTOM_COLUMN, '') self.flesch_reading_column_combo = CustomColumnComboBox(self, avail_columns, flesch_reading_col) flesch_reading_column_label.setBuddy(self.flesch_reading_column_combo) readability_layout.addWidget(flesch_reading_column_label, 1, 0, 1, 1) readability_layout.addWidget(self.flesch_reading_column_combo, 1, 1, 1, 2) flesch_grade_column_label = QLabel('Flesch-&Kincaid Grade:', self) flesch_grade_column_label.setToolTip('Specify the custom column to store a computed Flesch-Kincaid Grade Level score.\n' 'Leave this blank if you do not want to calculate it') flesch_grade_col = library_config.get(KEY_FLESCH_GRADE_CUSTOM_COLUMN, '') self.flesch_grade_column_combo = CustomColumnComboBox(self, avail_columns, flesch_grade_col) flesch_grade_column_label.setBuddy(self.flesch_grade_column_combo) readability_layout.addWidget(flesch_grade_column_label, 2, 0, 1, 1) readability_layout.addWidget(self.flesch_grade_column_combo, 2, 1, 1, 2) gunning_fog_column_label = QLabel('&Gunning Fox Index:', self) gunning_fog_column_label.setToolTip('Specify the custom column to store a computed Gunning Fog Index score.\n' 'Leave this blank if you do not want to calculate it') gunning_fog_col = library_config.get(KEY_GUNNING_FOG_CUSTOM_COLUMN, '') self.gunning_fog_column_combo = CustomColumnComboBox(self, avail_columns, gunning_fog_col) gunning_fog_column_label.setBuddy(self.gunning_fog_column_combo) readability_layout.addWidget(gunning_fog_column_label, 3, 0, 1, 1) readability_layout.addWidget(self.gunning_fog_column_combo, 3, 1, 1, 2) # --- Other options --- layout.addSpacing(5) other_group_box = QGroupBox('Other options:', self) layout.addWidget(other_group_box) other_group_box_layout = QGridLayout() other_group_box.setLayout(other_group_box_layout) button_default_label = QLabel('&Button default:', self) button_default_label.setToolTip('If plugin is placed as a toolbar button, choose a default action when clicked on') self.button_default_combo = KeyValueComboBox(self, BUTTON_DEFAULTS, button_default) button_default_label.setBuddy(self.button_default_combo) other_group_box_layout.addWidget(button_default_label, 0, 0, 1, 1) other_group_box_layout.addWidget(self.button_default_combo, 0, 1, 1, 2) self.overwrite_checkbox = QCheckBox('Always overwrite an existing word/page count', self) self.overwrite_checkbox.setToolTip('Uncheck this option if you have manually populated values in\n' 'either of your page/word custom columns, and never want the\n' 'plugin to overwrite it. Acts as a convenience option for users\n' 'who have the toolbar button configured to populate both page\n' 'and word count, but for some books have already assigned values\n' 'into a column and just want the zero/blank column populated.') self.overwrite_checkbox.setChecked(overwrite_existing) other_group_box_layout.addWidget(self.overwrite_checkbox, 1, 0, 1, 3) keyboard_shortcuts_button = QPushButton('Keyboard shortcuts...', self) keyboard_shortcuts_button.setToolTip(_( 'Edit the keyboard shortcuts associated with this plugin')) keyboard_shortcuts_button.clicked.connect(self.edit_shortcuts) view_prefs_button = QPushButton('&View library preferences...', self) view_prefs_button.setToolTip(_( 'View data stored in the library database for this plugin')) view_prefs_button.clicked.connect(self.view_prefs) layout.addWidget(keyboard_shortcuts_button) layout.addWidget(view_prefs_button) layout.addStretch(1)
def __init__(self, parent, db): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('Check Library -- Problems Found')) self.setWindowIcon(QIcon(I('debug.png'))) self._tl = QHBoxLayout() self.setLayout(self._tl) self.splitter = QSplitter(self) self.left = QWidget(self) self.splitter.addWidget(self.left) self.helpw = QTextEdit(self) self.splitter.addWidget(self.helpw) self._tl.addWidget(self.splitter) self._layout = QVBoxLayout() self.left.setLayout(self._layout) self.helpw.setReadOnly(True) self.helpw.setText(_('''\ <h1>Help</h1> <p>calibre stores the list of your books and their metadata in a database. The actual book files and covers are stored as normal files in the calibre library folder. The database contains a list of the files and covers belonging to each book entry. This tool checks that the actual files in the library folder on your computer match the information in the database.</p> <p>The result of each type of check is shown to the left. The various checks are: </p> <ul> <li><b>Invalid titles</b>: These are files and folders appearing in the library where books titles should, but that do not have the correct form to be a book title.</li> <li><b>Extra titles</b>: These are extra files in your calibre library that appear to be correctly-formed titles, but have no corresponding entries in the database</li> <li><b>Invalid authors</b>: These are files appearing in the library where only author folders should be.</li> <li><b>Extra authors</b>: These are folders in the calibre library that appear to be authors but that do not have entries in the database</li> <li><b>Missing book formats</b>: These are book formats that are in the database but have no corresponding format file in the book's folder. <li><b>Extra book formats</b>: These are book format files found in the book's folder but not in the database. <li><b>Unknown files in books</b>: These are extra files in the folder of each book that do not correspond to a known format or cover file.</li> <li><b>Missing cover files</b>: These represent books that are marked in the database as having covers but the actual cover files are missing.</li> <li><b>Cover files not in database</b>: These are books that have cover files but are marked as not having covers in the database.</li> <li><b>Folder raising exception</b>: These represent folders in the calibre library that could not be processed/understood by this tool.</li> </ul> <p>There are two kinds of automatic fixes possible: <i>Delete marked</i> and <i>Fix marked</i>.</p> <p><i>Delete marked</i> is used to remove extra files/folders/covers that have no entries in the database. Check the box next to the item you want to delete. Use with caution.</p> <p><i>Fix marked</i> is applicable only to covers and missing formats (the three lines marked 'fixable'). In the case of missing cover files, checking the fixable box and pushing this button will tell calibre that there is no cover for all of the books listed. Use this option if you are not going to restore the covers from a backup. In the case of extra cover files, checking the fixable box and pushing this button will tell calibre that the cover files it found are correct for all the books listed. Use this when you are not going to delete the file(s). In the case of missing formats, checking the fixable box and pushing this button will tell calibre that the formats are really gone. Use this if you are not going to restore the formats from a backup.</p> ''')) self.log = QTreeWidget(self) self.log.itemChanged.connect(self.item_changed) self.log.itemExpanded.connect(self.item_expanded_or_collapsed) self.log.itemCollapsed.connect(self.item_expanded_or_collapsed) self._layout.addWidget(self.log) self.check_button = QPushButton(_('&Run the check again')) self.check_button.setDefault(False) self.check_button.clicked.connect(self.run_the_check) self.copy_button = QPushButton(_('Copy &to clipboard')) self.copy_button.setDefault(False) self.copy_button.clicked.connect(self.copy_to_clipboard) self.ok_button = QPushButton(_('&Done')) self.ok_button.setDefault(True) self.ok_button.clicked.connect(self.accept) self.delete_button = QPushButton(_('Delete &marked')) self.delete_button.setToolTip(_('Delete marked files (checked subitems)')) self.delete_button.setDefault(False) self.delete_button.clicked.connect(self.delete_marked) self.fix_button = QPushButton(_('&Fix marked')) self.fix_button.setDefault(False) self.fix_button.setEnabled(False) self.fix_button.setToolTip(_('Fix marked sections (checked fixable items)')) self.fix_button.clicked.connect(self.fix_items) self.bbox = QDialogButtonBox(self) self.bbox.addButton(self.check_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.delete_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.fix_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.copy_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.ok_button, QDialogButtonBox.AcceptRole) h = QHBoxLayout() ln = QLabel(_('Names to ignore:')) h.addWidget(ln) self.name_ignores = QLineEdit() self.name_ignores.setText(db.prefs.get('check_library_ignore_names', '')) self.name_ignores.setToolTip( _('Enter comma-separated standard file name wildcards, such as synctoy*.dat')) ln.setBuddy(self.name_ignores) h.addWidget(self.name_ignores) le = QLabel(_('Extensions to ignore')) h.addWidget(le) self.ext_ignores = QLineEdit() self.ext_ignores.setText(db.prefs.get('check_library_ignore_extensions', '')) self.ext_ignores.setToolTip( _('Enter comma-separated extensions without a leading dot. Used only in book folders')) le.setBuddy(self.ext_ignores) h.addWidget(self.ext_ignores) self._layout.addLayout(h) self._layout.addWidget(self.bbox) self.resize(950, 500) self.bbox.setEnabled(True)
class AddBookDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None, mi=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:add book dialog') self.setWindowTitle('Add text to Casanova:') self.gui = parent self.mm = mm self.mi = mi self.one_line_description = '' layout = QVBoxLayout(self) self.setLayout(layout) self.one_liner_label = QLabel( 'Enter a short description (255 chars max) before pressing OK') layout.addWidget(self.one_liner_label) self.one_liner_str = QLineEdit(self) self.one_liner_str.setText('') layout.addWidget(self.one_liner_str) self.one_liner_label.setBuddy(self.one_liner_str) self.values_label = QLabel( 'Below are potential matches of texts that already exist - please make sure you are adding something new' ) layout.addWidget(self.values_label) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_choices() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self): self.values_list.clear() choices = self.mm.search(self.mi.title) if choices is None or len(choices) == 0: item = QListWidgetItem(get_icon('images/books.png'), _('there seem to be no matches'), self.values_list) self.values_list.addItem(item) for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id, )) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() one_liner = unicode(self.one_liner_str.text()) if one_liner == '': self.values_list.clear() item = QListWidgetItem(get_icon('images/books.png'), _('you need to enter a short description'), self.values_list) self.values_list.addItem(item) else: self.one_line_description = one_liner self.accept()
def __init__(self, field_metadata, parent=None, revert_tooltip=None, datetime_fmt='MMMM yyyy', blank_as_equal=True, fields=('title', 'authors', 'series', 'tags', 'rating', 'publisher', 'pubdate', 'identifiers', 'languages', 'comments', 'cover')): QWidget.__init__(self, parent) self.l = l = QGridLayout() l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) revert_tooltip = revert_tooltip or _('Revert %s') self.current_mi = None self.changed_font = QFont(QApplication.font()) self.changed_font.setBold(True) self.changed_font.setItalic(True) self.blank_as_equal = blank_as_equal self.widgets = OrderedDict() row = 0 for field in fields: m = field_metadata[field] dt = m['datatype'] extra = None if 'series' in {field, dt}: cls = SeriesEdit elif field == 'identifiers': cls = IdentifiersEdit elif field == 'languages': cls = LanguagesEdit elif 'comments' in {field, dt}: cls = CommentsEdit elif 'rating' in {field, dt}: cls = RatingsEdit elif dt == 'datetime': extra = datetime_fmt cls = DateEdit elif field == 'cover': cls = CoverView elif dt in {'text', 'enum'}: cls = LineEdit else: continue neww = cls(field, True, self, m, extra) neww.changed.connect(partial(self.changed, field)) oldw = cls(field, False, self, m, extra) newl = QLabel('&%s:' % m['name']) newl.setBuddy(neww) button = QToolButton(self) button.setIcon(QIcon(I('back.png'))) button.clicked.connect(partial(self.revert, field)) button.setToolTip(revert_tooltip % m['name']) self.widgets[field] = Widgets(neww, oldw, newl, button) for i, w in enumerate((newl, neww, button, oldw)): c = i if i < 2 else i + 1 if w is oldw: c += 1 l.addWidget(w, row, c) row += 1 self.sep = f = QFrame(self) f.setFrameShape(f.VLine) l.addWidget(f, 0, 2, row, 1) self.sep2 = f = QFrame(self) f.setFrameShape(f.VLine) l.addWidget(f, 0, 4, row, 1)
class ManageKeysDialog(QDialog): def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext=u"", wineprefix=None): QDialog.__init__(self, parent) self.parent = parent self.key_type_name = key_type_name self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext self.import_key = (keyfile_ext != u"") self.binary_file = (keyfile_ext == u"der") self.json_file = (keyfile_ext == u"k4i") self.wineprefix = wineprefix self.setWindowTitle("{0} {1}: Manage {2}s".format( PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) # Start Qt Gui dialog layout layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) layout.addWidget(keys_group_box) keys_group_box_layout = QHBoxLayout() keys_group_box.setLayout(keys_group_box_layout) self.listy = QListWidget(self) self.listy.setToolTip( u"{0}s that will be used to decrypt ebooks".format( self.key_type_name)) self.listy.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_list() keys_group_box_layout.addWidget(self.listy) button_layout = QVBoxLayout() keys_group_box_layout.addLayout(button_layout) self._add_key_button = QtGui.QToolButton(self) self._add_key_button.setToolTip(u"Create new {0}".format( self.key_type_name)) self._add_key_button.setIcon(QIcon(I('plus.png'))) self._add_key_button.clicked.connect(self.add_key) button_layout.addWidget(self._add_key_button) self._delete_key_button = QtGui.QToolButton(self) self._delete_key_button.setToolTip(_(u"Delete highlighted key")) self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) self._delete_key_button.clicked.connect(self.delete_key) button_layout.addWidget(self._delete_key_button) if type(self.plugin_keys) == dict and self.import_key: self._rename_key_button = QtGui.QToolButton(self) self._rename_key_button.setToolTip(_(u"Rename highlighted key")) self._rename_key_button.setIcon(QIcon(I('edit-select-all.png'))) self._rename_key_button.clicked.connect(self.rename_key) button_layout.addWidget(self._rename_key_button) self.export_key_button = QtGui.QToolButton(self) self.export_key_button.setToolTip( u"Save highlighted key to a .{0} file".format( self.keyfile_ext)) self.export_key_button.setIcon(QIcon(I('save.png'))) self.export_key_button.clicked.connect(self.export_key) button_layout.addWidget(self.export_key_button) spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) button_layout.addItem(spacerItem) if self.wineprefix is not None: layout.addSpacing(5) wineprefix_layout = QHBoxLayout() layout.addLayout(wineprefix_layout) wineprefix_layout.setAlignment(Qt.AlignCenter) self.wp_label = QLabel(u"WINEPREFIX:") wineprefix_layout.addWidget(self.wp_label) self.wp_lineedit = QLineEdit(self) wineprefix_layout.addWidget(self.wp_lineedit) self.wp_label.setBuddy(self.wp_lineedit) self.wp_lineedit.setText(self.wineprefix) layout.addSpacing(5) migrate_layout = QHBoxLayout() layout.addLayout(migrate_layout) if self.import_key: migrate_layout.setAlignment(Qt.AlignJustify) self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self) self.migrate_btn.setToolTip( u"Import *.{0} files (created using other tools).".format( self.keyfile_ext)) self.migrate_btn.clicked.connect(self.migrate_wrapper) migrate_layout.addWidget(self.migrate_btn) migrate_layout.addStretch() self.button_box = QDialogButtonBox(QDialogButtonBox.Close) self.button_box.rejected.connect(self.close) migrate_layout.addWidget(self.button_box) self.resize(self.sizeHint()) def getwineprefix(self): if self.wineprefix is not None: return unicode(self.wp_lineedit.text().toUtf8(), 'utf8').strip() return u"" def populate_list(self): if type(self.plugin_keys) == dict: for key in self.plugin_keys.keys(): self.listy.addItem(QListWidgetItem(key)) else: for key in self.plugin_keys: self.listy.addItem(QListWidgetItem(key)) def add_key(self): d = self.create_key(self) d.exec_() if d.result() != d.Accepted: # New key generation cancelled. return new_key_value = d.key_value if type(self.plugin_keys) == dict: if new_key_value in self.plugin_keys.values(): old_key_name = [ name for name, value in self.plugin_keys.iteritems() if value == new_key_value ][0] info_dialog( None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name), u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added." .format(old_key_name, self.key_type_name), show=True) return self.plugin_keys[d.key_name] = new_key_value else: if new_key_value in self.plugin_keys: info_dialog( None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name), u"This {0} is already in the list of {0}s has not been added." .format(self.key_type_name), show=True) return self.plugin_keys.append(d.key_value) self.listy.clear() self.populate_list() def rename_key(self): if not self.listy.currentItem(): errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format( self.key_type_name) r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return d = RenameKeyDialog(self) d.exec_() if d.result() != d.Accepted: # rename cancelled or moot. return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog( self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?" .format(keyname, d.key_name, self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys[d.key_name] = self.plugin_keys[keyname] del self.plugin_keys[keyname] self.listy.clear() self.populate_list() def delete_key(self): if not self.listy.currentItem(): return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog( self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?". format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return if type(self.plugin_keys) == dict: del self.plugin_keys[keyname] else: self.plugin_keys.remove(keyname) self.listy.clear() self.populate_list() def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. help_file_name = u"{0}_{1}_Help.htm".format( PLUGIN_NAME, self.key_type_name) file_path = os.path.join(config_dir, u"plugins", u"DeDRM", u"help", help_file_name) with open(file_path, 'w') as f: f.write(self.parent.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url)) def migrate_files(self): dynamic[PLUGIN_NAME + u"config_dir"] = config_dir files = choose_files( self, PLUGIN_NAME + u"config_dir", u"Select {0} files to import".format(self.key_type_name), [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])], False) counter = 0 skipped = 0 if files: for filename in files: fpath = os.path.join(config_dir, filename) filename = os.path.basename(filename) new_key_name = os.path.splitext(os.path.basename(filename))[0] with open(fpath, 'rb') as keyfile: new_key_value = keyfile.read() if self.binary_file: new_key_value = new_key_value.encode('hex') elif self.json_file: new_key_value = json.loads(new_key_value) match = False for key in self.plugin_keys.keys(): if uStrCmp(new_key_name, key, True): skipped += 1 msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file <strong>{1}</strong>.\nRename the existing key and import again".format( new_key_name, filename) inf = info_dialog(None, "{0} {1}".format( PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) match = True break if not match: if new_key_value in self.plugin_keys.values(): old_key_name = [ name for name, value in self.plugin_keys.iteritems() if value == new_key_value ][0] skipped += 1 info_dialog( None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped." .format(filename, old_key_name), show_copy_button=False, show=True) else: counter += 1 self.plugin_keys[new_key_name] = new_key_value msg = u"" if counter + skipped > 1: if counter > 0: msg += u"Imported <strong>{0:d}</strong> key {1}. ".format( counter, u"file" if counter == 1 else u"files") if skipped > 0: msg += u"Skipped <strong>{0:d}</strong> key {1}.".format( skipped, u"file" if counter == 1 else u"files") inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) return counter > 0 def migrate_wrapper(self): if self.migrate_files(): self.listy.clear() self.populate_list() def export_key(self): if not self.listy.currentItem(): errmsg = u"No keyfile selected to export. Highlight a keyfile first." r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return filter = QString(u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext)) keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if dynamic.get(PLUGIN_NAME + 'save_dir'): defaultname = os.path.join( dynamic.get(PLUGIN_NAME + 'save_dir'), u"{0}.{1}".format(keyname, self.keyfile_ext)) else: defaultname = os.path.join( os.path.expanduser('~'), u"{0}.{1}".format(keyname, self.keyfile_ext)) filename = unicode( QtGui.QFileDialog.getSaveFileName( self, u"Save {0} File as...".format(self.key_type_name), defaultname, u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext), filter)) if filename: dynamic[PLUGIN_NAME + 'save_dir'] = os.path.split(filename)[0] with file(filename, 'w') as fname: if self.binary_file: fname.write(self.plugin_keys[keyname].decode('hex')) elif self.json_file: fname.write(json.dumps(self.plugin_keys[keyname])) else: fname.write(self.plugin_keys[keyname])
def __init__( self, field_metadata, parent=None, revert_tooltip=None, datetime_fmt='MMMM yyyy', blank_as_equal=True, fields=('title', 'authors', 'series', 'tags', 'rating', 'publisher', 'pubdate', 'identifiers', 'languages', 'comments', 'cover')): QWidget.__init__(self, parent) self.l = l = QGridLayout() l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) revert_tooltip = revert_tooltip or _('Revert %s') self.current_mi = None self.changed_font = QFont(QApplication.font()) self.changed_font.setBold(True) self.changed_font.setItalic(True) self.blank_as_equal = blank_as_equal self.widgets = OrderedDict() row = 0 for field in fields: m = field_metadata[field] dt = m['datatype'] extra = None if 'series' in {field, dt}: cls = SeriesEdit elif field == 'identifiers': cls = IdentifiersEdit elif field == 'languages': cls = LanguagesEdit elif 'comments' in {field, dt}: cls = CommentsEdit elif 'rating' in {field, dt}: cls = RatingsEdit elif dt == 'datetime': extra = datetime_fmt cls = DateEdit elif field == 'cover': cls = CoverView elif dt in {'text', 'enum'}: cls = LineEdit else: continue neww = cls(field, True, self, m, extra) neww.changed.connect(partial(self.changed, field)) oldw = cls(field, False, self, m, extra) newl = QLabel('&%s:' % m['name']) newl.setBuddy(neww) button = QToolButton(self) button.setIcon(QIcon(I('back.png'))) button.clicked.connect(partial(self.revert, field)) button.setToolTip(revert_tooltip % m['name']) self.widgets[field] = Widgets(neww, oldw, newl, button) for i, w in enumerate((newl, neww, button, oldw)): c = i if i < 2 else i + 1 if w is oldw: c += 1 l.addWidget(w, row, c) row += 1 self.sep = f = QFrame(self) f.setFrameShape(f.VLine) l.addWidget(f, 0, 2, row, 1) self.sep2 = f = QFrame(self) f.setFrameShape(f.VLine) l.addWidget(f, 0, 4, row, 1) if 'comments' in self.widgets and not gprefs.get('diff_widget_show_comments_controls', True): self.widgets['comments'].new.hide_toolbars()
class ConfigWidget(QWidget): def __init__(self, plugin_action, prefs): QWidget.__init__(self) self.plugin_action = plugin_action self.prefs = prefs self.layout = QGridLayout() self.setLayout(self.layout) accounts = self.prefs[self.prefs.ACCOUNTS] # Copy any data necessary into the prefs object # The primary account, as configured in the GUI above account = accounts.get('0', {}) self.labelUrlBase = QLabel(_('URL')) self.layout.addWidget(self.labelUrlBase, 0, 0) self.urlbase = QLabel() if prefs[prefs.URLBASE] is not None: self.urlbase.setText(prefs[prefs.URLBASE]) self.layout.addWidget(self.urlbase, 0, 1) self.labelUrlBase.setBuddy(self.urlbase) self.labelUserName = QLabel(_('Username')) self.layout.addWidget(self.labelUserName, 1, 0) self.username = QLineEdit(self) if account.get(prefs.USERNAME) is not None: self.username.setText(account[prefs.USERNAME]) self.layout.addWidget(self.username, 1, 1) self.labelUserName.setBuddy(self.username) self.labelPassword = QLabel(_('Password')) self.layout.addWidget(self.labelPassword, 2, 0) self.password = QLineEdit(self) if account.get(prefs.OBFUSCATED_PASSWORD) is not None: decrypted = prefs.decrypt_password(account[prefs.OBFUSCATED_PASSWORD]) self.password.setText(decrypted) self.layout.addWidget(self.password, 2, 1) self.labelPassword.setBuddy(self.password) def save_settings(self): # TODO proper obfuscating somewhere, maybe even in 'migrate' accounts = self.prefs[self.prefs.ACCOUNTS] # Copy any data necessary into the prefs object # The primary account, as configured in the GUI above account_id = '0' account = accounts.get(account_id, {}) account[self.prefs.ACCOUNT_ID] = account_id account[self.prefs.USERNAME] = '%s' % self.username.text() decrypted = '%s' % self.password.text() # account['Lala'] = decrypted account[self.prefs.OBFUSCATED_PASSWORD] = '%s' % self.prefs.encrypt_password(decrypted) account[self.prefs.ENABLED] = True accounts[account_id] = account # Now the secondary account :-) account_id = '1' account = accounts.get(account_id, {}) account[self.prefs.ACCOUNT_ID] = account_id if account.get(self.prefs.USERNAME) is None: account[self.prefs.USERNAME] = '' decrypted = '' # account['Lala'] = decrypted account[self.prefs.OBFUSCATED_PASSWORD] = '%s' % self.prefs.encrypt_password(decrypted) account[self.prefs.ENABLED] = False accounts[account_id] = account # Now, put the hash back to the main prefs self.prefs[self.prefs.ACCOUNTS] = accounts # And save it... self.prefs.save()
class ConfigWidget(QWidget): def __init__(self, plugin_action, prefs): QWidget.__init__(self) self.plugin_action = plugin_action self.prefs = prefs self.layout = QGridLayout() self.setLayout(self.layout) accounts = self.prefs[self.prefs.ACCOUNTS] # Copy any data necessary into the prefs object # The primary account, as configured in the GUI above account = accounts.get('0', {}) self.labelUrlBase = QLabel(_('URL')) self.layout.addWidget(self.labelUrlBase, 0, 0) self.urlbase = QLabel() if prefs[prefs.URLBASE] is not None: self.urlbase.setText(prefs[prefs.URLBASE]) self.layout.addWidget(self.urlbase, 0, 1) self.labelUrlBase.setBuddy(self.urlbase) self.labelUserName = QLabel(_('Username')) self.layout.addWidget(self.labelUserName, 1, 0) self.username = QLineEdit(self) if account.get(prefs.USERNAME) is not None: self.username.setText(account[prefs.USERNAME]) self.layout.addWidget(self.username, 1, 1) self.labelUserName.setBuddy(self.username) self.labelPassword = QLabel(_('Password')) self.layout.addWidget(self.labelPassword, 2, 0) self.password = QLineEdit(self) if account.get(prefs.OBFUSCATED_PASSWORD) is not None: decrypted = prefs.decrypt_password( account[prefs.OBFUSCATED_PASSWORD]) self.password.setText(decrypted) self.layout.addWidget(self.password, 2, 1) self.labelPassword.setBuddy(self.password) def save_settings(self): # TODO proper obfuscating somewhere, maybe even in 'migrate' accounts = self.prefs[self.prefs.ACCOUNTS] # Copy any data necessary into the prefs object # The primary account, as configured in the GUI above account_id = '0' account = accounts.get(account_id, {}) account[self.prefs.ACCOUNT_ID] = account_id account[self.prefs.USERNAME] = '%s' % self.username.text() decrypted = '%s' % self.password.text() # account['Lala'] = decrypted account[self.prefs. OBFUSCATED_PASSWORD] = '%s' % self.prefs.encrypt_password( decrypted) account[self.prefs.ENABLED] = True accounts[account_id] = account # Now the secondary account :-) account_id = '1' account = accounts.get(account_id, {}) account[self.prefs.ACCOUNT_ID] = account_id if account.get(self.prefs.USERNAME) is None: account[self.prefs.USERNAME] = '' decrypted = '' # account['Lala'] = decrypted account[self.prefs. OBFUSCATED_PASSWORD] = '%s' % self.prefs.encrypt_password( decrypted) account[self.prefs.ENABLED] = False accounts[account_id] = account # Now, put the hash back to the main prefs self.prefs[self.prefs.ACCOUNTS] = accounts # And save it... self.prefs.save()
class ValueTypeEditor(QWidget): ValueTypes = (bool, int, float, complex, str) def __init__(self, *args): QWidget.__init__(self, *args) lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(5) # type selector self.wtypesel = QComboBox(self) for i, tp in enumerate(self.ValueTypes): self.wtypesel.addItem(tp.__name__) QObject.connect(self.wtypesel, SIGNAL("activated(int)"), self._selectTypeNum) typesel_lab = QLabel("&Type:", self) typesel_lab.setBuddy(self.wtypesel) lo.addWidget(typesel_lab, 0) lo.addWidget(self.wtypesel, 0) self.wvalue = QLineEdit(self) self.wvalue_lab = QLabel("&Value:", self) self.wvalue_lab.setBuddy(self.wvalue) self.wbool = QComboBox(self) self.wbool.addItems(["false", "true"]) self.wbool.setCurrentIndex(1) lo.addWidget(self.wvalue_lab, 0) lo.addWidget(self.wvalue, 1) lo.addWidget(self.wbool, 1) self.wvalue.hide() # make input validators self._validators = {int: QIntValidator(self), float: QDoubleValidator(self)} # select bool type initially self._selectTypeNum(0) def _selectTypeNum(self, index): tp = self.ValueTypes[index] self.wbool.setShown(tp is bool) self.wvalue.setShown(tp is not bool) self.wvalue_lab.setBuddy(self.wbool if tp is bool else self.wvalue) self.wvalue.setValidator(self._validators.get(tp, None)) def setValue(self, value): """Sets current value""" for i, tp in enumerate(self.ValueTypes): if isinstance(value, tp): self.wtypesel.setCurrentIndex(i) self._selectTypeNum(i) if tp is bool: self.wbool.setCurrentIndex(1 if value else 0) else: self.wvalue.setText(str(value)) return # unknown value: set bool self.setValue(True) def getValue(self): """Returns current value, or None if no legal value is set""" tp = self.ValueTypes[self.wtypesel.currentIndex()] if tp is bool: return bool(self.wbool.currentIndex()) else: try: return tp(self.wvalue.text()) except: print("Error converting input to type ", tp.__name__) traceback.print_exc() return None
def __init__(self, settings, all_formats, supports_subdirs, must_read_metadata, supports_use_author_sort, extra_customization_message, device, extra_customization_choices=None): QWidget.__init__(self) Ui_ConfigWidget.__init__(self) self.setupUi(self) self.settings = settings all_formats = set(all_formats) self.calibre_known_formats = device.FORMATS try: self.device_name = device.get_gui_name() except TypeError: self.device_name = getattr(device, 'gui_name', None) or _('Device') if device.USER_CAN_ADD_NEW_FORMATS: all_formats = set(all_formats) | set(BOOK_EXTENSIONS) format_map = settings.format_map disabled_formats = list(set(all_formats).difference(format_map)) for format in format_map + list(sorted(disabled_formats)): item = QListWidgetItem(format, self.columns) item.setData(Qt.UserRole, QVariant(format)) item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable) item.setCheckState(Qt.Checked if format in format_map else Qt.Unchecked) self.column_up.clicked.connect(self.up_column) self.column_down.clicked.connect(self.down_column) if device.HIDE_FORMATS_CONFIG_BOX: self.groupBox.hide() if supports_subdirs: self.opt_use_subdirs.setChecked(self.settings.use_subdirs) else: self.opt_use_subdirs.hide() if not must_read_metadata: self.opt_read_metadata.setChecked(self.settings.read_metadata) else: self.opt_read_metadata.hide() if supports_use_author_sort: self.opt_use_author_sort.setChecked(self.settings.use_author_sort) else: self.opt_use_author_sort.hide() if extra_customization_message: extra_customization_choices = extra_customization_choices or {} def parse_msg(m): msg, _, tt = m.partition(':::') if m else ('', '', '') return msg.strip(), textwrap.fill(tt.strip(), 100) if isinstance(extra_customization_message, list): self.opt_extra_customization = [] if len(extra_customization_message) > 6: row_func = lambda x, y: ((x/2) * 2) + y col_func = lambda x: x%2 else: row_func = lambda x, y: x*2 + y col_func = lambda x: 0 for i, m in enumerate(extra_customization_message): label_text, tt = parse_msg(m) if not label_text: self.opt_extra_customization.append(None) continue if isinstance(settings.extra_customization[i], bool): self.opt_extra_customization.append(QCheckBox(label_text)) self.opt_extra_customization[-1].setToolTip(tt) self.opt_extra_customization[i].setChecked(bool(settings.extra_customization[i])) elif i in extra_customization_choices: cb = QComboBox(self) self.opt_extra_customization.append(cb) l = QLabel(label_text) l.setToolTip(tt), cb.setToolTip(tt), l.setBuddy(cb), cb.setToolTip(tt) for li in sorted(extra_customization_choices[i]): self.opt_extra_customization[i].addItem(li) cb.setCurrentIndex(max(0, cb.findText(settings.extra_customization[i]))) else: self.opt_extra_customization.append(QLineEdit(self)) l = QLabel(label_text) l.setToolTip(tt) self.opt_extra_customization[i].setToolTip(tt) l.setBuddy(self.opt_extra_customization[i]) l.setWordWrap(True) self.opt_extra_customization[i].setText(settings.extra_customization[i]) self.opt_extra_customization[i].setCursorPosition(0) self.extra_layout.addWidget(l, row_func(i, 0), col_func(i)) self.extra_layout.addWidget(self.opt_extra_customization[i], row_func(i, 1), col_func(i)) else: self.opt_extra_customization = QLineEdit() label_text, tt = parse_msg(extra_customization_message) l = QLabel(label_text) l.setToolTip(tt) l.setBuddy(self.opt_extra_customization) l.setWordWrap(True) if settings.extra_customization: self.opt_extra_customization.setText(settings.extra_customization) self.opt_extra_customization.setCursorPosition(0) self.opt_extra_customization.setCursorPosition(0) self.extra_layout.addWidget(l, 0, 0) self.extra_layout.addWidget(self.opt_extra_customization, 1, 0) self.opt_save_template.setText(settings.save_template)
class ManageKeysDialog(QDialog): def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u"", wineprefix = None): QDialog.__init__(self,parent) self.parent = parent self.key_type_name = key_type_name self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext self.import_key = (keyfile_ext != u"") self.binary_file = (keyfile_ext == u"der") self.json_file = (keyfile_ext == u"k4i") self.wineprefix = wineprefix self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) # Start Qt Gui dialog layout layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) layout.addWidget(keys_group_box) keys_group_box_layout = QHBoxLayout() keys_group_box.setLayout(keys_group_box_layout) self.listy = QListWidget(self) self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name)) self.listy.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_list() keys_group_box_layout.addWidget(self.listy) button_layout = QVBoxLayout() keys_group_box_layout.addLayout(button_layout) self._add_key_button = QtGui.QToolButton(self) self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name)) self._add_key_button.setIcon(QIcon(I('plus.png'))) self._add_key_button.clicked.connect(self.add_key) button_layout.addWidget(self._add_key_button) self._delete_key_button = QtGui.QToolButton(self) self._delete_key_button.setToolTip(_(u"Delete highlighted key")) self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) self._delete_key_button.clicked.connect(self.delete_key) button_layout.addWidget(self._delete_key_button) if type(self.plugin_keys) == dict and self.import_key: self._rename_key_button = QtGui.QToolButton(self) self._rename_key_button.setToolTip(_(u"Rename highlighted key")) self._rename_key_button.setIcon(QIcon(I('edit-select-all.png'))) self._rename_key_button.clicked.connect(self.rename_key) button_layout.addWidget(self._rename_key_button) self.export_key_button = QtGui.QToolButton(self) self.export_key_button.setToolTip(u"Save highlighted key to a .{0} file".format(self.keyfile_ext)) self.export_key_button.setIcon(QIcon(I('save.png'))) self.export_key_button.clicked.connect(self.export_key) button_layout.addWidget(self.export_key_button) spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) button_layout.addItem(spacerItem) if self.wineprefix is not None: layout.addSpacing(5) wineprefix_layout = QHBoxLayout() layout.addLayout(wineprefix_layout) wineprefix_layout.setAlignment(Qt.AlignCenter) self.wp_label = QLabel(u"WINEPREFIX:") wineprefix_layout.addWidget(self.wp_label) self.wp_lineedit = QLineEdit(self) wineprefix_layout.addWidget(self.wp_lineedit) self.wp_label.setBuddy(self.wp_lineedit) self.wp_lineedit.setText(self.wineprefix) layout.addSpacing(5) migrate_layout = QHBoxLayout() layout.addLayout(migrate_layout) if self.import_key: migrate_layout.setAlignment(Qt.AlignJustify) self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self) self.migrate_btn.setToolTip(u"Import *.{0} files (created using other tools).".format(self.keyfile_ext)) self.migrate_btn.clicked.connect(self.migrate_wrapper) migrate_layout.addWidget(self.migrate_btn) migrate_layout.addStretch() self.button_box = QDialogButtonBox(QDialogButtonBox.Close) self.button_box.rejected.connect(self.close) migrate_layout.addWidget(self.button_box) self.resize(self.sizeHint()) def getwineprefix(self): if self.wineprefix is not None: return unicode(self.wp_lineedit.text().toUtf8(), 'utf8').strip() return u"" def populate_list(self): if type(self.plugin_keys) == dict: for key in self.plugin_keys.keys(): self.listy.addItem(QListWidgetItem(key)) else: for key in self.plugin_keys: self.listy.addItem(QListWidgetItem(key)) def add_key(self): d = self.create_key(self) d.exec_() if d.result() != d.Accepted: # New key generation cancelled. return new_key_value = d.key_value if type(self.plugin_keys) == dict: if new_key_value in self.plugin_keys.values(): old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added.".format(old_key_name,self.key_type_name), show=True) return self.plugin_keys[d.key_name] = new_key_value else: if new_key_value in self.plugin_keys: info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name), show=True) return self.plugin_keys.append(d.key_value) self.listy.clear() self.populate_list() def rename_key(self): if not self.listy.currentItem(): errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format(self.key_type_name) r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return d = RenameKeyDialog(self) d.exec_() if d.result() != d.Accepted: # rename cancelled or moot. return keyname = unicode(self.listy.currentItem().text().toUtf8(),'utf8') if not question_dialog(self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?".format(keyname,d.key_name,self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys[d.key_name] = self.plugin_keys[keyname] del self.plugin_keys[keyname] self.listy.clear() self.populate_list() def delete_key(self): if not self.listy.currentItem(): return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return if type(self.plugin_keys) == dict: del self.plugin_keys[keyname] else: self.plugin_keys.remove(keyname) self.listy.clear() self.populate_list() def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. help_file_name = u"{0}_{1}_Help.htm".format(PLUGIN_NAME, self.key_type_name) file_path = os.path.join(config_dir, u"plugins", u"DeDRM", u"help", help_file_name) with open(file_path,'w') as f: f.write(self.parent.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url)) def migrate_files(self): dynamic[PLUGIN_NAME + u"config_dir"] = config_dir files = choose_files(self, PLUGIN_NAME + u"config_dir", u"Select {0} files to import".format(self.key_type_name), [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])], False) counter = 0 skipped = 0 if files: for filename in files: fpath = os.path.join(config_dir, filename) filename = os.path.basename(filename) new_key_name = os.path.splitext(os.path.basename(filename))[0] with open(fpath,'rb') as keyfile: new_key_value = keyfile.read() if self.binary_file: new_key_value = new_key_value.encode('hex') elif self.json_file: new_key_value = json.loads(new_key_value) match = False for key in self.plugin_keys.keys(): if uStrCmp(new_key_name, key, True): skipped += 1 msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file <strong>{1}</strong>.\nRename the existing key and import again".format(new_key_name,filename) inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) match = True break if not match: if new_key_value in self.plugin_keys.values(): old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] skipped += 1 info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True) else: counter += 1 self.plugin_keys[new_key_name] = new_key_value msg = u"" if counter+skipped > 1: if counter > 0: msg += u"Imported <strong>{0:d}</strong> key {1}. ".format(counter, u"file" if counter == 1 else u"files") if skipped > 0: msg += u"Skipped <strong>{0:d}</strong> key {1}.".format(skipped, u"file" if counter == 1 else u"files") inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) return counter > 0 def migrate_wrapper(self): if self.migrate_files(): self.listy.clear() self.populate_list() def export_key(self): if not self.listy.currentItem(): errmsg = u"No keyfile selected to export. Highlight a keyfile first." r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return filter = QString(u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext)) keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if dynamic.get(PLUGIN_NAME + 'save_dir'): defaultname = os.path.join(dynamic.get(PLUGIN_NAME + 'save_dir'), u"{0}.{1}".format(keyname , self.keyfile_ext)) else: defaultname = os.path.join(os.path.expanduser('~'), u"{0}.{1}".format(keyname , self.keyfile_ext)) filename = unicode(QtGui.QFileDialog.getSaveFileName(self, u"Save {0} File as...".format(self.key_type_name), defaultname, u"{0} Files (*.{1})".format(self.key_type_name,self.keyfile_ext), filter)) if filename: dynamic[PLUGIN_NAME + 'save_dir'] = os.path.split(filename)[0] with file(filename, 'w') as fname: if self.binary_file: fname.write(self.plugin_keys[keyname].decode('hex')) elif self.json_file: fname.write(json.dumps(self.plugin_keys[keyname])) else: fname.write(self.plugin_keys[keyname])
def __init__(self, parent, db): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('Check Library -- Problems Found')) self.setWindowIcon(QIcon(I('debug.png'))) self._tl = QHBoxLayout() self.setLayout(self._tl) self.splitter = QSplitter(self) self.left = QWidget(self) self.splitter.addWidget(self.left) self.helpw = QTextEdit(self) self.splitter.addWidget(self.helpw) self._tl.addWidget(self.splitter) self._layout = QVBoxLayout() self.left.setLayout(self._layout) self.helpw.setReadOnly(True) self.helpw.setText( _('''\ <h1>Help</h1> <p>calibre stores the list of your books and their metadata in a database. The actual book files and covers are stored as normal files in the calibre library folder. The database contains a list of the files and covers belonging to each book entry. This tool checks that the actual files in the library folder on your computer match the information in the database.</p> <p>The result of each type of check is shown to the left. The various checks are: </p> <ul> <li><b>Invalid titles</b>: These are files and folders appearing in the library where books titles should, but that do not have the correct form to be a book title.</li> <li><b>Extra titles</b>: These are extra files in your calibre library that appear to be correctly-formed titles, but have no corresponding entries in the database</li> <li><b>Invalid authors</b>: These are files appearing in the library where only author folders should be.</li> <li><b>Extra authors</b>: These are folders in the calibre library that appear to be authors but that do not have entries in the database</li> <li><b>Missing book formats</b>: These are book formats that are in the database but have no corresponding format file in the book's folder. <li><b>Extra book formats</b>: These are book format files found in the book's folder but not in the database. <li><b>Unknown files in books</b>: These are extra files in the folder of each book that do not correspond to a known format or cover file.</li> <li><b>Missing cover files</b>: These represent books that are marked in the database as having covers but the actual cover files are missing.</li> <li><b>Cover files not in database</b>: These are books that have cover files but are marked as not having covers in the database.</li> <li><b>Folder raising exception</b>: These represent folders in the calibre library that could not be processed/understood by this tool.</li> </ul> <p>There are two kinds of automatic fixes possible: <i>Delete marked</i> and <i>Fix marked</i>.</p> <p><i>Delete marked</i> is used to remove extra files/folders/covers that have no entries in the database. Check the box next to the item you want to delete. Use with caution.</p> <p><i>Fix marked</i> is applicable only to covers and missing formats (the three lines marked 'fixable'). In the case of missing cover files, checking the fixable box and pushing this button will tell calibre that there is no cover for all of the books listed. Use this option if you are not going to restore the covers from a backup. In the case of extra cover files, checking the fixable box and pushing this button will tell calibre that the cover files it found are correct for all the books listed. Use this when you are not going to delete the file(s). In the case of missing formats, checking the fixable box and pushing this button will tell calibre that the formats are really gone. Use this if you are not going to restore the formats from a backup.</p> ''')) self.log = QTreeWidget(self) self.log.itemChanged.connect(self.item_changed) self.log.itemExpanded.connect(self.item_expanded_or_collapsed) self.log.itemCollapsed.connect(self.item_expanded_or_collapsed) self._layout.addWidget(self.log) self.check_button = QPushButton(_('&Run the check again')) self.check_button.setDefault(False) self.check_button.clicked.connect(self.run_the_check) self.copy_button = QPushButton(_('Copy &to clipboard')) self.copy_button.setDefault(False) self.copy_button.clicked.connect(self.copy_to_clipboard) self.ok_button = QPushButton(_('&Done')) self.ok_button.setDefault(True) self.ok_button.clicked.connect(self.accept) self.delete_button = QPushButton(_('Delete &marked')) self.delete_button.setToolTip( _('Delete marked files (checked subitems)')) self.delete_button.setDefault(False) self.delete_button.clicked.connect(self.delete_marked) self.fix_button = QPushButton(_('&Fix marked')) self.fix_button.setDefault(False) self.fix_button.setEnabled(False) self.fix_button.setToolTip( _('Fix marked sections (checked fixable items)')) self.fix_button.clicked.connect(self.fix_items) self.bbox = QDialogButtonBox(self) self.bbox.addButton(self.check_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.delete_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.fix_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.copy_button, QDialogButtonBox.ActionRole) self.bbox.addButton(self.ok_button, QDialogButtonBox.AcceptRole) h = QHBoxLayout() ln = QLabel(_('Names to ignore:')) h.addWidget(ln) self.name_ignores = QLineEdit() self.name_ignores.setText( db.prefs.get('check_library_ignore_names', '')) self.name_ignores.setToolTip( _('Enter comma-separated standard file name wildcards, such as synctoy*.dat' )) ln.setBuddy(self.name_ignores) h.addWidget(self.name_ignores) le = QLabel(_('Extensions to ignore')) h.addWidget(le) self.ext_ignores = QLineEdit() self.ext_ignores.setText( db.prefs.get('check_library_ignore_extensions', '')) self.ext_ignores.setToolTip( _('Enter comma-separated extensions without a leading dot. Used only in book folders' )) le.setBuddy(self.ext_ignores) h.addWidget(self.ext_ignores) self._layout.addLayout(h) self._layout.addWidget(self.bbox) self.resize(950, 500) self.bbox.setEnabled(True)
class ValueTypeEditor(QWidget): ValueTypes = (bool, int, float, complex, str) def __init__(self, *args): QWidget.__init__(self, *args) lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(5) # type selector self.wtypesel = QComboBox(self) for i, tp in enumerate(self.ValueTypes): self.wtypesel.addItem(tp.__name__) QObject.connect(self.wtypesel, SIGNAL("activated(int)"), self._selectTypeNum) typesel_lab = QLabel("&Type:", self) typesel_lab.setBuddy(self.wtypesel) lo.addWidget(typesel_lab, 0) lo.addWidget(self.wtypesel, 0) self.wvalue = QLineEdit(self) self.wvalue_lab = QLabel("&Value:", self) self.wvalue_lab.setBuddy(self.wvalue) self.wbool = QComboBox(self) self.wbool.addItems(["false", "true"]) self.wbool.setCurrentIndex(1) lo.addWidget(self.wvalue_lab, 0) lo.addWidget(self.wvalue, 1) lo.addWidget(self.wbool, 1) self.wvalue.hide() # make input validators self._validators = { int: QIntValidator(self), float: QDoubleValidator(self) } # select bool type initially self._selectTypeNum(0) def _selectTypeNum(self, index): tp = self.ValueTypes[index] self.wbool.setShown(tp is bool) self.wvalue.setShown(tp is not bool) self.wvalue_lab.setBuddy(self.wbool if tp is bool else self.wvalue) self.wvalue.setValidator(self._validators.get(tp, None)) def setValue(self, value): """Sets current value""" for i, tp in enumerate(self.ValueTypes): if isinstance(value, tp): self.wtypesel.setCurrentIndex(i) self._selectTypeNum(i) if tp is bool: self.wbool.setCurrentIndex(1 if value else 0) else: self.wvalue.setText(str(value)) return # unknown value: set bool self.setValue(True) def getValue(self): """Returns current value, or None if no legal value is set""" tp = self.ValueTypes[self.wtypesel.currentIndex()] if tp is bool: return bool(self.wbool.currentIndex()) else: try: return tp(self.wvalue.text()) except: print("Error converting input to type ", tp.__name__) traceback.print_exc() return None