def __init__(self, parent, label, filename=None, dialog_label=None, file_types=None, default_suffix=None, file_mode=QFileDialog.AnyFile): QWidget.__init__(self, parent) lo = QHBoxLayout(self) lo.setContentsMargins(0, 0, 0, 0) lo.setSpacing(5) # label lab = QLabel(label, self) lo.addWidget(lab, 0) # text field self.wfname = QLineEdit(self) self.wfname.setReadOnly(True) self.setFilename(filename) lo.addWidget(self.wfname, 1) # selector wsel = QToolButton(self) wsel.setText("Choose...") QObject.connect(wsel, SIGNAL("clicked()"), self._chooseFile) lo.addWidget(wsel, 0) # other init self._file_dialog = None self._dialog_label = dialog_label or label self._file_types = file_types or "All files (*)" self._file_mode = file_mode self._default_suffix = default_suffix self._dir = None
def setup_ui(self): self.l = l = QFormLayout(self) self.setLayout(l) la = self.la = QLabel(_( 'You can import an HTML or DOCX file directly as an EPUB and edit it. The EPUB' ' will be generated with minimal changes from the source, unlike doing a full' ' conversion in calibre.')) la.setWordWrap(True) l.addRow(la) self.h1 = h1 = QHBoxLayout() self.src = src = QLineEdit(self) src.setPlaceholderText(_('Choose the file to import')) h1.addWidget(src) self.b1 = b = QToolButton(self) b.setIcon(QIcon(I('document_open.png'))) b.setText(_('Choose file')) h1.addWidget(b) l.addRow(_('Source file'), h1) b.clicked.connect(self.choose_source) b.setFocus(Qt.OtherFocusReason) self.h2 = h1 = QHBoxLayout() self.dest = src = QLineEdit(self) src.setPlaceholderText(_('Choose the location for the newly created EPUB')) h1.addWidget(src) self.b2 = b = QToolButton(self) b.setIcon(QIcon(I('document_open.png'))) b.setText(_('Choose file')) h1.addWidget(b) l.addRow(_('Destination file'), h1) b.clicked.connect(self.choose_destination) l.addRow(self.bb)
def _init_controls(self): # Add the control set vbl = QVBoxLayout() self.move_rule_up_tb = QToolButton() self.move_rule_up_tb.setObjectName("move_rule_up_tb") self.move_rule_up_tb.setToolTip('Move rule up') self.move_rule_up_tb.setIcon(QIcon(I('arrow-up.png'))) self.move_rule_up_tb.clicked.connect(self.move_row_up) vbl.addWidget(self.move_rule_up_tb) self.add_rule_tb = QToolButton() self.add_rule_tb.setObjectName("add_rule_tb") self.add_rule_tb.setToolTip('Add a new rule') self.add_rule_tb.setIcon(QIcon(I('plus.png'))) self.add_rule_tb.clicked.connect(self.add_row) vbl.addWidget(self.add_rule_tb) self.delete_rule_tb = QToolButton() self.delete_rule_tb.setObjectName("delete_rule_tb") self.delete_rule_tb.setToolTip('Delete selected rule') self.delete_rule_tb.setIcon(QIcon(I('list_remove.png'))) self.delete_rule_tb.clicked.connect(self.delete_row) vbl.addWidget(self.delete_rule_tb) self.move_rule_down_tb = QToolButton() self.move_rule_down_tb.setObjectName("move_rule_down_tb") self.move_rule_down_tb.setToolTip('Move rule down') self.move_rule_down_tb.setIcon(QIcon(I('arrow-down.png'))) self.move_rule_down_tb.clicked.connect(self.move_row_down) vbl.addWidget(self.move_rule_down_tb) self.layout.addLayout(vbl)
def __init__(self, all_formats, format_map): QWidget.__init__(self) self.l = l = QGridLayout() self.setLayout(l) self.f = f = QListWidget(self) l.addWidget(f, 0, 0, 3, 1) unchecked_formats = sorted(all_formats - set(format_map)) for fmt in format_map + unchecked_formats: item = QListWidgetItem(fmt, f) item.setData(Qt.UserRole, fmt) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) item.setCheckState(Qt.Checked if fmt in format_map else Qt.Unchecked) self.button_up = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) l.addWidget(b, 0, 1) b.clicked.connect(self.up) self.button_down = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) l.addWidget(b, 2, 1) b.clicked.connect(self.down)
def _init_controls(self): # Add the control set vbl = QVBoxLayout() self.move_element_up_tb = QToolButton() self.move_element_up_tb.setObjectName("move_element_up_tb") self.move_element_up_tb.setToolTip('Move element up') self.move_element_up_tb.setIcon(QIcon(I('arrow-up.png'))) self.move_element_up_tb.clicked.connect(self.move_row_up) vbl.addWidget(self.move_element_up_tb) self.undo_css_tb = QToolButton() self.undo_css_tb.setObjectName("undo_css_tb") self.undo_css_tb.setToolTip('Restore CSS to last saved') self.undo_css_tb.setIcon(QIcon(I('edit-undo.png'))) self.undo_css_tb.clicked.connect(partial(self.undo_reset_button_clicked, 'undo')) vbl.addWidget(self.undo_css_tb) self.reset_css_tb = QToolButton() self.reset_css_tb.setObjectName("reset_css_tb") self.reset_css_tb.setToolTip('Reset CSS to default') self.reset_css_tb.setIcon(QIcon(I('trash.png'))) self.reset_css_tb.clicked.connect(partial(self.undo_reset_button_clicked, 'reset')) vbl.addWidget(self.reset_css_tb) self.move_element_down_tb = QToolButton() self.move_element_down_tb.setObjectName("move_element_down_tb") self.move_element_down_tb.setToolTip('Move element down') self.move_element_down_tb.setIcon(QIcon(I('arrow-down.png'))) self.move_element_down_tb.clicked.connect(self.move_row_down) vbl.addWidget(self.move_element_down_tb) self.layout.addLayout(vbl)
def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('No library found')) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace('/', os.sep) self.header = QLabel( _('No existing calibre library was found at %s. ' 'If the library was moved, select its new location below. ' 'Otherwise calibre will forget this library.') % loc) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel('<br><b>' + _('New location of this library:')) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I('document_open.png'))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(QDialogButtonBox.Abort) b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole) b.setIcon(QIcon(I('ok.png'))) b = self.bb.addButton(_('Forget library'), self.bb.RejectRole) b.setIcon(QIcon(I('edit-clear.png'))) b.clicked.connect(self.forget_library) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50))
def makeControlWidgets(self, parent, gridlayout, row, column): toprow = QWidget(parent) gridlayout.addWidget(toprow, row * 2, column) top_lo = QHBoxLayout(toprow) top_lo.setContentsMargins(0, 0, 0, 0) self._wlabel = QLabel(self.format % (self.name, self.value), toprow) top_lo.addWidget(self._wlabel) self._wreset = QToolButton(toprow) self._wreset.setText("reset") self._wreset.setToolButtonStyle(Qt.ToolButtonTextOnly) self._wreset.setAutoRaise(True) self._wreset.setEnabled(self.value != self._default) QObject.connect(self._wreset, SIGNAL("clicked()"), self._resetValue) top_lo.addWidget(self._wreset) self._wslider = QwtSlider(parent) # This works around a stupid bug in QwtSliders -- see comments on histogram zoom wheel above self._wslider_timer = QTimer(parent) self._wslider_timer.setSingleShot(True) self._wslider_timer.setInterval(500) QObject.connect(self._wslider_timer, SIGNAL("timeout()"), self.setValue) gridlayout.addWidget(self._wslider, row * 2 + 1, column) self._wslider.setRange(self.minval, self.maxval) self._wslider.setStep(self.step) self._wslider.setValue(self.value) self._wslider.setTracking(False) QObject.connect(self._wslider, SIGNAL("valueChanged(double)"), self.setValue) QObject.connect(self._wslider, SIGNAL("sliderMoved(double)"), self._previewValue)
def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.create_epub = c = QCheckBox(_('Create an empty EPUB file as well')) c.setChecked(gprefs.get('create_empty_epub_file', False)) c.setToolTip(_('Also create an empty EPUB file that you can subsequently edit')) self._layout.addWidget(c, 6, 0, 1, -1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 7, 0, 1, -1) self.resize(self.sizeHint())
class SliderControl(QObject): """This class implements a slider control for a colormap""" def __init__(self, name, value, minval, maxval, step, format="%s: %.1f"): QObject.__init__(self) self.name, self.value, self.minval, self.maxval, self.step, self.format = \ name, value, minval, maxval, step, format self._default = value self._wlabel = None def makeControlWidgets(self, parent, gridlayout, row, column): toprow = QWidget(parent) gridlayout.addWidget(toprow, row * 2, column) top_lo = QHBoxLayout(toprow) top_lo.setContentsMargins(0, 0, 0, 0) self._wlabel = QLabel(self.format % (self.name, self.value), toprow) top_lo.addWidget(self._wlabel) self._wreset = QToolButton(toprow) self._wreset.setText("reset") self._wreset.setToolButtonStyle(Qt.ToolButtonTextOnly) self._wreset.setAutoRaise(True) self._wreset.setEnabled(self.value != self._default) QObject.connect(self._wreset, SIGNAL("clicked()"), self._resetValue) top_lo.addWidget(self._wreset) self._wslider = QwtSlider(parent) # This works around a stupid bug in QwtSliders -- see comments on histogram zoom wheel above self._wslider_timer = QTimer(parent) self._wslider_timer.setSingleShot(True) self._wslider_timer.setInterval(500) QObject.connect(self._wslider_timer, SIGNAL("timeout()"), self.setValue) gridlayout.addWidget(self._wslider, row * 2 + 1, column) self._wslider.setRange(self.minval, self.maxval) self._wslider.setStep(self.step) self._wslider.setValue(self.value) self._wslider.setTracking(False) QObject.connect(self._wslider, SIGNAL("valueChanged(double)"), self.setValue) QObject.connect(self._wslider, SIGNAL("sliderMoved(double)"), self._previewValue) def _resetValue(self): self._wslider.setValue(self._default) self.setValue(self._default) def setValue(self, value=None, notify=True): # only update widgets if already created self.value = value if self._wlabel is not None: if value is None: self.value = value = self._wslider.value() self._wreset.setEnabled(value != self._default) self._wlabel.setText(self.format % (self.name, self.value)) # stop timer if being called to finalize the change in value if notify: self._wslider_timer.stop() self.emit(SIGNAL("valueChanged"), self.value) def _previewValue(self, value): self.setValue(notify=False) self._wslider_timer.start(500) self.emit(SIGNAL("valueMoved"), self.value)
class MovedDialog(QDialog): # {{{ def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('No library found')) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace('/', os.sep) self.header = QLabel( _('No existing calibre library was found at %s. ' 'If the library was moved, select its new location below. ' 'Otherwise calibre will forget this library.') % loc) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel('<br><b>' + _('New location of this library:')) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I('document_open.png'))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(QDialogButtonBox.Abort) b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole) b.setIcon(QIcon(I('ok.png'))) b = self.bb.addButton(_('Forget library'), self.bb.RejectRole) b.setIcon(QIcon(I('edit-clear.png'))) b.clicked.connect(self.forget_library) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50)) def choose_dir(self): d = choose_dir(self, 'library moved choose new loc', _('New library location'), default_dir=self.oldloc) if d is not None: self.loc.setText(d) def forget_library(self): self.stats.remove(self.location) def accept(self): newloc = unicode(self.loc.text()) if not db_class.exists_at(newloc): error_dialog(self, _('No library found'), _('No existing calibre library found at %s') % newloc, show=True) return self.stats.rename(self.location, newloc) self.newloc = newloc QDialog.accept(self)
class DateEdit(QDateTimeEdit): # {{{ TOOLTIP = '' LABEL = _('&Date:') FMT = 'dd MMM yyyy hh:mm:ss' ATTR = 'timestamp' TWEAK = 'gui_timestamp_display_format' def __init__(self, parent): QDateTimeEdit.__init__(self, parent) self.setToolTip(self.TOOLTIP) self.setWhatsThis(self.TOOLTIP) fmt = tweaks[self.TWEAK] if fmt is None: fmt = self.FMT self.setDisplayFormat(fmt) self.setCalendarPopup(True) self.setMinimumDateTime(UNDEFINED_QDATETIME) self.setSpecialValueText(_('Undefined')) self.clear_button = QToolButton(parent) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Clear date')) self.clear_button.clicked.connect(self.reset_date) def reset_date(self, *args): self.current_val = None @dynamic_property def current_val(self): def fget(self): return qt_to_dt(self.dateTime(), as_utc=False) def fset(self, val): if val is None: val = UNDEFINED_DATE else: val = as_local_time(val) self.setDateTime(val) return property(fget=fget, fset=fset) def initialize(self, db, id_): self.current_val = getattr(db, self.ATTR)(id_, index_is_id=True) self.original_val = self.current_val def commit(self, db, id_): if self.changed: getattr(db, 'set_' + self.ATTR)(id_, self.current_val, commit=False, notify=False) return True @property def changed(self): o, c = self.original_val, self.current_val return o != c
def __init__(self, *args): QToolButton.__init__(self, *args) self.animation = QPropertyAnimation(self, 'iconSize', self) self.animation.setDuration(60/72.*1000) self.animation.setLoopCount(4) self.normal_icon_size = QSize(64, 64) self.animation.valueChanged.connect(self.value_changed) self.setCursor(Qt.PointingHandCursor) self.animation.finished.connect(self.animation_finished)
def __init__(self, *args): QToolButton.__init__(self, *args) self.animation = QPropertyAnimation(self, 'iconSize', self) self.animation.setDuration(60 / 72. * 1000) self.animation.setLoopCount(4) self.normal_icon_size = QSize(64, 64) self.animation.valueChanged.connect(self.value_changed) self.setCursor(Qt.PointingHandCursor) self.animation.finished.connect(self.animation_finished)
class DateEdit(QDateTimeEdit): TOOLTIP = '' LABEL = _('&Date:') FMT = 'dd MMM yyyy hh:mm:ss' ATTR = 'timestamp' TWEAK = 'gui_timestamp_display_format' def __init__(self, parent): QDateTimeEdit.__init__(self, parent) self.setToolTip(self.TOOLTIP) self.setWhatsThis(self.TOOLTIP) fmt = tweaks[self.TWEAK] if fmt is None: fmt = self.FMT self.setDisplayFormat(fmt) self.setCalendarPopup(True) self.cw = CalendarWidget(self) self.cw.setVerticalHeaderFormat(self.cw.NoVerticalHeader) self.setCalendarWidget(self.cw) self.setMinimumDateTime(UNDEFINED_QDATETIME) self.setSpecialValueText(_('Undefined')) self.clear_button = QToolButton(parent) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Clear date')) self.clear_button.clicked.connect(self.reset_date) def reset_date(self, *args): self.current_val = None @dynamic_property def current_val(self): def fget(self): return qt_to_dt(self.dateTime(), as_utc=False) def fset(self, val): if val is None: val = UNDEFINED_DATE else: val = as_local_time(val) self.setDateTime(val) return property(fget=fget, fset=fset) def initialize(self, db, id_): self.current_val = getattr(db, self.ATTR)(id_, index_is_id=True) self.original_val = self.current_val def commit(self, db, id_): if self.changed: getattr(db, 'set_'+self.ATTR)(id_, self.current_val, commit=False, notify=False) return True @property def changed(self): o, c = self.original_val, self.current_val return o != c
def create_color_button(key, text): b = ColorButton(data, key, text, self) b.changed.connect(self.changed), l.addWidget(b) bc = QToolButton(self) bc.setIcon(QIcon(I('clear_left.png'))) bc.setToolTip(_('Remove color')) bc.clicked.connect(b.clear) h = QHBoxLayout() h.addWidget(b), h.addWidget(bc) return h
def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box) self.resize(self.sizeHint())
class MovedDialog(QDialog): # {{{ def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_("No library found")) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace("/", os.sep) self.header = QLabel( _( "No existing calibre library was found at %s. " "If the library was moved, select its new location below. " "Otherwise calibre will forget this library." ) % loc ) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel("<br><b>" + _("New location of this library:")) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I("document_open.png"))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(QDialogButtonBox.Abort) b = self.bb.addButton(_("Library moved"), self.bb.AcceptRole) b.setIcon(QIcon(I("ok.png"))) b = self.bb.addButton(_("Forget library"), self.bb.RejectRole) b.setIcon(QIcon(I("edit-clear.png"))) b.clicked.connect(self.forget_library) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50)) def choose_dir(self): d = choose_dir(self, "library moved choose new loc", _("New library location"), default_dir=self.oldloc) if d is not None: self.loc.setText(d) def forget_library(self): self.stats.remove(self.location) def accept(self): newloc = unicode(self.loc.text()) if not db_class.exists_at(newloc): error_dialog(self, _("No library found"), _("No existing calibre library found at %s") % newloc, show=True) return self.stats.rename(self.location, newloc) self.newloc = newloc QDialog.accept(self)
class MovedDialog(QDialog): # {{{ def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('No library found')) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace('/', os.sep) self.header = QLabel(_('No existing calibre library was found at %s. ' 'If the library was moved, select its new location below. ' 'Otherwise calibre will forget this library.')%loc) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel('<br><b>'+_('New location of this library:')) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I('document_open.png'))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(self) b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole) b.setIcon(QIcon(I('ok.png'))) b = self.bb.addButton(_('Forget library'), self.bb.RejectRole) b.setIcon(QIcon(I('edit-clear.png'))) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50)) def choose_dir(self): d = choose_dir(self, 'library moved choose new loc', _('New library location'), default_dir=self.oldloc) if d is not None: self.loc.setText(d) def reject(self): self.stats.remove(self.location) QDialog.reject(self) def accept(self): newloc = unicode(self.loc.text()) if not LibraryDatabase2.exists_at(newloc): error_dialog(self, _('No library found'), _('No existing calibre library found at %s')%newloc, show=True) return self.stats.rename(self.location, newloc) self.newloc = newloc QDialog.accept(self)
def __init__(self, current_family, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose font family')) self.setWindowIcon(QIcon(I('font.png'))) from calibre.utils.fonts.scanner import font_scanner self.font_scanner = font_scanner self.m = QStringListModel(self) self.build_font_list() self.l = l = QGridLayout() self.setLayout(l) self.view = FontsView(self) self.view.setModel(self.m) self.view.setCurrentIndex(self.m.index(0)) if current_family: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(current_family): self.view.setCurrentIndex(self.m.index(i)) break self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection) self.view.changed.connect(self.current_changed, type=Qt.QueuedConnection) self.faces = Typefaces(self) self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.add_fonts_button = afb = self.bb.addButton( _('Add &fonts'), self.bb.ActionRole) afb.setIcon(QIcon(I('plus.png'))) afb.clicked.connect(self.add_fonts) self.ml = QLabel(_('Choose a font family from the list below:')) self.search = QLineEdit(self) self.search.setPlaceholderText(_('Search')) self.search.returnPressed.connect(self.find) self.nb = QToolButton(self) self.nb.setIcon(QIcon(I('arrow-down.png'))) self.nb.setToolTip(_('Find Next')) self.pb = QToolButton(self) self.pb.setIcon(QIcon(I('arrow-up.png'))) self.pb.setToolTip(_('Find Previous')) self.nb.clicked.connect(self.find_next) self.pb.clicked.connect(self.find_previous) l.addWidget(self.ml, 0, 0, 1, 4) l.addWidget(self.search, 1, 0, 1, 1) l.addWidget(self.nb, 1, 1, 1, 1) l.addWidget(self.pb, 1, 2, 1, 1) l.addWidget(self.view, 2, 0, 1, 3) l.addWidget(self.faces, 1, 3, 2, 1) l.addWidget(self.bb, 3, 0, 1, 4) l.setAlignment(self.faces, Qt.AlignTop) self.resize(800, 600)
def __init__(self, current_family, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose font family')) self.setWindowIcon(QIcon(I('font.png'))) from calibre.utils.fonts.scanner import font_scanner self.font_scanner = font_scanner self.m = QStringListModel(self) self.build_font_list() self.l = l = QGridLayout() self.setLayout(l) self.view = FontsView(self) self.view.setModel(self.m) self.view.setCurrentIndex(self.m.index(0)) if current_family: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(current_family): self.view.setCurrentIndex(self.m.index(i)) break self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection) self.view.changed.connect(self.current_changed, type=Qt.QueuedConnection) self.faces = Typefaces(self) self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.add_fonts_button = afb = self.bb.addButton(_('Add &fonts'), self.bb.ActionRole) afb.setIcon(QIcon(I('plus.png'))) afb.clicked.connect(self.add_fonts) self.ml = QLabel(_('Choose a font family from the list below:')) self.search = QLineEdit(self) self.search.setPlaceholderText(_('Search')) self.search.returnPressed.connect(self.find) self.nb = QToolButton(self) self.nb.setIcon(QIcon(I('arrow-down.png'))) self.nb.setToolTip(_('Find Next')) self.pb = QToolButton(self) self.pb.setIcon(QIcon(I('arrow-up.png'))) self.pb.setToolTip(_('Find Previous')) self.nb.clicked.connect(self.find_next) self.pb.clicked.connect(self.find_previous) l.addWidget(self.ml, 0, 0, 1, 4) l.addWidget(self.search, 1, 0, 1, 1) l.addWidget(self.nb, 1, 1, 1, 1) l.addWidget(self.pb, 1, 2, 1, 1) l.addWidget(self.view, 2, 0, 1, 3) l.addWidget(self.faces, 1, 3, 2, 1) l.addWidget(self.bb, 3, 0, 1, 4) l.setAlignment(self.faces, Qt.AlignTop) self.resize(800, 600)
def __init__(self, icon, text, splitter, parent=None, shortcut=None): QToolButton.__init__(self, parent) self.label = text self.setIcon(QIcon(icon)) self.setCheckable(True) self.splitter = splitter splitter.state_changed.connect(self.update_state) self.setCursor(Qt.PointingHandCursor) self.shortcut = '' if shortcut: self.shortcut = shortcut
def __init__(self, parent): QWidget.__init__(self, parent) layout = QHBoxLayout() layout.setSpacing(5) layout.setContentsMargins(0, 0, 0, 0) self.tags_box = EditWithComplete(parent) layout.addWidget(self.tags_box, stretch=1000) self.editor_button = QToolButton(self) self.editor_button.setToolTip(_('Open Item Editor')) self.editor_button.setIcon(QIcon(I('chapters.png'))) layout.addWidget(self.editor_button) self.setLayout(layout)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel('<p>'+_( 'You can control the color of columns in the' ' book list by creating "rules" that tell calibre' ' what color to use. Click the Add Rule button below' ' to get started.<p>You can <b>change an existing rule</b> by double' ' clicking it.')) l1.setWordWrap(True) l.addWidget(l1, 0, 0, 1, 2) self.add_button = QPushButton(QIcon(I('plus.png')), _('Add Rule'), self) self.remove_button = QPushButton(QIcon(I('minus.png')), _('Remove Rule'), self) self.add_button.clicked.connect(self.add_rule) self.remove_button.clicked.connect(self.remove_rule) l.addWidget(self.add_button, 1, 0) l.addWidget(self.remove_button, 1, 1) self.g = g = QGridLayout() self.rules_view = QListView(self) self.rules_view.doubleClicked.connect(self.edit_rule) self.rules_view.setSelectionMode(self.rules_view.SingleSelection) self.rules_view.setAlternatingRowColors(True) self.rtfd = RichTextDelegate(parent=self.rules_view, max_width=400) self.rules_view.setItemDelegate(self.rtfd) g.addWidget(self.rules_view, 0, 0, 2, 1) self.up_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) b.setToolTip(_('Move the selected rule up')) b.clicked.connect(self.move_up) g.addWidget(b, 0, 1, 1, 1, Qt.AlignTop) self.down_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.setToolTip(_('Move the selected rule down')) b.clicked.connect(self.move_down) g.addWidget(b, 1, 1, 1, 1, Qt.AlignBottom) l.addLayout(g, 2, 0, 1, 2) l.setRowStretch(2, 10) self.add_advanced_button = b = QPushButton(QIcon(I('plus.png')), _('Add Advanced Rule'), self) b.clicked.connect(self.add_advanced) l.addWidget(b, 3, 0, 1, 2)
def __init__(self, parent, copy_fmt): QWidget.__init__(self, parent) self.dialog = parent self.copy_fmt = copy_fmt self.changed = False self.l = l = QGridLayout() self.setLayout(l) self.cover_from_format_button = QToolButton(self) self.cover_from_format_button.setToolTip( _('Set the cover for the book from the selected format')) self.cover_from_format_button.setIcon(QIcon(I('book.png'))) self.cover_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button = QToolButton(self) self.metadata_from_format_button.setIcon(QIcon(I('edit_input.png'))) self.metadata_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button.setToolTip( _('Set metadata for the book from the selected format')) self.add_format_button = QToolButton(self) self.add_format_button.setIcon(QIcon(I('add_book.png'))) self.add_format_button.setIconSize(QSize(32, 32)) self.add_format_button.clicked.connect(self.add_format) self.add_format_button.setToolTip( _('Add a format to this book')) self.remove_format_button = QToolButton(self) self.remove_format_button.setIcon(QIcon(I('trash.png'))) self.remove_format_button.setIconSize(QSize(32, 32)) self.remove_format_button.clicked.connect(self.remove_format) self.remove_format_button.setToolTip( _('Remove the selected format from this book')) self.formats = FormatList(self) self.formats.setAcceptDrops(True) self.formats.formats_dropped.connect(self.formats_dropped) self.formats.restore_fmt.connect(self.restore_fmt) self.formats.delete_format.connect(self.remove_format) self.formats.itemDoubleClicked.connect(self.show_format) self.formats.setDragDropMode(self.formats.DropOnly) self.formats.setIconSize(QSize(32, 32)) self.formats.setMaximumWidth(200) l.addWidget(self.cover_from_format_button, 0, 0, 1, 1) l.addWidget(self.metadata_from_format_button, 2, 0, 1, 1) l.addWidget(self.add_format_button, 0, 2, 1, 1) l.addWidget(self.remove_format_button, 2, 2, 1, 1) l.addWidget(self.formats, 0, 1, 3, 1) self.temp_files = []
def __init__(self, layer, rawLayer, linkedCanvas, dock): # Canvas params QgsMapCanvas.__init__(self, dock) self.setCanvasColor(Qt.white) self.setWheelAction(QgsMapCanvas.WheelZoom, factor=0) self._dock = dock # Add buttons buttonWidth = self.width() / 2.5 self._buttonUp = QToolButton(self) self._buttonUp.setArrowType(Qt.UpArrow) self._buttonUp.setMaximumWidth(buttonWidth) self._buttonUp.setVisible(False) self._buttonUp.connect(self._buttonUp, SIGNAL("clicked()"), self.moveUp) self._buttonHide = QPushButton("Hide") self._buttonHide.setMaximumWidth(buttonWidth) self._buttonHide.setVisible(False) self._buttonHide.setFocusPolicy(Qt.NoFocus) self._buttonHide.connect(self._buttonHide, SIGNAL("clicked()"), self.toggleLayer) self._buttonDown = QToolButton(self) self._buttonDown.setArrowType(Qt.DownArrow) self._buttonDown.setMaximumWidth(buttonWidth) self._buttonDown.setVisible(False) self._buttonDown.connect(self._buttonDown, SIGNAL("clicked()"), self.moveDown) self._layout = QVBoxLayout(self) self._layout.setMargin(1) self._layout.addWidget(self._buttonUp) self._layout.addWidget(self._buttonHide) self._layout.addWidget(self._buttonDown) self._rawLayer = rawLayer self._layer = layer self.setLayerSet([layer]) self._linkedCanvas = linkedCanvas self._extent = self._linkedCanvas.extent() self.setExtent(self._extent) self.setFocusPolicy(Qt.StrongFocus) self._hidden = False
def _init_controls(self): # Add the control set vbl = QVBoxLayout() self.move_element_up_tb = QToolButton() self.move_element_up_tb.setObjectName("move_element_up_tb") self.move_element_up_tb.setToolTip('Move element up') self.move_element_up_tb.setIcon(QIcon(I('arrow-up.png'))) self.move_element_up_tb.clicked.connect(self.move_row_up) vbl.addWidget(self.move_element_up_tb) self.undo_css_tb = QToolButton() self.undo_css_tb.setObjectName("undo_css_tb") self.undo_css_tb.setToolTip('Restore CSS to last saved') self.undo_css_tb.setIcon(QIcon(I('edit-undo.png'))) self.undo_css_tb.clicked.connect( partial(self.undo_reset_button_clicked, 'undo')) vbl.addWidget(self.undo_css_tb) self.reset_css_tb = QToolButton() self.reset_css_tb.setObjectName("reset_css_tb") self.reset_css_tb.setToolTip('Reset CSS to default') self.reset_css_tb.setIcon(QIcon(I('trash.png'))) self.reset_css_tb.clicked.connect( partial(self.undo_reset_button_clicked, 'reset')) vbl.addWidget(self.reset_css_tb) self.move_element_down_tb = QToolButton() self.move_element_down_tb.setObjectName("move_element_down_tb") self.move_element_down_tb.setToolTip('Move element down') self.move_element_down_tb.setIcon(QIcon(I('arrow-down.png'))) self.move_element_down_tb.clicked.connect(self.move_row_down) vbl.addWidget(self.move_element_down_tb) self.layout.addLayout(vbl)
def makeButton(self, label, callback=None, width=None, icon=None): btn = QToolButton(self) # btn.setAutoRaise(True) label and btn.setText(label) icon and btn.setIcon(icon) # btn = QPushButton(label,self) # btn.setFlat(True) if width: btn.setMinimumWidth(width) btn.setMaximumWidth(width) if icon: btn.setIcon(icon) if callback: QObject.connect(btn, SIGNAL("clicked()"), callback) return btn
def __init__(self, parent): QDateTimeEdit.__init__(self, parent) self.setToolTip(self.TOOLTIP) self.setWhatsThis(self.TOOLTIP) fmt = tweaks[self.TWEAK] if fmt is None: fmt = self.FMT self.setDisplayFormat(fmt) self.setCalendarPopup(True) self.setMinimumDateTime(UNDEFINED_QDATETIME) self.setSpecialValueText(_('Undefined')) self.clear_button = QToolButton(parent) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Clear date')) self.clear_button.clicked.connect(self.reset_date)
class MultipleWidget(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) layout = QHBoxLayout() layout.setSpacing(5) layout.setContentsMargins(0, 0, 0, 0) self.tags_box = EditWithComplete(parent) layout.addWidget(self.tags_box, stretch=1000) self.editor_button = QToolButton(self) self.editor_button.setToolTip(_('Open Item Editor')) self.editor_button.setIcon(QIcon(I('chapters.png'))) layout.addWidget(self.editor_button) self.setLayout(layout) def get_editor_button(self): return self.editor_button def update_items_cache(self, values): self.tags_box.update_items_cache(values) def clear(self): self.tags_box.clear() def setEditText(self): self.tags_box.setEditText() def addItem(self, itm): self.tags_box.addItem(itm) def set_separator(self, sep): self.tags_box.set_separator(sep) def set_add_separator(self, sep): self.tags_box.set_add_separator(sep) def set_space_before_sep(self, v): self.tags_box.set_space_before_sep(v) def setSizePolicy(self, v1, v2): self.tags_box.setSizePolicy(v1, v2) def setText(self, v): self.tags_box.setText(v) def text(self): return self.tags_box.text()
def __init__(self, parent): super(ChooseLibrary, self).__init__(parent) d = self d.l = l = QGridLayout() d.setLayout(l) d.setWindowTitle(_('Choose library')) la = d.la = QLabel(_('Library &path:')) l.addWidget(la, 0, 0) le = d.le = HistoryLineEdit(d) le.initialize('choose_library_for_copy') l.addWidget(le, 0, 1) la.setBuddy(le) b = d.b = QToolButton(d) b.setIcon(QIcon(I('document_open.png'))) b.setToolTip(_('Browse for library')) b.clicked.connect(self.browse) l.addWidget(b, 0, 2) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.delete_after_copy = False b = bb.addButton(_('&Copy'), bb.AcceptRole) b.setIcon(QIcon(I('edit-copy.png'))) b.setToolTip(_('Copy to the specified library')) b2 = bb.addButton(_('&Move'), bb.AcceptRole) b2.clicked.connect(lambda: setattr(self, 'delete_after_copy', True)) b2.setIcon(QIcon(I('edit-cut.png'))) b2.setToolTip(_('Copy to the specified library and delete from the current library')) b.setDefault(True) l.addWidget(bb, 1, 0, 1, 3) le.setMinimumWidth(350) self.resize(self.sizeHint())
def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('No library found')) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace('/', os.sep) self.header = QLabel(_('No existing calibre library was found at %s. ' 'If the library was moved, select its new location below. ' 'Otherwise calibre will forget this library.')%loc) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel('<br><b>'+_('New location of this library:')) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I('document_open.png'))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(QDialogButtonBox.Abort) b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole) b.setIcon(QIcon(I('ok.png'))) b = self.bb.addButton(_('Forget library'), self.bb.RejectRole) b.setIcon(QIcon(I('edit-clear.png'))) b.clicked.connect(self.forget_library) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50))
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel('') l1.setWordWrap(True) l.addWidget(l1, 0, 0, 1, 2) self.add_button = QPushButton(QIcon(I('plus.png')), _('Add Rule'), self) self.remove_button = QPushButton(QIcon(I('minus.png')), _('Remove Rule'), self) self.add_button.clicked.connect(self.add_rule) self.remove_button.clicked.connect(self.remove_rule) l.addWidget(self.add_button, 1, 0) l.addWidget(self.remove_button, 1, 1) self.g = g = QGridLayout() self.rules_view = QListView(self) self.rules_view.doubleClicked.connect(self.edit_rule) self.rules_view.setSelectionMode(self.rules_view.SingleSelection) self.rules_view.setAlternatingRowColors(True) self.rtfd = RichTextDelegate(parent=self.rules_view, max_width=400) self.rules_view.setItemDelegate(self.rtfd) g.addWidget(self.rules_view, 0, 0, 2, 1) self.up_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) b.setToolTip(_('Move the selected rule up')) b.clicked.connect(self.move_up) g.addWidget(b, 0, 1, 1, 1, Qt.AlignTop) self.down_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.setToolTip(_('Move the selected rule down')) b.clicked.connect(self.move_down) g.addWidget(b, 1, 1, 1, 1, Qt.AlignBottom) l.addLayout(g, 2, 0, 1, 2) l.setRowStretch(2, 10) self.add_advanced_button = b = QPushButton(QIcon(I('plus.png')), _('Add Advanced Rule'), self) b.clicked.connect(self.add_advanced) l.addWidget(b, 3, 0, 1, 2)
class FontFamilyChooser(QWidget): family_changed = pyqtSignal(object) def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QHBoxLayout() l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) self.button = QPushButton(self) self.button.setIcon(QIcon(I('font.png'))) self.button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) l.addWidget(self.button) self.default_text = _('Choose &font family') self.font_family = None self.button.clicked.connect(self.show_chooser) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('clear_left.png'))) self.clear_button.clicked.connect(self.clear_family) l.addWidget(self.clear_button) self.setToolTip = self.button.setToolTip self.toolTip = self.button.toolTip self.clear_button.setToolTip(_('Clear the font family')) l.addStretch(1) def clear_family(self): self.font_family = None @dynamic_property def font_family(self): def fget(self): return self._current_family def fset(self, val): if not val: val = None self._current_family = val self.button.setText(val or self.default_text) self.family_changed.emit(val) return property(fget=fget, fset=fset) def show_chooser(self): d = FontFamilyDialog(self.font_family, self) if d.exec_() == d.Accepted: self.font_family = d.font_family
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QHBoxLayout() self.setLayout(l) self.button = QPushButton(self) self.button.setIcon(QIcon(I('font.png'))) l.addWidget(self.button) self.default_text = _('Choose &font family') self.font_family = None self.button.clicked.connect(self.show_chooser) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('clear_left.png'))) self.clear_button.clicked.connect(self.clear_family) l.addWidget(self.clear_button) self.setToolTip = self.button.setToolTip self.toolTip = self.button.toolTip self.clear_button.setToolTip(_('Clear the font family'))
def setup_ui(self): self.l = l = QGridLayout(self) self.setLayout(l) self.la1 = la = QLabel(_('&Existing images in the book')) la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) l.addWidget(la, 0, 0, 1, 2) if self.for_browsing: la.setVisible(False) self.view = v = QListView(self) v.setViewMode(v.IconMode) v.setFlow(v.LeftToRight) v.setSpacing(4) v.setResizeMode(v.Adjust) v.setUniformItemSizes(True) pi = plugins['progress_indicator'][0] if hasattr(pi, 'set_no_activate_on_click'): pi.set_no_activate_on_click(v) v.activated.connect(self.activated) v.doubleClicked.connect(self.activated) self.d = ImageDelegate(v) v.setItemDelegate(self.d) self.model = Images(self.view) self.fm = fm = QSortFilterProxyModel(self.view) self.fm.setDynamicSortFilter(self.for_browsing) fm.setSourceModel(self.model) fm.setFilterCaseSensitivity(False) v.setModel(fm) l.addWidget(v, 1, 0, 1, 2) v.pressed.connect(self.pressed) la.setBuddy(v) self.filter = f = QLineEdit(self) f.setPlaceholderText(_('Search for image by file name')) l.addWidget(f, 2, 0) self.cb = b = QToolButton(self) b.setIcon(QIcon(I('clear_left.png'))) b.clicked.connect(f.clear) l.addWidget(b, 2, 1) f.textChanged.connect(self.filter_changed) l.addWidget(self.bb, 3, 0, 1, 2) if self.for_browsing: self.bb.clear() self.bb.addButton(self.bb.Close) b = self.refresh_button = self.bb.addButton( _('&Refresh'), self.bb.ActionRole) b.clicked.connect(self.refresh) b.setIcon(QIcon(I('view-refresh.png'))) b.setToolTip(_('Refresh the displayed images')) self.setAttribute(Qt.WA_DeleteOnClose, False) else: b = self.import_button = self.bb.addButton(_('&Import image'), self.bb.ActionRole) b.clicked.connect(self.import_image) b.setIcon(QIcon(I('view-image.png'))) b.setToolTip(_('Import an image from elsewhere in your computer'))
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)
def setup_ui(self): self.l = l = QGridLayout(self) self.setLayout(l) self.bb.setStandardButtons(self.bb.Close) self.rearrange_button = b = self.bb.addButton( _('Re-arrange favorites'), self.bb.ActionRole) b.setCheckable(True) b.setChecked(False) b.setVisible(False) b.setDefault(True) self.splitter = s = QSplitter(self) s.setChildrenCollapsible(False) self.search = h = HistoryLineEdit2(self) h.setToolTip( textwrap.fill( _('Search for unicode characters by using the English names or nicknames.' ' You can also search directly using a character code. For example, the following' ' searches will all yield the no-break space character: U+A0, nbsp, no-break' ))) h.initialize('charmap_search') h.setPlaceholderText(_('Search by name, nickname or character code')) self.search_button = b = QPushButton(_('&Search')) h.returnPressed.connect(self.do_search) b.clicked.connect(self.do_search) self.clear_button = cb = QToolButton(self) cb.setIcon(QIcon(I('clear_left.png'))) cb.setText(_('Clear search')) cb.clicked.connect(self.clear_search) l.addWidget(h), l.addWidget(b, 0, 1), l.addWidget(cb, 0, 2) self.category_view = CategoryView(self) l.addWidget(s, 1, 0, 1, 3) self.char_view = CharView(self) self.rearrange_button.toggled[bool].connect( self.set_allow_drag_and_drop) self.category_view.category_selected.connect(self.show_chars) self.char_view.show_name.connect(self.show_char_info) self.char_view.char_selected.connect(self.char_selected) s.addWidget(self.category_view), s.addWidget(self.char_view) self.char_info = la = QLabel('\xa0') la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) l.addWidget(la, 2, 0, 1, 3) self.rearrange_msg = la = QLabel( _('Drag and drop characters to re-arrange them. Click the re-arrange button again when you are done.' )) la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) la.setVisible(False) l.addWidget(la, 3, 0, 1, 3) l.addWidget(self.bb, 4, 0, 1, 3) self.char_view.setFocus(Qt.OtherFocusReason)
def __init__(self, parent=None): QDialog.__init__(self, parent=parent) self.l = l = QFormLayout(self) self.setLayout(l) self.setWindowTitle(_('Import OPML file')) self.setWindowIcon(QIcon(I('opml.png'))) self.h = h = QHBoxLayout() self.path = p = QLineEdit(self) p.setMinimumWidth(300) p.setPlaceholderText(_('Path to OPML file')) h.addWidget(p) self.cfb = b = QToolButton(self) b.setIcon(QIcon(I('document_open.png'))) b.setToolTip(_('Browse for OPML file')) b.clicked.connect(self.choose_file) h.addWidget(b) l.addRow(_('&OPML file:'), h) l.labelForField(h).setBuddy(p) b.setFocus(Qt.OtherFocusReason) self._articles_per_feed = a = QSpinBox(self) a.setMinimum(1), a.setMaximum(1000), a.setValue(100) a.setToolTip(_('Maximum number of articles to download per RSS feed')) l.addRow(_('&Maximum articles per feed:'), a) self._oldest_article = o = QSpinBox(self) o.setMinimum(1), o.setMaximum(3650), o.setValue(7) o.setSuffix(_(' days')) o.setToolTip( _('Articles in the RSS feeds older than this will be ignored')) l.addRow(_('&Oldest article:'), o) self.preserve_groups = g = QCheckBox( _('Preserve groups in the OPML file')) g.setToolTip('<p>' + _( 'If enabled, every group of feeds in the OPML file will be converted into a single recipe. Otherwise every feed becomes its own recipe' )) g.setChecked(True) l.addRow(g) self._replace_existing = r = QCheckBox(_('Replace existing recipes')) r.setToolTip('<p>' + _( 'If enabled, any existing recipes with the same titles as entries in the OPML file will be replaced.' ' Otherwise, new entries with modified titles will be created')) r.setChecked(True) l.addRow(r) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept), bb.rejected.connect(self.reject) l.addRow(bb) self.recipes = ()
def __init__(self, win): QStatusBar.__init__(self, win) self.statusMsgLabel = QLabel() self.statusMsgLabel.setMinimumWidth(200) self.statusMsgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.addPermanentWidget(self.statusMsgLabel) self.progressBar = QProgressBar(win) self.progressBar.setMaximumWidth(250) qt4todo('StatusBar.progressBar.setCenterIndicator(True)') self.addPermanentWidget(self.progressBar) self.progressBar.hide() self.simAbortButton = QToolButton(win) self.simAbortButton.setIcon( geticon("ui/actions/Simulation/Stopsign.png")) self.simAbortButton.setMaximumWidth(32) self.addPermanentWidget(self.simAbortButton) self.connect(self.simAbortButton, SIGNAL("clicked()"), self.simAbort) self.simAbortButton.hide() self.dispbarLabel = QLabel(win) #self.dispbarLabel.setFrameStyle( QFrame.Panel | QFrame.Sunken ) self.dispbarLabel.setText("Global display style:") self.addPermanentWidget(self.dispbarLabel) # Global display styles combobox self.globalDisplayStylesComboBox = GlobalDisplayStylesComboBox(win) self.addPermanentWidget(self.globalDisplayStylesComboBox) # Selection lock button. It always displays the selection lock state # and it is available to click. self.selectionLockButton = QToolButton(win) self.selectionLockButton.setDefaultAction(win.selectLockAction) self.addPermanentWidget(self.selectionLockButton) # Only use of this appears to be commented out in MWsemantics as of 2007/12/14 self.modebarLabel = QLabel(win) self.addPermanentWidget(self.modebarLabel) self.abortableCommands = {}
def __init__(self, parent, copy_fmt): QWidget.__init__(self, parent) self.dialog = parent self.copy_fmt = copy_fmt self.changed = False self.l = l = QGridLayout() self.setLayout(l) self.cover_from_format_button = QToolButton(self) self.cover_from_format_button.setToolTip( _('Set the cover for the book from the selected format')) self.cover_from_format_button.setIcon(QIcon(I('book.png'))) self.cover_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button = QToolButton(self) self.metadata_from_format_button.setIcon(QIcon(I('edit_input.png'))) self.metadata_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button.setToolTip( _('Set metadata for the book from the selected format')) self.add_format_button = QToolButton(self) self.add_format_button.setIcon(QIcon(I('add_book.png'))) self.add_format_button.setIconSize(QSize(32, 32)) self.add_format_button.clicked.connect(self.add_format) self.add_format_button.setToolTip(_('Add a format to this book')) self.remove_format_button = QToolButton(self) self.remove_format_button.setIcon(QIcon(I('trash.png'))) self.remove_format_button.setIconSize(QSize(32, 32)) self.remove_format_button.clicked.connect(self.remove_format) self.remove_format_button.setToolTip( _('Remove the selected format from this book')) self.formats = FormatList(self) self.formats.setAcceptDrops(True) self.formats.formats_dropped.connect(self.formats_dropped) self.formats.restore_fmt.connect(self.restore_fmt) self.formats.delete_format.connect(self.remove_format) self.formats.itemDoubleClicked.connect(self.show_format) self.formats.setDragDropMode(self.formats.DropOnly) self.formats.setIconSize(QSize(32, 32)) self.formats.setMaximumWidth(200) l.addWidget(self.cover_from_format_button, 0, 0, 1, 1) l.addWidget(self.metadata_from_format_button, 2, 0, 1, 1) l.addWidget(self.add_format_button, 0, 2, 1, 1) l.addWidget(self.remove_format_button, 2, 2, 1, 1) l.addWidget(self.formats, 0, 1, 3, 1) self.temp_files = []
def __init__(self, win): QStatusBar.__init__(self, win) self.statusMsgLabel = QLabel() self.statusMsgLabel.setMinimumWidth(200) self.statusMsgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.addPermanentWidget(self.statusMsgLabel) self.progressBar = QProgressBar(win) self.progressBar.setMaximumWidth(250) qt4todo("StatusBar.progressBar.setCenterIndicator(True)") self.addPermanentWidget(self.progressBar) self.progressBar.hide() self.simAbortButton = QToolButton(win) self.simAbortButton.setIcon(geticon("ui/actions/Simulation/Stopsign.png")) self.simAbortButton.setMaximumWidth(32) self.addPermanentWidget(self.simAbortButton) self.connect(self.simAbortButton, SIGNAL("clicked()"), self.simAbort) self.simAbortButton.hide() self.dispbarLabel = QLabel(win) # self.dispbarLabel.setFrameStyle( QFrame.Panel | QFrame.Sunken ) self.dispbarLabel.setText("Global display style:") self.addPermanentWidget(self.dispbarLabel) # Global display styles combobox self.globalDisplayStylesComboBox = GlobalDisplayStylesComboBox(win) self.addPermanentWidget(self.globalDisplayStylesComboBox) # Selection lock button. It always displays the selection lock state # and it is available to click. self.selectionLockButton = QToolButton(win) self.selectionLockButton.setDefaultAction(win.selectLockAction) self.addPermanentWidget(self.selectionLockButton) # Only use of this appears to be commented out in MWsemantics as of 2007/12/14 self.modebarLabel = QLabel(win) self.addPermanentWidget(self.modebarLabel) self.abortableCommands = {}
def _createSponsorButton(self): """ Creates the Property Manager sponsor button, which contains a QPushButton inside of a QGridLayout inside of a QFrame. The sponsor logo image is not loaded here. """ # Sponsor button (inside a frame) self.sponsorButtonContainer = QWidget(self) SponsorFrameGrid = QGridLayout(self.sponsorButtonContainer) SponsorFrameGrid.setMargin(PM_SPONSOR_FRAME_MARGIN) SponsorFrameGrid.setSpacing(PM_SPONSOR_FRAME_SPACING) # Has no effect. self.sponsor_btn = QToolButton(self.sponsorButtonContainer) self.sponsor_btn.setAutoRaise(True) self.connect(self.sponsor_btn, SIGNAL("clicked()"), self.open_sponsor_homepage) SponsorFrameGrid.addWidget(self.sponsor_btn, 0, 0, 1, 1) self.vBoxLayout.addWidget(self.sponsorButtonContainer) button_whatsthis_widget = self.sponsor_btn #bruce 070615 bugfix -- put tooltip & whatsthis on self.sponsor_btn, # not self. # [self.sponsorButtonContainer might be another possible place to put them.] button_whatsthis_widget.setWhatsThis("""<b>Sponsor Button</b> <p>When clicked, this sponsor logo will display a short description about a NanoEngineer-1 sponsor. This can be an official sponsor or credit given to a contributor that has helped code part or all of this command. A link is provided in the description to learn more about this sponsor.</p>""") button_whatsthis_widget.setToolTip("NanoEngineer-1 Sponsor Button") return
def __init__(self, parent, db, author): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box) self.resize(self.sizeHint())
class FormatsManager(QWidget): def __init__(self, parent, copy_fmt): QWidget.__init__(self, parent) self.dialog = parent self.copy_fmt = copy_fmt self.changed = False self.l = l = QGridLayout() self.setLayout(l) self.cover_from_format_button = QToolButton(self) self.cover_from_format_button.setToolTip( _('Set the cover for the book from the selected format')) self.cover_from_format_button.setIcon(QIcon(I('book.png'))) self.cover_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button = QToolButton(self) self.metadata_from_format_button.setIcon(QIcon(I('edit_input.png'))) self.metadata_from_format_button.setIconSize(QSize(32, 32)) self.metadata_from_format_button.setToolTip( _('Set metadata for the book from the selected format')) self.add_format_button = QToolButton(self) self.add_format_button.setIcon(QIcon(I('add_book.png'))) self.add_format_button.setIconSize(QSize(32, 32)) self.add_format_button.clicked.connect(self.add_format) self.add_format_button.setToolTip( _('Add a format to this book')) self.remove_format_button = QToolButton(self) self.remove_format_button.setIcon(QIcon(I('trash.png'))) self.remove_format_button.setIconSize(QSize(32, 32)) self.remove_format_button.clicked.connect(self.remove_format) self.remove_format_button.setToolTip( _('Remove the selected format from this book')) self.formats = FormatList(self) self.formats.setAcceptDrops(True) self.formats.formats_dropped.connect(self.formats_dropped) self.formats.restore_fmt.connect(self.restore_fmt) self.formats.delete_format.connect(self.remove_format) self.formats.itemDoubleClicked.connect(self.show_format) self.formats.setDragDropMode(self.formats.DropOnly) self.formats.setIconSize(QSize(32, 32)) self.formats.setMaximumWidth(200) l.addWidget(self.cover_from_format_button, 0, 0, 1, 1) l.addWidget(self.metadata_from_format_button, 2, 0, 1, 1) l.addWidget(self.add_format_button, 0, 2, 1, 1) l.addWidget(self.remove_format_button, 2, 2, 1, 1) l.addWidget(self.formats, 0, 1, 3, 1) self.temp_files = [] def initialize(self, db, id_): self.changed = False self.formats.clear() exts = db.formats(id_, index_is_id=True) self.original_val = set([]) if exts: exts = exts.split(',') for ext in exts: if not ext: ext = '' size = db.sizeof_format(id_, ext, index_is_id=True) timestamp = db.format_last_modified(id_, ext) if size is None: continue Format(self.formats, ext, size, timestamp=timestamp) self.original_val.add(ext.lower()) def commit(self, db, id_): if not self.changed: return True old_extensions, new_extensions, paths = set(), set(), {} for row in range(self.formats.count()): fmt = self.formats.item(row) ext, path = fmt.ext.lower(), fmt.path if 'unknown' in ext.lower(): ext = None if path: new_extensions.add(ext) paths[ext] = path else: old_extensions.add(ext) for ext in new_extensions: with SpooledTemporaryFile(SPOOL_SIZE) as spool: with open(paths[ext], 'rb') as f: shutil.copyfileobj(f, spool) spool.seek(0) db.add_format(id_, ext, spool, notify=False, index_is_id=True) dbfmts = db.formats(id_, index_is_id=True) db_extensions = set([f.lower() for f in (dbfmts.split(',') if dbfmts else [])]) extensions = new_extensions.union(old_extensions) for ext in db_extensions: if ext not in extensions and ext in self.original_val: db.remove_format(id_, ext, notify=False, index_is_id=True) self.changed = False return True def add_format(self, *args): files = choose_files(self, 'add formats dialog', _("Choose formats for ") + self.dialog.title.current_val, [(_('Books'), BOOK_EXTENSIONS)]) self._add_formats(files) def restore_fmt(self, fmt): pt = PersistentTemporaryFile(suffix='_restore_fmt.'+fmt.lower()) ofmt = 'ORIGINAL_'+fmt with pt: self.copy_fmt(ofmt, pt) self._add_formats((pt.name,)) self.temp_files.append(pt.name) self.changed = True self.formats.remove_format(ofmt) def _add_formats(self, paths): added = False if not paths: return added bad_perms = [] for _file in paths: _file = os.path.abspath(_file) if not os.access(_file, os.R_OK): bad_perms.append(_file) continue nfile = run_plugins_on_import(_file) if nfile is not None: _file = nfile stat = os.stat(_file) size = stat.st_size ext = os.path.splitext(_file)[1].lower().replace('.', '') timestamp = utcfromtimestamp(stat.st_mtime) for row in range(self.formats.count()): fmt = self.formats.item(row) if fmt.ext.lower() == ext: self.formats.takeItem(row) break Format(self.formats, ext, size, path=_file, timestamp=timestamp) self.changed = True added = True if bad_perms: error_dialog(self, _('No permission'), _('You do not have ' 'permission to read the following files:'), det_msg='\n'.join(bad_perms), show=True) return added def formats_dropped(self, event, paths): if self._add_formats(paths): event.accept() def remove_format(self, *args): rows = self.formats.selectionModel().selectedRows(0) for row in rows: self.formats.takeItem(row.row()) self.changed = True def show_format(self, item, *args): self.dialog.do_view_format(item.path, item.ext) def get_selected_format_metadata(self, db, id_): old = prefs['read_file_metadata'] if not old: prefs['read_file_metadata'] = True try: row = self.formats.currentRow() fmt = self.formats.item(row) if fmt is None: if self.formats.count() == 1: fmt = self.formats.item(0) if fmt is None: error_dialog(self, _('No format selected'), _('No format selected')).exec_() return None, None ext = fmt.ext.lower() if fmt.path is None: stream = db.format(id_, ext, as_file=True, index_is_id=True) else: stream = open(fmt.path, 'r+b') try: with stream: mi = get_metadata(stream, ext) return mi, ext except: error_dialog(self, _('Could not read metadata'), _('Could not read metadata from %s format')%ext).exec_() return None, None finally: if old != prefs['read_file_metadata']: prefs['read_file_metadata'] = old def break_cycles(self): self.dialog = None self.copy_fmt = None for name in self.temp_files: try: os.remove(name) except: pass self.temp_files = []
class ConfigWidget(QWidget, Logger): ''' Config dialog for Marvin Manager ''' WIZARD_PROFILES = { 'Annotations': { 'label': 'mm_annotations', 'datatype': 'comments', 'display': {}, 'is_multiple': False }, 'Collections': { 'label': 'mm_collections', 'datatype': 'text', 'display': {u'is_names': False}, 'is_multiple': True }, 'Last read': { 'label': 'mm_date_read', 'datatype': 'datetime', 'display': {}, 'is_multiple': False }, 'Locked': { 'label': 'mm_locked', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Progress': { 'label': 'mm_progress', 'datatype': 'float', 'display': {u'number_format': u'{0:.0f}%'}, 'is_multiple': False }, 'Read': { 'label': 'mm_read', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Reading list': { 'label': 'mm_reading_list', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Word count': { 'label': 'mm_word_count', 'datatype': 'int', 'display': {u'number_format': u'{0:n}'}, 'is_multiple': False } } def __init__(self, plugin_action): QWidget.__init__(self) self.parent = plugin_action self.gui = get_gui() self.icon = plugin_action.icon self.opts = plugin_action.opts self.prefs = plugin_prefs self.resources_path = plugin_action.resources_path self.verbose = plugin_action.verbose self.restart_required = False self._log_location() self.l = QGridLayout() self.setLayout(self.l) self.column1_layout = QVBoxLayout() self.l.addLayout(self.column1_layout, 0, 0) self.column2_layout = QVBoxLayout() self.l.addLayout(self.column2_layout, 0, 1) # ----------------------------- Column 1 ----------------------------- # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~ self.cfg_custom_fields_gb = QGroupBox(self) self.cfg_custom_fields_gb.setTitle('Custom column assignments') self.column1_layout.addWidget(self.cfg_custom_fields_gb) self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb) current_row = 0 # ++++++++ Labels + HLine ++++++++ self.marvin_source_label = QLabel("Marvin source") self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0) self.calibre_destination_label = QLabel("calibre destination") self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1) current_row += 1 self.sd_hl = QFrame(self.cfg_custom_fields_gb) self.sd_hl.setFrameShape(QFrame.HLine) self.sd_hl.setFrameShadow(QFrame.Raised) self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3) current_row += 1 # ++++++++ Annotations ++++++++ self.cfg_annotations_label = QLabel('Annotations') self.cfg_annotations_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0) self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.annotations_field_comboBox.setObjectName('annotations_field_comboBox') self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations') self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1) self.cfg_highlights_wizard = QToolButton() self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations") self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2) current_row += 1 # ++++++++ Collections ++++++++ self.cfg_collections_label = QLabel('Collections') self.cfg_collections_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0) self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.collection_field_comboBox.setObjectName('collection_field_comboBox') self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments') self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Last read ++++++++ self.cfg_date_read_label = QLabel("Last read") self.cfg_date_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0) self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.date_read_field_comboBox.setObjectName('date_read_field_comboBox') self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date') self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Locked ++++++++ self.cfg_locked_label = QLabel("Locked") self.cfg_locked_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0) self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.locked_field_comboBox.setObjectName('locked_field_comboBox') self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status') self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1) self.cfg_locked_wizard = QToolButton() self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status") self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked')) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2) current_row += 1 # ++++++++ Progress ++++++++ self.cfg_progress_label = QLabel('Progress') self.cfg_progress_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0) self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.progress_field_comboBox.setObjectName('progress_field_comboBox') self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress') self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1) self.cfg_progress_wizard = QToolButton() self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress") self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress')) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2) current_row += 1 # ++++++++ Read flag ++++++++ self.cfg_read_label = QLabel('Read') self.cfg_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0) self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.read_field_comboBox.setObjectName('read_field_comboBox') self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status') self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1) self.cfg_read_wizard = QToolButton() self.cfg_read_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status") self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2) current_row += 1 # ++++++++ Reading list flag ++++++++ self.cfg_reading_list_label = QLabel('Reading list') self.cfg_reading_list_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0) self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox') self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status') self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1) self.cfg_reading_list_wizard = QToolButton() self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status") self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list')) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2) current_row += 1 # ++++++++ Word count ++++++++ self.cfg_word_count_label = QLabel('Word count') self.cfg_word_count_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0) self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.word_count_field_comboBox.setObjectName('word_count_field_comboBox') self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts') self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1) self.cfg_word_count_wizard = QToolButton() self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts") self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count')) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2) current_row += 1 self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column1_layout.addItem(self.spacerItem1) # ----------------------------- Column 2 ----------------------------- # ~~~~~~~~ Create the CSS group box ~~~~~~~~ self.cfg_css_options_gb = QGroupBox(self) self.cfg_css_options_gb.setTitle('CSS') self.column2_layout.addWidget(self.cfg_css_options_gb) self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb) current_row = 0 # ++++++++ Annotations appearance ++++++++ self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png')) self.cfg_annotations_appearance_toolbutton = QToolButton() self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon) self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0) self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations") self.connect(self.cfg_annotations_label, SIGNAL('clicked()'), self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1) current_row += 1 # ++++++++ Injected CSS ++++++++ self.css_editor_icon = QIcon(I('format-text-heading.png')) self.cfg_css_editor_toolbutton = QToolButton() self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon) self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0) self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary") self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'), self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1) """ # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~ self.cfg_dropbox_syncing_gb = QGroupBox(self) self.cfg_dropbox_syncing_gb.setTitle('Dropbox') self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb) self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb) current_row = 0 # ++++++++ Syncing enabled checkbox ++++++++ self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates') self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing') self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata') self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox, current_row, 0, 1, 3) current_row += 1 # ++++++++ Dropbox folder picker ++++++++ self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png')) self.cfg_dropbox_folder_toolbutton = QToolButton() self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon) self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer") self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder) self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton, current_row, 1) # ++++++++ Dropbox location lineedit ++++++++ self.dropbox_location_lineedit = QLineEdit() self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location") self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit, current_row, 2) """ # ~~~~~~~~ Create the General options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle('General options') self.column2_layout.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ++++++++ Temporary markers: Duplicates ++++++++ self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books') self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates') self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox) # ++++++++ Temporary markers: Updated ++++++++ self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content') self.updated_markers_checkbox.setObjectName('apply_markers_to_updated') self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox) # ++++++++ Auto refresh checkbox ++++++++ self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content') self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup') self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened') self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox) # ++++++++ Progress as percentage checkbox ++++++++ self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage') self.reading_progress_checkbox.setObjectName('show_progress_as_percentage') self.reading_progress_checkbox.setToolTip('Display percentage in Progress column') self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox) # ~~~~~~~~ Create the Debug options group box ~~~~~~~~ self.cfg_debug_options_gb = QGroupBox(self) self.cfg_debug_options_gb.setTitle('Debug options') self.column2_layout.addWidget(self.cfg_debug_options_gb) self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb) # ++++++++ Debug logging checkboxes ++++++++ self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD') self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox') self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox) self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice') self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox') self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox) self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column2_layout.addItem(self.spacerItem2) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # ~~~~~~~~ Populate/restore config options ~~~~~~~~ # Annotations comboBox self.populate_annotations() self.populate_collections() self.populate_date_read() self.populate_locked() self.populate_progress() self.populate_read() self.populate_reading_list() self.populate_word_count() """ # Restore Dropbox settings, hook changes dropbox_syncing = self.prefs.get('dropbox_syncing', False) self.dropbox_syncing_checkbox.setChecked(dropbox_syncing) self.set_dropbox_syncing(dropbox_syncing) self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing)) self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', '')) """ # Restore general settings self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True)) self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True)) self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False)) self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False)) # Restore debug settings, hook changes self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False)) self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required) self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False)) self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required) # Hook changes to Annotations comboBox # self.annotations_field_comboBox.currentIndexChanged.connect( # partial(self.save_combobox_setting, 'annotations_field_comboBox')) self.connect(self.annotations_field_comboBox, SIGNAL('currentIndexChanged(const QString &)'), self.annotations_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal, self.inventory_complete) QTimer.singleShot(1, self.start_inventory) def annotations_destination_changed(self, qs_new_destination_name): ''' If the destination field changes, move all existing annotations from old to new ''' self._log_location(str(qs_new_destination_name)) #self._log("self.eligible_annotations_fields: %s" % self.eligible_annotations_fields) old_destination_field = get_cc_mapping('annotations', 'field', None) old_destination_name = get_cc_mapping('annotations', 'combobox', None) self._log("old_destination_field: %s" % old_destination_field) self._log("old_destination_name: %s" % old_destination_name) new_destination_name = unicode(qs_new_destination_name) self._log("new_destination_name: %s" % repr(new_destination_name)) if old_destination_name == new_destination_name: self._log_location("old_destination_name = new_destination_name, no changes") return if new_destination_name == '': self._log_location("annotations storage disabled") set_cc_mapping('annotations', field=None, combobox=new_destination_name) return new_destination_field = self.eligible_annotations_fields[new_destination_name] if existing_annotations(self.parent, old_destination_field): command = self.launch_new_destination_dialog(old_destination_name, new_destination_name) if command == 'move': set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) if self.annotated_books_scanner.isRunning(): self.annotated_books_scanner.wait() move_annotations(self, self.annotated_books_scanner.annotation_map, old_destination_field, new_destination_field) elif command == 'change': # Keep the updated destination field, but don't move annotations pass elif command == 'cancel': # Restore previous destination self.annotations_field_comboBox.blockSignals(True) old_index = self.annotations_field_comboBox.findText(old_destination_name) self.annotations_field_comboBox.setCurrentIndex(old_index) self.annotations_field_comboBox.blockSignals(False) else: # No existing annotations, just update prefs self._log("no existing annotations, updating destination to '{0}'".format(new_destination_name)) set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) def configure_appearance(self): ''' ''' self._log_location() appearance_settings = { 'appearance_css': default_elements, 'appearance_hr_checkbox': False, 'appearance_timestamp_format': default_timestamp } # Save, hash the original settings original_settings = {} osh = hashlib.md5() for setting in appearance_settings: original_settings[setting] = plugin_prefs.get(setting, appearance_settings[setting]) osh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) # Display the Annotations appearance dialog aa = AnnotationsAppearance(self, self.annotations_icon, plugin_prefs) cancelled = False if aa.exec_(): # appearance_hr_checkbox and appearance_timestamp_format changed live to prefs during previews plugin_prefs.set('appearance_css', aa.elements_table.get_data()) # Generate a new hash nsh = hashlib.md5() for setting in appearance_settings: nsh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) else: for setting in appearance_settings: plugin_prefs.set(setting, original_settings[setting]) nsh = osh # If there were changes, and there are existing annotations, # and there is an active Annotations field, offer to re-render field = get_cc_mapping('annotations', 'field', None) if osh.digest() != nsh.digest() and existing_annotations(self.parent, field): title = 'Update annotations?' msg = '<p>Update existing annotations to new appearance settings?</p>' d = MessageBox(MessageBox.QUESTION, title, msg, show_copy_button=False) self._log_location("QUESTION: %s" % msg) if d.exec_(): self._log_location("Updating existing annotations to modified appearance") # Wait for indexing to complete while not self.annotated_books_scanner.isFinished(): Application.processEvents() move_annotations(self, self.annotated_books_scanner.annotation_map, field, field, window_title="Updating appearance") def edit_css(self): ''' ''' self._log_location() from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'css_editor.py') if os.path.exists(klass): sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('css_editor') sys.path.remove(dialog_resources_path) dlg = this_dc.CSSEditorDialog(self, 'css_editor') dlg.initialize(self) dlg.exec_() def get_eligible_custom_fields(self, eligible_types=[], is_multiple=None): ''' Discover qualifying custom fields for eligible_types[] ''' #self._log_location(eligible_types) eligible_custom_fields = {} for cf in self.gui.current_db.custom_field_keys(): cft = self.gui.current_db.metadata_for_field(cf)['datatype'] cfn = self.gui.current_db.metadata_for_field(cf)['name'] cfim = self.gui.current_db.metadata_for_field(cf)['is_multiple'] #self._log("cf: %s cft: %s cfn: %s cfim: %s" % (cf, cft, cfn, cfim)) if cft in eligible_types: if is_multiple is not None: if bool(cfim) == is_multiple: eligible_custom_fields[cfn] = cf else: eligible_custom_fields[cfn] = cf return eligible_custom_fields def inventory_complete(self, msg): self._log_location(msg) def launch_cc_wizard(self, column_type): ''' ''' def _update_combo_box(comboBox, destination, previous): ''' ''' cb = getattr(self, comboBox) cb.blockSignals(True) all_items = [str(cb.itemText(i)) for i in range(cb.count())] if previous and previous in all_items: all_items.remove(previous) all_items.append(destination) cb.clear() cb.addItems(sorted(all_items, key=lambda s: s.lower())) # Select the new destination in the comboBox idx = cb.findText(destination) if idx > -1: cb.setCurrentIndex(idx) cb.blockSignals(False) from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'cc_wizard.py') if os.path.exists(klass): #self._log("importing CC Wizard dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('cc_wizard') sys.path.remove(dialog_resources_path) dlg = this_dc.CustomColumnWizard(self, column_type, self.WIZARD_PROFILES[column_type], verbose=True) dlg.exec_() if dlg.modified_column: self._log("modified_column: %s" % dlg.modified_column) self.restart_required = True destination = dlg.modified_column['destination'] label = dlg.modified_column['label'] previous = dlg.modified_column['previous'] source = dlg.modified_column['source'] if source == "Annotations": _update_combo_box("annotations_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_annotations_fields[destination] = label # Save manually in case user cancels set_cc_mapping('annotations', combobox=destination, field=label) elif source == 'Collections': _update_combo_box("collection_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_collection_fields[destination] = label # Save manually in case user cancels set_cc_mapping('collections', combobox=destination, field=label) elif source == 'Last read': _update_combo_box("date_read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_date_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('date_read', combobox=destination, field=label) elif source == 'Locked': _update_combo_box("locked_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_locked_fields[destination] = label # Save manually in case user cancels set_cc_mapping('locked', combobox=destination, field=label) elif source == "Progress": _update_combo_box("progress_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_progress_fields[destination] = label # Save manually in case user cancels set_cc_mapping('progress', combobox=destination, field=label) elif source == "Read": _update_combo_box("read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('read', combobox=destination, field=label) elif source == "Reading list": _update_combo_box("reading_list_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_reading_list_fields[destination] = label # Save manually in case user cancels set_cc_mapping('reading_list', combobox=destination, field=label) elif source == "Word count": _update_combo_box("word_count_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_word_count_fields[destination] = label # Save manually in case user cancels set_cc_mapping('word_count', combobox=destination, field=label) else: self._log("ERROR: Can't import from '%s'" % klass) def launch_new_destination_dialog(self, old, new): ''' Return 'move', 'change' or 'cancel' ''' from calibre_plugins.marvin_manager.book_status import dialog_resources_path self._log_location() klass = os.path.join(dialog_resources_path, 'new_destination.py') if os.path.exists(klass): self._log("importing new destination dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('new_destination') sys.path.remove(dialog_resources_path) dlg = this_dc.NewDestinationDialog(self, old, new) dlg.exec_() return dlg.command def populate_annotations(self): datatype = self.WIZARD_PROFILES['Annotations']['datatype'] self.eligible_annotations_fields = self.get_eligible_custom_fields([datatype]) self.annotations_field_comboBox.addItems(['']) ecf = sorted(self.eligible_annotations_fields.keys(), key=lambda s: s.lower()) self.annotations_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('annotations', 'combobox') if existing: ci = self.annotations_field_comboBox.findText(existing) self.annotations_field_comboBox.setCurrentIndex(ci) def populate_collections(self): datatype = self.WIZARD_PROFILES['Collections']['datatype'] self.eligible_collection_fields = self.get_eligible_custom_fields([datatype], is_multiple=True) self.collection_field_comboBox.addItems(['']) ecf = sorted(self.eligible_collection_fields.keys(), key=lambda s: s.lower()) self.collection_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('collections', 'combobox') if existing: ci = self.collection_field_comboBox.findText(existing) self.collection_field_comboBox.setCurrentIndex(ci) def populate_date_read(self): #self.eligible_date_read_fields = self.get_eligible_custom_fields(['datetime']) datatype = self.WIZARD_PROFILES['Last read']['datatype'] self.eligible_date_read_fields = self.get_eligible_custom_fields([datatype]) self.date_read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_date_read_fields.keys(), key=lambda s: s.lower()) self.date_read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('date_read', 'combobox') if existing: ci = self.date_read_field_comboBox.findText(existing) self.date_read_field_comboBox.setCurrentIndex(ci) def populate_locked(self): datatype = self.WIZARD_PROFILES['Locked']['datatype'] self.eligible_locked_fields = self.get_eligible_custom_fields([datatype]) self.locked_field_comboBox.addItems(['']) ecf = sorted(self.eligible_locked_fields.keys(), key=lambda s: s.lower()) self.locked_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('locked', 'combobox') if existing: ci = self.locked_field_comboBox.findText(existing) self.locked_field_comboBox.setCurrentIndex(ci) def populate_progress(self): #self.eligible_progress_fields = self.get_eligible_custom_fields(['float']) datatype = self.WIZARD_PROFILES['Progress']['datatype'] self.eligible_progress_fields = self.get_eligible_custom_fields([datatype]) self.progress_field_comboBox.addItems(['']) ecf = sorted(self.eligible_progress_fields.keys(), key=lambda s: s.lower()) self.progress_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('progress', 'combobox') if existing: ci = self.progress_field_comboBox.findText(existing) self.progress_field_comboBox.setCurrentIndex(ci) def populate_read(self): datatype = self.WIZARD_PROFILES['Read']['datatype'] self.eligible_read_fields = self.get_eligible_custom_fields([datatype]) self.read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_read_fields.keys(), key=lambda s: s.lower()) self.read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('read', 'combobox') if existing: ci = self.read_field_comboBox.findText(existing) self.read_field_comboBox.setCurrentIndex(ci) def populate_reading_list(self): datatype = self.WIZARD_PROFILES['Reading list']['datatype'] self.eligible_reading_list_fields = self.get_eligible_custom_fields([datatype]) self.reading_list_field_comboBox.addItems(['']) ecf = sorted(self.eligible_reading_list_fields.keys(), key=lambda s: s.lower()) self.reading_list_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('reading_list', 'combobox') if existing: ci = self.reading_list_field_comboBox.findText(existing) self.reading_list_field_comboBox.setCurrentIndex(ci) def populate_word_count(self): #self.eligible_word_count_fields = self.get_eligible_custom_fields(['int']) datatype = self.WIZARD_PROFILES['Word count']['datatype'] self.eligible_word_count_fields = self.get_eligible_custom_fields([datatype]) self.word_count_field_comboBox.addItems(['']) ecf = sorted(self.eligible_word_count_fields.keys(), key=lambda s: s.lower()) self.word_count_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('word_count', 'combobox') if existing: ci = self.word_count_field_comboBox.findText(existing) self.word_count_field_comboBox.setCurrentIndex(ci) """ def select_dropbox_folder(self): ''' ''' self._log_location() dropbox_location = QFileDialog.getExistingDirectory( self, "Dropbox folder", os.path.expanduser("~"), QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) self.dropbox_location_lineedit.setText(unicode(dropbox_location)) def set_dropbox_syncing(self, state): ''' Called when checkbox changes state, or when restoring state Set enabled state of Dropbox folder picker to match ''' self.cfg_dropbox_folder_toolbutton.setEnabled(state) self.dropbox_location_lineedit.setEnabled(state) """ def set_restart_required(self, state): ''' Set restart_required flag to show show dialog when closing dialog ''' self.restart_required = True """ def save_combobox_setting(self, cb, index): ''' Apply changes immediately ''' cf = str(getattr(self, cb).currentText()) self._log_location("%s => %s" % (cb, repr(cf))) if cb == 'annotations_field_comboBox': field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) """ def save_settings(self): self._log_location() # Annotations field cf = unicode(self.annotations_field_comboBox.currentText()) field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) # Collections field cf = unicode(self.collection_field_comboBox.currentText()) field = None if cf: field = self.eligible_collection_fields[cf] set_cc_mapping('collections', combobox=cf, field=field) # Date read field cf = unicode(self.date_read_field_comboBox.currentText()) field = None if cf: field = self.eligible_date_read_fields[cf] set_cc_mapping('date_read', combobox=cf, field=field) # Locked field cf = unicode(self.locked_field_comboBox.currentText()) field = None if cf: field = self.eligible_locked_fields[cf] set_cc_mapping('locked', combobox=cf, field=field) # Progress field cf = unicode(self.progress_field_comboBox.currentText()) field = None if cf: field = self.eligible_progress_fields[cf] set_cc_mapping('progress', combobox=cf, field=field) # Read field cf = unicode(self.read_field_comboBox.currentText()) field = None if cf: field = self.eligible_read_fields[cf] set_cc_mapping('read', combobox=cf, field=field) # Reading list field cf = unicode(self.reading_list_field_comboBox.currentText()) field = None if cf: field = self.eligible_reading_list_fields[cf] set_cc_mapping('reading_list', combobox=cf, field=field) # Word count field cf = unicode(self.word_count_field_comboBox.currentText()) field = None if cf: field = self.eligible_word_count_fields[cf] set_cc_mapping('word_count', combobox=cf, field=field) ''' # Save Dropbox settings self.prefs.set('dropbox_syncing', self.dropbox_syncing_checkbox.isChecked()) self.prefs.set('dropbox_folder', unicode(self.dropbox_location_lineedit.text())) ''' # Save general settings self.prefs.set('apply_markers_to_duplicates', self.duplicate_markers_checkbox.isChecked()) self.prefs.set('apply_markers_to_updated', self.updated_markers_checkbox.isChecked()) self.prefs.set('auto_refresh_at_startup', self.auto_refresh_checkbox.isChecked()) self.prefs.set('show_progress_as_percentage', self.reading_progress_checkbox.isChecked()) # Save debug settings self.prefs.set('debug_plugin', self.debug_plugin_checkbox.isChecked()) self.prefs.set('debug_libimobiledevice', self.debug_libimobiledevice_checkbox.isChecked()) # If restart needed, inform user if self.restart_required: do_restart = show_restart_warning('Restart calibre for the changes to be applied.', parent=self.gui) if do_restart: self.gui.quit(restart=True) def start_inventory(self): self._log_location() self.annotated_books_scanner.start()
def __init__(self, plugin_action): QWidget.__init__(self) self.parent = plugin_action self.gui = get_gui() self.icon = plugin_action.icon self.opts = plugin_action.opts self.prefs = plugin_prefs self.resources_path = plugin_action.resources_path self.verbose = plugin_action.verbose self.restart_required = False self._log_location() self.l = QGridLayout() self.setLayout(self.l) self.column1_layout = QVBoxLayout() self.l.addLayout(self.column1_layout, 0, 0) self.column2_layout = QVBoxLayout() self.l.addLayout(self.column2_layout, 0, 1) # ----------------------------- Column 1 ----------------------------- # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~ self.cfg_custom_fields_gb = QGroupBox(self) self.cfg_custom_fields_gb.setTitle('Custom column assignments') self.column1_layout.addWidget(self.cfg_custom_fields_gb) self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb) current_row = 0 # ++++++++ Labels + HLine ++++++++ self.marvin_source_label = QLabel("Marvin source") self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0) self.calibre_destination_label = QLabel("calibre destination") self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1) current_row += 1 self.sd_hl = QFrame(self.cfg_custom_fields_gb) self.sd_hl.setFrameShape(QFrame.HLine) self.sd_hl.setFrameShadow(QFrame.Raised) self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3) current_row += 1 # ++++++++ Annotations ++++++++ self.cfg_annotations_label = QLabel('Annotations') self.cfg_annotations_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0) self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.annotations_field_comboBox.setObjectName('annotations_field_comboBox') self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations') self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1) self.cfg_highlights_wizard = QToolButton() self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations") self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2) current_row += 1 # ++++++++ Collections ++++++++ self.cfg_collections_label = QLabel('Collections') self.cfg_collections_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0) self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.collection_field_comboBox.setObjectName('collection_field_comboBox') self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments') self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Last read ++++++++ self.cfg_date_read_label = QLabel("Last read") self.cfg_date_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0) self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.date_read_field_comboBox.setObjectName('date_read_field_comboBox') self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date') self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Locked ++++++++ self.cfg_locked_label = QLabel("Locked") self.cfg_locked_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0) self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.locked_field_comboBox.setObjectName('locked_field_comboBox') self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status') self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1) self.cfg_locked_wizard = QToolButton() self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status") self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked')) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2) current_row += 1 # ++++++++ Progress ++++++++ self.cfg_progress_label = QLabel('Progress') self.cfg_progress_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0) self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.progress_field_comboBox.setObjectName('progress_field_comboBox') self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress') self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1) self.cfg_progress_wizard = QToolButton() self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress") self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress')) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2) current_row += 1 # ++++++++ Read flag ++++++++ self.cfg_read_label = QLabel('Read') self.cfg_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0) self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.read_field_comboBox.setObjectName('read_field_comboBox') self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status') self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1) self.cfg_read_wizard = QToolButton() self.cfg_read_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status") self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2) current_row += 1 # ++++++++ Reading list flag ++++++++ self.cfg_reading_list_label = QLabel('Reading list') self.cfg_reading_list_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0) self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox') self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status') self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1) self.cfg_reading_list_wizard = QToolButton() self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status") self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list')) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2) current_row += 1 # ++++++++ Word count ++++++++ self.cfg_word_count_label = QLabel('Word count') self.cfg_word_count_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0) self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.word_count_field_comboBox.setObjectName('word_count_field_comboBox') self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts') self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1) self.cfg_word_count_wizard = QToolButton() self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts") self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count')) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2) current_row += 1 self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column1_layout.addItem(self.spacerItem1) # ----------------------------- Column 2 ----------------------------- # ~~~~~~~~ Create the CSS group box ~~~~~~~~ self.cfg_css_options_gb = QGroupBox(self) self.cfg_css_options_gb.setTitle('CSS') self.column2_layout.addWidget(self.cfg_css_options_gb) self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb) current_row = 0 # ++++++++ Annotations appearance ++++++++ self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png')) self.cfg_annotations_appearance_toolbutton = QToolButton() self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon) self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0) self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations") self.connect(self.cfg_annotations_label, SIGNAL('clicked()'), self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1) current_row += 1 # ++++++++ Injected CSS ++++++++ self.css_editor_icon = QIcon(I('format-text-heading.png')) self.cfg_css_editor_toolbutton = QToolButton() self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon) self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0) self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary") self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'), self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1) """ # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~ self.cfg_dropbox_syncing_gb = QGroupBox(self) self.cfg_dropbox_syncing_gb.setTitle('Dropbox') self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb) self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb) current_row = 0 # ++++++++ Syncing enabled checkbox ++++++++ self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates') self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing') self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata') self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox, current_row, 0, 1, 3) current_row += 1 # ++++++++ Dropbox folder picker ++++++++ self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png')) self.cfg_dropbox_folder_toolbutton = QToolButton() self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon) self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer") self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder) self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton, current_row, 1) # ++++++++ Dropbox location lineedit ++++++++ self.dropbox_location_lineedit = QLineEdit() self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location") self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit, current_row, 2) """ # ~~~~~~~~ Create the General options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle('General options') self.column2_layout.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ++++++++ Temporary markers: Duplicates ++++++++ self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books') self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates') self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox) # ++++++++ Temporary markers: Updated ++++++++ self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content') self.updated_markers_checkbox.setObjectName('apply_markers_to_updated') self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox) # ++++++++ Auto refresh checkbox ++++++++ self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content') self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup') self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened') self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox) # ++++++++ Progress as percentage checkbox ++++++++ self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage') self.reading_progress_checkbox.setObjectName('show_progress_as_percentage') self.reading_progress_checkbox.setToolTip('Display percentage in Progress column') self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox) # ~~~~~~~~ Create the Debug options group box ~~~~~~~~ self.cfg_debug_options_gb = QGroupBox(self) self.cfg_debug_options_gb.setTitle('Debug options') self.column2_layout.addWidget(self.cfg_debug_options_gb) self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb) # ++++++++ Debug logging checkboxes ++++++++ self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD') self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox') self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox) self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice') self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox') self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox) self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column2_layout.addItem(self.spacerItem2) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # ~~~~~~~~ Populate/restore config options ~~~~~~~~ # Annotations comboBox self.populate_annotations() self.populate_collections() self.populate_date_read() self.populate_locked() self.populate_progress() self.populate_read() self.populate_reading_list() self.populate_word_count() """ # Restore Dropbox settings, hook changes dropbox_syncing = self.prefs.get('dropbox_syncing', False) self.dropbox_syncing_checkbox.setChecked(dropbox_syncing) self.set_dropbox_syncing(dropbox_syncing) self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing)) self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', '')) """ # Restore general settings self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True)) self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True)) self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False)) self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False)) # Restore debug settings, hook changes self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False)) self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required) self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False)) self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required) # Hook changes to Annotations comboBox # self.annotations_field_comboBox.currentIndexChanged.connect( # partial(self.save_combobox_setting, 'annotations_field_comboBox')) self.connect(self.annotations_field_comboBox, SIGNAL('currentIndexChanged(const QString &)'), self.annotations_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal, self.inventory_complete) QTimer.singleShot(1, self.start_inventory)
def __init__(self, parent = None, desc = None, name = None, modal = 0, fl = 0, env = None, type = "QDialog"): if env is None: import foundation.env as env # this is a little weird... probably it'll be ok, and logically it seems correct. self.desc = desc self.typ = type if type == "QDialog": QDialog.__init__(self,parent,name,modal,fl) elif type == "QTextEdit": QTextEdit.__init__(self, parent, name) elif type == "QFrame": QFrame.__init__(self,parent,name) else: print "don't know about type == %r" % (type,) self.image1 = QPixmap() self.image1.loadFromData(image1_data,"PNG") # should be: title_icon #### self.image3 = QPixmap() self.image3.loadFromData(image3_data,"PNG") self.image4 = QPixmap() self.image4.loadFromData(image4_data,"PNG") self.image5 = QPixmap() self.image5.loadFromData(image5_data,"PNG") self.image6 = QPixmap() self.image6.loadFromData(image6_data,"PNG") self.image7 = QPixmap() self.image7.loadFromData(image7_data,"PNG") self.image0 = QPixmap(image0_data) # should be: border_icon #### self.image2 = QPixmap(image2_data) # should be: sponsor_pixmap #### try: ####@@@@ title_icon_name = self.desc.options.get('title_icon') border_icon_name = self.desc.options.get('border_icon') if title_icon_name: self.image1 = imagename_to_pixmap(title_icon_name) ###@@@ pass icon_path ###@@@ import imagename_to_pixmap or use env function # or let that func itself be an arg, or have an env arg for it ###e rename it icon_name_to_pixmap, or find_icon? (the latter only if it's ok if it returns an iconset) ###e use iconset instead? if border_icon_name: self.image0 = imagename_to_pixmap(border_icon_name) except: print_compact_traceback("bug in icon-setting code, using fallback icons: ") pass if not name: self.setName("parameter_dialog_or_frame") ### ###k guess this will need: if type == 'QDialog' self.setIcon(self.image0) # should be: border_icon #### nanotube_dialogLayout = QVBoxLayout(self,0,0,"nanotube_dialogLayout") self.heading_frame = QFrame(self,"heading_frame") self.heading_frame.setPaletteBackgroundColor(QColor(122,122,122)) self.heading_frame.setFrameShape(QFrame.NoFrame) self.heading_frame.setFrameShadow(QFrame.Plain) heading_frameLayout = QHBoxLayout(self.heading_frame,0,3,"heading_frameLayout") self.heading_pixmap = QLabel(self.heading_frame,"heading_pixmap") self.heading_pixmap.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.heading_pixmap.sizePolicy().hasHeightForWidth())) self.heading_pixmap.setPixmap(self.image1) # should be: title_icon #### self.heading_pixmap.setScaledContents(1) heading_frameLayout.addWidget(self.heading_pixmap) self.heading_label = QLabel(self.heading_frame,"heading_label") self.heading_label.setPaletteForegroundColor(QColor(255,255,255)) heading_label_font = QFont(self.heading_label.font()) heading_label_font.setPointSize(12) heading_label_font.setBold(1) self.heading_label.setFont(heading_label_font) heading_frameLayout.addWidget(self.heading_label) nanotube_dialogLayout.addWidget(self.heading_frame) self.body_frame = QFrame(self,"body_frame") self.body_frame.setFrameShape(QFrame.StyledPanel) self.body_frame.setFrameShadow(QFrame.Raised) body_frameLayout = QVBoxLayout(self.body_frame,3,3,"body_frameLayout") self.sponsor_frame = QFrame(self.body_frame,"sponsor_frame") self.sponsor_frame.setPaletteBackgroundColor(QColor(255,255,255)) self.sponsor_frame.setFrameShape(QFrame.StyledPanel) self.sponsor_frame.setFrameShadow(QFrame.Raised) sponsor_frameLayout = QHBoxLayout(self.sponsor_frame,0,0,"sponsor_frameLayout") self.sponsor_btn = QPushButton(self.sponsor_frame,"sponsor_btn") self.sponsor_btn.setAutoDefault(0) #bruce 060703 bugfix self.sponsor_btn.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred,0,0,self.sponsor_btn.sizePolicy().hasHeightForWidth())) self.sponsor_btn.setPaletteBackgroundColor(QColor(255,255,255)) self.sponsor_btn.setPixmap(self.image2) # should be: sponsor_pixmap #### [also we'll need to support >1 sponsor] self.sponsor_btn.setFlat(1) sponsor_frameLayout.addWidget(self.sponsor_btn) body_frameLayout.addWidget(self.sponsor_frame) layout59 = QHBoxLayout(None,0,6,"layout59") left_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout59.addItem(left_spacer) self.done_btn = QToolButton(self.body_frame,"done_btn") self.done_btn.setIcon(QIcon(self.image3)) layout59.addWidget(self.done_btn) self.abort_btn = QToolButton(self.body_frame,"abort_btn") self.abort_btn.setIcon(QIcon(self.image4)) layout59.addWidget(self.abort_btn) self.preview_btn = QToolButton(self.body_frame,"preview_btn") self.preview_btn.setIcon(QIcon(self.image5)) layout59.addWidget(self.preview_btn) self.whatsthis_btn = QToolButton(self.body_frame,"whatsthis_btn") self.whatsthis_btn.setIcon(QIcon(self.image6)) layout59.addWidget(self.whatsthis_btn) right_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout59.addItem(right_spacer) body_frameLayout.addLayout(layout59) self.groups = [] self.param_getters = {} # map from param name to get-function (which gets current value out of its widget or controller) for group_desc in self.desc.kids('group'): # == start parameters_grpbox ### this will differ for Windows style header_refs = [] # keep python refcounted refs to all objects we make (at least the ones pyuic stored in self attrs) self.parameters_grpbox = QGroupBox(self.body_frame,"parameters_grpbox") self.parameters_grpbox.setFrameShape(QGroupBox.StyledPanel) self.parameters_grpbox.setFrameShadow(QGroupBox.Sunken) self.parameters_grpbox.setMargin(0) self.parameters_grpbox.setColumnLayout(0,Qt.Vertical) self.parameters_grpbox.layout().setSpacing(1) self.parameters_grpbox.layout().setMargin(4) parameters_grpboxLayout = QVBoxLayout(self.parameters_grpbox.layout()) parameters_grpboxLayout.setAlignment(Qt.AlignTop) layout20 = QHBoxLayout(None,0,6,"layout20") self.nt_parameters_grpbtn = QPushButton(self.parameters_grpbox,"nt_parameters_grpbtn") self.nt_parameters_grpbtn.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,QSizePolicy.Fixed,0,0,self.nt_parameters_grpbtn.sizePolicy().hasHeightForWidth())) self.nt_parameters_grpbtn.setMaximumSize(QSize(16,16)) self.nt_parameters_grpbtn.setAutoDefault(0) self.nt_parameters_grpbtn.setIcon(QIcon(self.image7)) ### not always right, but doesn't matter self.nt_parameters_grpbtn.setFlat(1) layout20.addWidget(self.nt_parameters_grpbtn) self.parameters_grpbox_label = QLabel(self.parameters_grpbox,"parameters_grpbox_label") self.parameters_grpbox_label.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Minimum,0,0,self.parameters_grpbox_label.sizePolicy().hasHeightForWidth())) self.parameters_grpbox_label.setAlignment(QLabel.AlignVCenter) layout20.addWidget(self.parameters_grpbox_label) gbx_spacer1 = QSpacerItem(67,16,QSizePolicy.Expanding,QSizePolicy.Minimum) layout20.addItem(gbx_spacer1) parameters_grpboxLayout.addLayout(layout20) nt_parameters_body_layout = QGridLayout(None,1,1,0,6,"nt_parameters_body_layout") ### what is 6 -- is it related to number of items??? # is it 6 in all the ones we got, but that could be a designer error so i better look it up sometime. # == start its kids # will use from above: self.parameters_grpbox, nt_parameters_body_layout nextrow = 0 # which row of the QGridLayout to start filling next (loop variable) hidethese = [] # set of objects to hide or show, when this group is closed or opened for param in group_desc.kids('parameter'): # param (a group subobj desc) is always a parameter, but we already plan to extend this beyond that, # so we redundantly test for this here. getter = None paramname = None # set these for use by uniform code at the end (e.g. for tooltips) editfield = None label = None if param.isa('parameter'): label = QLabel(self.parameters_grpbox,"members_label") label.setAlignment(QLabel.AlignVCenter | QLabel.AlignRight) nt_parameters_body_layout.addWidget(label,nextrow,0) hidethese.append(label) thisrow = nextrow nextrow += 1 #e following should be known in a place that knows the input language, not here paramname = param.options.get('name') or (param.args and param.args[0]) or "?" paramlabel = param.options.get('label') or paramname ##e wrong, label "" or none ought to be possible # QtGui.QApplication.translate(self.__class__.__name__, "xyz") label.setText(QtGui.QApplication.translate(self.__class__.__name__, paramlabel)) if param.isa('parameter', widget = 'combobox', type = ('str',None)): self.members_combox = QComboBox(0,self.parameters_grpbox,"members_combox") ###k what's 0? editfield = self.members_combox #### it probably needs a handler class, and then that could do this setup self.members_combox.clear() default = param.options.get('default', None) # None is not equal to any string thewidgetkid = param.kids('widget')[-1] # kluge; need to think what the desc method for this should be for item in thewidgetkid.kids('item'): itemval = item.args[0] itemtext = itemval self.members_combox.insertItem(QtGui.QApplication.translate(self.__class__.__name__, itemtext)) #k __tr ok?? if itemval == default: #k or itemtext? pass ##k i find no setItem in our py code, so not sure yet what to do for this. nt_parameters_body_layout.addWidget(self.members_combox,thisrow,1) hidethese.append(self.members_combox) getter = (lambda combobox = self.members_combox: str(combobox.currentText())) ##e due to __tr or non-str values, it might be better to use currentIndex and look it up in a table # (though whether __tr is good here might depend on what it's used for) elif param.isa('parameter', widget = ('lineedit', None), type = ('str',None)): # this covers explicit str|lineedit, and 3 default cases str, lineedit, neither. # (i.e. if you say parameter and nothing else, it's str lineedit by default.) self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit") editfield = self.length_linedit nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1) hidethese.append(self.length_linedit) default = str(param.options.get('default', "")) self.length_linedit.setText(QtGui.QApplication.translate(self.__class__.__name__, default)) # __tr ok? getter = (lambda lineedit = self.length_linedit: str(lineedit.text())) elif param.isa('parameter', widget = ('lineedit', None), type = 'float'): self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit") editfield = self.length_linedit nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1) hidethese.append(self.length_linedit) controller = FloatLineeditController_Qt(self, param, self.length_linedit) header_refs.append(controller) getter = controller.get_value elif param.isa('parameter', widget = ('spinbox', None), type = 'int') or \ param.isa('parameter', widget = ('spinbox'), type = None): self.chirality_N_spinbox = QSpinBox(self.parameters_grpbox,"chirality_N_spinbox") # was chirality_m_spinbox, now chirality_N_spinbox editfield = self.chirality_N_spinbox ### seems like Qt defaults for min and max are 0,100 -- way too small a range! if param.options.has_key('min') or 1: self.chirality_N_spinbox.setMinimum(param.options.get('min', -999999999)) # was 0 if param.options.has_key('max') or 1: self.chirality_N_spinbox.setMaximum(param.options.get('max', +999999999)) # wasn't in egcode, but needed self.chirality_N_spinbox.setValue(param.options.get('default', 0)) # was 5 ##e note: i suspect this default 0 should come from something that knows this desc grammar. suffix = param.options.get('suffix', '') if suffix: self.chirality_N_spinbox.setSuffix(QtGui.QApplication.translate(self.__class__.__name__, suffix)) else: self.chirality_N_spinbox.setSuffix(QString.null) # probably not needed nt_parameters_body_layout.addWidget(self.chirality_N_spinbox,thisrow,1) hidethese.append(self.chirality_N_spinbox) getter = self.chirality_N_spinbox.value # note: it also has .text, which includes suffix else: print "didn't match:",param ###e improve this # things done the same way for all kinds of param-editing widgets if 1: #bruce 060703 moved this down here, as bugfix # set tooltip (same one for editfield and label) tooltip = param.options.get('tooltip', '') ###e do it for more kinds of params; share the code somehow; do it in controller, or setup-aid? ###k QToolTip appropriateness; tooltip option might be entirely untested if tooltip and label: QToolTip.add(label, QtGui.QApplication.translate(self.__class__.__name__, tooltip)) if tooltip and editfield: QToolTip.add(editfield, QtGui.QApplication.translate(self.__class__.__name__, tooltip)) ##k ok?? review once not all params have same-row labels. if getter and paramname and paramname != '?': self.param_getters[paramname] = getter ### also bind these params to actions... continue # next param header_refs.extend( [self.parameters_grpbox, self.nt_parameters_grpbtn, self.parameters_grpbox_label] ) # now create the logic/control object for the group group = CollapsibleGroupController_Qt(self, group_desc, header_refs, hidethese, self.nt_parameters_grpbtn) ### maybe ask env for the class to use for this? self.groups.append(group) ### needed?? only for scanning the params, AFAIK -- oh, and to maintain a python refcount. # from languageChange: if 1: # i don't know if these are needed: self.parameters_grpbox.setTitle(QString.null) self.nt_parameters_grpbtn.setText(QString.null) self.parameters_grpbox_label.setText(QtGui.QApplication.translate(self.__class__.__name__, group_desc.args[0])) # was "Nanotube Parameters" ##e note that it's questionable in the syntax design for this property of a group (overall group label) # to be in that position (desc arg 0). # == end its kids parameters_grpboxLayout.addLayout(nt_parameters_body_layout) body_frameLayout.addWidget(self.parameters_grpbox) # == end parameters groupbox continue # next group nanotube_dialogLayout.addWidget(self.body_frame) spacer14 = QSpacerItem(20,20,QSizePolicy.Minimum,QSizePolicy.Expanding) nanotube_dialogLayout.addItem(spacer14) layout42 = QHBoxLayout(None,4,6,"layout42") btm_spacer = QSpacerItem(59,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout42.addItem(btm_spacer) self.cancel_btn = QPushButton(self,"cancel_btn") self.cancel_btn.setAutoDefault(0) #bruce 060703 bugfix layout42.addWidget(self.cancel_btn) self.ok_btn = QPushButton(self,"ok_btn") self.ok_btn.setAutoDefault(0) #bruce 060703 bugfix layout42.addWidget(self.ok_btn) nanotube_dialogLayout.addLayout(layout42) self.languageChange() self.resize(QSize(246,618).expandedTo(self.minimumSizeHint())) ### this size will need to be adjusted (guess -- it's only place overall size is set) qt4todo('self.clearWState(Qt.WState_Polished)') ## self.connect(self.nt_parameters_grpbtn,SIGNAL("clicked()"),self.toggle_nt_parameters_grpbtn) #### # new: for button, methodname in ((self.sponsor_btn, 'do_sponsor_btn'), #e generalize to more than one sponsor button (self.done_btn, 'do_done_btn'), (self.abort_btn, 'do_abort_btn'), (self.preview_btn, 'do_preview_btn'), (self.whatsthis_btn, 'do_whatsthis_btn'), (self.cancel_btn, 'do_cancel_btn'), (self.ok_btn, 'do_ok_btn')): if hasattr(self, methodname): self.connect(button, SIGNAL("clicked()"), getattr(self, methodname)) return
def _createToolButtonWidget(self, parent): """ @see: self.createWidget() """ btn = QToolButton(parent) btn.setAutoFillBackground(True) btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) btn.setMinimumWidth(75) btn.setMaximumWidth(75) btn.setMinimumHeight(62) btn.setAutoRaise(True) btn.setCheckable(True) btn.setDefaultAction(self) text = truncateText(self.text()) btn.setText(text) if self._toolButtonPalette: btn.setPalette(self._toolButtonPalette) #@@@ ninad070125 The following function #adds a newline character after each word in toolbutton text. #but the changes are reflected only on 'mode' toolbuttons #on the flyout toolbar (i.e.only Checkable buttons..don't know #why. Disabling its use for now. debug_wrapText = False if debug_wrapText: text = wrapToolButtonText(action.text()) if text: action.setText(text) return btn