def dial(self): dial = QDialog(self) dial.setWindowTitle("Select a layer") layerList = QListWidget(dial) db = GPostGISDatabase() for t in db.tables(): layerList.addItem(t) dial.setBaseSize(layerList.minimumSize()) dial.show()
class PrefsViewerDialog(SizePersistedDialog): def __init__(self, gui, namespace): SizePersistedDialog.__init__(self, gui, 'Prefs Viewer dialog') self.setWindowTitle('Preferences for: ' + namespace) self.db = gui.current_db self.namespace = namespace self._init_controls() self.resize_dialog() self._populate_settings() if self.keys_list.count(): self.keys_list.setCurrentRow(0) def _init_controls(self): layout = QVBoxLayout(self) self.setLayout(layout) ml = QHBoxLayout() layout.addLayout(ml, 1) self.keys_list = QListWidget(self) self.keys_list.setSelectionMode(QAbstractItemView.SingleSelection) self.keys_list.setFixedWidth(150) self.keys_list.setAlternatingRowColors(True) ml.addWidget(self.keys_list) self.value_text = QTextEdit(self) self.value_text.setTabStopWidth(24) self.value_text.setReadOnly(True) ml.addWidget(self.value_text, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok) button_box.accepted.connect(self.accept) button_box.setCenterButtons(True) layout.addWidget(button_box) def _populate_settings(self): self.keys_list.clear() ns_prefix = 'namespaced:%s:' % self.namespace keys = sorted([ k[len(ns_prefix):] for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix) ]) for key in keys: self.keys_list.addItem(key) self.keys_list.setMinimumWidth(self.keys_list.sizeHintForColumn(0)) self.keys_list.currentRowChanged[int].connect( self._current_row_changed) def _current_row_changed(self, new_row): if new_row < 0: self.value_text.clear() return key = unicode(self.keys_list.currentItem().text()) val = self.db.prefs.get_namespaced(self.namespace, key, '') self.value_text.setPlainText(self.db.prefs.to_raw(val))
class PrefsViewerDialog(SizePersistedDialog): def __init__(self, gui, namespace): SizePersistedDialog.__init__(self, gui, 'Prefs Viewer dialog') self.setWindowTitle('Preferences for: '+namespace) self.db = gui.current_db self.namespace = namespace self._init_controls() self.resize_dialog() self._populate_settings() if self.keys_list.count(): self.keys_list.setCurrentRow(0) def _init_controls(self): layout = QVBoxLayout(self) self.setLayout(layout) ml = QHBoxLayout() layout.addLayout(ml, 1) self.keys_list = QListWidget(self) self.keys_list.setSelectionMode(QAbstractItemView.SingleSelection) self.keys_list.setFixedWidth(150) self.keys_list.setAlternatingRowColors(True) ml.addWidget(self.keys_list) self.value_text = QTextEdit(self) self.value_text.setTabStopWidth(24) self.value_text.setReadOnly(True) ml.addWidget(self.value_text, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok) button_box.accepted.connect(self.accept) button_box.setCenterButtons(True) layout.addWidget(button_box) def _populate_settings(self): self.keys_list.clear() ns_prefix = 'namespaced:%s:'% self.namespace keys = sorted([k[len(ns_prefix):] for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix)]) for key in keys: self.keys_list.addItem(key) self.keys_list.setMinimumWidth(self.keys_list.sizeHintForColumn(0)) self.keys_list.currentRowChanged[int].connect(self._current_row_changed) def _current_row_changed(self, new_row): if new_row < 0: self.value_text.clear() return key = unicode(self.keys_list.currentItem().text()) val = self.db.prefs.get_namespaced(self.namespace, key, '') self.value_text.setPlainText(self.db.prefs.to_raw(val))
class SearchDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:search dialog') self.setWindowTitle('Search Casanova:') self.gui = parent self.mm = mm layout = QVBoxLayout(self) self.setLayout(layout) self.search_label = QLabel('Search for:') layout.addWidget(self.search_label) self.search_str = QLineEdit(self) self.search_str.setText('') layout.addWidget(self.search_str) self.search_label.setBuddy(self.search_str) self.find_button = QPushButton("&Find") self.search_button_box = QDialogButtonBox(Qt.Horizontal) self.search_button_box.addButton(self.find_button, QDialogButtonBox.ActionRole) self.search_button_box.clicked.connect(self._find_clicked) layout.addWidget(self.search_button_box) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self, choices): self.values_list.clear() for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id, )) self.values_list.addItem(item) def _find_clicked(self): query = unicode(self.search_str.text()) self._display_choices(self.mm.search(query)) def _accept_clicked(self): #self._save_preferences() self.selected_texts = [] for item in self.values_list.selectedItems(): self.selected_texts.append(item.data(1).toPyObject()[0]) self.accept()
class SearchDialog(SizePersistedDialog): def __init__(self, parent=None, func=None, title="Search"): SizePersistedDialog.__init__(self, parent, 'arg plugin:search dialog') self.setWindowTitle(title) self.gui = parent self.func = func layout = QVBoxLayout(self) self.setLayout(layout) self.search_label = QLabel(title) layout.addWidget(self.search_label) self.search_str = QLineEdit(self) self.search_str.setText('') layout.addWidget(self.search_str) self.search_label.setBuddy(self.search_str) self.find_button = QPushButton("&Find") self.search_button_box = QDialogButtonBox(Qt.Horizontal) self.search_button_box.addButton(self.find_button, QDialogButtonBox.ActionRole) self.search_button_box.clicked.connect(self._find_clicked) layout.addWidget(self.search_button_box) self.values_list = QListWidget(self) # for multiple selection #self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self, choices): self.values_list.clear() for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id,)) self.values_list.addItem(item) def _find_clicked(self): query = unicode(self.search_str.text()) self._display_choices(self.func(query)) def _accept_clicked(self): #self._save_preferences() self.selected_result = None if self.values_list.currentItem(): i = self.values_list.currentItem() self.selected_result = (i.data(1)[0], i.text()) self.accept()
class ChooseFormatToDownloadDialog(SizePersistedDialog): def __init__(self, parent=None, dm=None, casanova_id=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:format download dialog') self.setWindowTitle('Select format to download:') self.gui = parent self.dm = dm self.casanova_id = casanova_id layout = QVBoxLayout(self) self.setLayout(layout) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_formats() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_formats(self): self.values_list.clear() formats = self.dm.get_download_info(self.casanova_id) if isinstance(formats, list): for format in formats: item = QListWidgetItem(get_icon('images/books.png'), format['type'], self.values_list) item.setData(1, (format, )) self.values_list.addItem(item) else: return error_dialog(self.gui, 'Casanova message', unicode(formats), show=True) def _accept_clicked(self): #self._save_preferences() self.selected_format = None for item in self.values_list.selectedItems(): self.selected_format = item.data(1).toPyObject()[0] self.accept()
class ChoosePluginToolbarsDialog(QDialog): def __init__(self, parent, plugin, locations): QDialog.__init__(self, parent) self.locations = locations self.setWindowTitle( _('Add "%s" to toolbars or menus')%plugin.name) self._layout = QVBoxLayout(self) self.setLayout(self._layout) self._header_label = QLabel( _('Select the toolbars and/or menus to add <b>%s</b> to:') % plugin.name) self._layout.addWidget(self._header_label) self._locations_list = QListWidget(self) self._locations_list.setSelectionMode(QAbstractItemView.MultiSelection) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self._locations_list.setSizePolicy(sizePolicy) for key, text in locations: self._locations_list.addItem(text) if key in {'toolbar', 'toolbar-device'}: self._locations_list.item(self._locations_list.count()-1 ).setSelected(True) self._layout.addWidget(self._locations_list) self._footer_label = QLabel( _('You can also customise the plugin locations ' 'using <b>Preferences -> Customise the toolbar</b>')) self._layout.addWidget(self._footer_label) 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()) def selected_locations(self): selected = [] for row in self._locations_list.selectionModel().selectedRows(): selected.append(self.locations[row.row()]) return selected
class ChoosePluginToolbarsDialog(QDialog): def __init__(self, parent, plugin, locations): QDialog.__init__(self, parent) self.locations = locations self.setWindowTitle(_('Add "%s" to toolbars or menus') % plugin.name) self._layout = QVBoxLayout(self) self.setLayout(self._layout) self._header_label = QLabel( _('Select the toolbars and/or menus to add <b>%s</b> to:') % plugin.name) self._layout.addWidget(self._header_label) self._locations_list = QListWidget(self) self._locations_list.setSelectionMode(QAbstractItemView.MultiSelection) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self._locations_list.setSizePolicy(sizePolicy) for key, text in locations: self._locations_list.addItem(text) if key in {'toolbar', 'toolbar-device'}: self._locations_list.item(self._locations_list.count() - 1).setSelected(True) self._layout.addWidget(self._locations_list) self._footer_label = QLabel( _('You can also customise the plugin locations ' 'using <b>Preferences -> Customise the toolbar</b>')) self._layout.addWidget(self._footer_label) 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()) def selected_locations(self): selected = [] for row in self._locations_list.selectionModel().selectedRows(): selected.append(self.locations[row.row()]) return selected
class ChooseFormatToDownloadDialog(SizePersistedDialog): def __init__(self, parent=None, dm=None, casanova_id=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:format download dialog') self.setWindowTitle('Select format to download:') self.gui = parent self.dm = dm self.casanova_id = casanova_id layout = QVBoxLayout(self) self.setLayout(layout) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_formats() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_formats(self): self.values_list.clear() formats = self.dm.get_download_info(self.casanova_id) if isinstance(formats, list): for format in formats: item = QListWidgetItem(get_icon('images/books.png'), format['type'], self.values_list) item.setData(1, (format,)) self.values_list.addItem(item) else: return error_dialog(self.gui, 'Casanova message', unicode(formats), show=True) def _accept_clicked(self): #self._save_preferences() self.selected_format = None for item in self.values_list.selectedItems(): self.selected_format = item.data(1).toPyObject()[0] self.accept()
def __init__(self, dev, ignored_folders=None, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel( "<p>" + _("<b>Scanned folders:</b>") + " " + _("You can select which top level folders calibre will " "scan when searching this device for books.") ) la.setWordWrap(True) l.addWidget(la) self.tabs = QTabWidget(self) l.addWidget(self.tabs) self.widgets = [] for storage in dev.filesystem_cache.entries: w = QListWidget(self) w.storage = storage self.tabs.addTab(w, storage.name) self.widgets.append(w) for child in sorted(storage.folders, key=attrgetter("name")): i = QListWidgetItem(child.name) i.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) i.setCheckState( Qt.Unchecked if dev.is_folder_ignored(storage, child.name, ignored_folders=ignored_folders) else Qt.Checked ) w.addItem(i) self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.sab = self.bb.addButton(_("Select &All"), self.bb.ActionRole) self.sab.clicked.connect(self.select_all) self.snb = self.bb.addButton(_("Select &None"), self.bb.ActionRole) self.snb.clicked.connect(self.select_none) l.addWidget(self.bb) self.setWindowTitle(_("Choose folders to scan")) self.setWindowIcon(QIcon(I("devices/tablet.png"))) self.resize(500, 500)
class ChooseIssuesToUpdateDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:issues update dialog') self.setWindowTitle('Select issues to update:') self.gui = parent self.mm = mm layout = QVBoxLayout(self) self.setLayout(layout) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_issues() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_issues(self): self.values_list.clear() issues = self.mm.get_all_issues(True) for id, issue in issues: item = QListWidgetItem(get_icon('images/books.png'), issue, self.values_list) item.setData(1, (id, )) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() self.selected_issues = [] for item in self.values_list.selectedItems(): self.selected_issues.append(item.data(1).toPyObject()[0]) self.accept()
def __init__(self, dev, ignored_folders=None, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel( '<p>' + _('<b>Scanned folders:</b>') + ' ' + _('You can select which top level folders calibre will ' 'scan when searching this device for books.')) la.setWordWrap(True) l.addWidget(la) self.tabs = QTabWidget(self) l.addWidget(self.tabs) self.widgets = [] for storage in dev.filesystem_cache.entries: w = QListWidget(self) w.storage = storage self.tabs.addTab(w, storage.name) self.widgets.append(w) for child in sorted(storage.folders, key=attrgetter('name')): i = QListWidgetItem(child.name) i.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) i.setCheckState(Qt.Unchecked if dev.is_folder_ignored( storage, child.name, ignored_folders=ignored_folders ) else Qt.Checked) w.addItem(i) self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.sab = self.bb.addButton(_('Select &All'), self.bb.ActionRole) self.sab.clicked.connect(self.select_all) self.snb = self.bb.addButton(_('Select &None'), self.bb.ActionRole) self.snb.clicked.connect(self.select_none) l.addWidget(self.bb) self.setWindowTitle(_('Choose folders to scan')) self.setWindowIcon(QIcon(I('devices/tablet.png'))) self.resize(500, 500)
class ChooseIssuesToUpdateDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:issues update dialog') self.setWindowTitle('Select issues to update:') self.gui = parent self.mm = mm layout = QVBoxLayout(self) self.setLayout(layout) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_issues() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_issues(self): self.values_list.clear() issues = self.mm.get_all_issues(True) for id, issue in issues: item = QListWidgetItem(get_icon('images/books.png'), issue, self.values_list) item.setData(1, (id,)) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() self.selected_issues = [] for item in self.values_list.selectedItems(): self.selected_issues.append(item.data(1).toPyObject()[0]) self.accept()
class AddBookDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None, mi = None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:add book dialog') self.setWindowTitle('Add text to Casanova:') self.gui = parent self.mm = mm self.mi = mi self.one_line_description = '' layout = QVBoxLayout(self) self.setLayout(layout) self.one_liner_label = QLabel('Enter a short description (255 chars max) before pressing OK') layout.addWidget(self.one_liner_label) self.one_liner_str = QLineEdit(self) self.one_liner_str.setText('') layout.addWidget(self.one_liner_str) self.one_liner_label.setBuddy(self.one_liner_str) self.values_label = QLabel('Below are potential matches of texts that already exist - please make sure you are adding something new') layout.addWidget(self.values_label) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_choices() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self): self.values_list.clear() choices = self.mm.search(self.mi.title) if choices is None or len(choices)==0: item = QListWidgetItem(get_icon('images/books.png'), _('there seem to be no matches'), self.values_list) self.values_list.addItem(item) for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id,)) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() one_liner = unicode(self.one_liner_str.text()) if one_liner=='': self.values_list.clear() item = QListWidgetItem(get_icon('images/books.png'), _('you need to enter a short description'), self.values_list) self.values_list.addItem(item) else: self.one_line_description = one_liner self.accept()
class AddBookDialog(SizePersistedDialog): def __init__(self, parent=None, mm=None, mi=None): SizePersistedDialog.__init__(self, parent, 'casanova plugin:add book dialog') self.setWindowTitle('Add text to Casanova:') self.gui = parent self.mm = mm self.mi = mi self.one_line_description = '' layout = QVBoxLayout(self) self.setLayout(layout) self.one_liner_label = QLabel( 'Enter a short description (255 chars max) before pressing OK') layout.addWidget(self.one_liner_label) self.one_liner_str = QLineEdit(self) self.one_liner_str.setText('') layout.addWidget(self.one_liner_str) self.one_liner_label.setBuddy(self.one_liner_str) self.values_label = QLabel( 'Below are potential matches of texts that already exist - please make sure you are adding something new' ) layout.addWidget(self.values_label) self.values_list = QListWidget(self) self.values_list.setSelectionMode(QAbstractItemView.ExtendedSelection) layout.addWidget(self.values_list) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self._accept_clicked) self.button_box.rejected.connect(self.reject) layout.addWidget(self.button_box) self._display_choices() # Cause our dialog size to be restored from prefs or created on first usage self.resize_dialog() def _display_choices(self): self.values_list.clear() choices = self.mm.search(self.mi.title) if choices is None or len(choices) == 0: item = QListWidgetItem(get_icon('images/books.png'), _('there seem to be no matches'), self.values_list) self.values_list.addItem(item) for id, name in choices.items(): item = QListWidgetItem(get_icon('images/books.png'), name, self.values_list) item.setData(1, (id, )) self.values_list.addItem(item) def _accept_clicked(self): #self._save_preferences() one_liner = unicode(self.one_liner_str.text()) if one_liner == '': self.values_list.clear() item = QListWidgetItem(get_icon('images/books.png'), _('you need to enter a short description'), self.values_list) self.values_list.addItem(item) else: self.one_line_description = one_liner self.accept()
class ManageKeysDialog(QDialog): def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u""): QDialog.__init__(self,parent) self.parent = parent self.key_type_name = key_type_name self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext self.import_key = (keyfile_ext != u"") self.binary_file = (key_type_name == u"Adobe Digital Editions Key") self.json_file = (key_type_name == u"Kindle for Mac and PC Key") self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) # Start Qt Gui dialog layout layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) layout.addWidget(keys_group_box) keys_group_box_layout = QHBoxLayout() keys_group_box.setLayout(keys_group_box_layout) self.listy = QListWidget(self) self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name)) self.listy.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_list() keys_group_box_layout.addWidget(self.listy) button_layout = QVBoxLayout() keys_group_box_layout.addLayout(button_layout) self._add_key_button = QtGui.QToolButton(self) self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name)) self._add_key_button.setIcon(QIcon(I('plus.png'))) self._add_key_button.clicked.connect(self.add_key) button_layout.addWidget(self._add_key_button) self._delete_key_button = QtGui.QToolButton(self) self._delete_key_button.setToolTip(_(u"Delete highlighted key")) self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) self._delete_key_button.clicked.connect(self.delete_key) button_layout.addWidget(self._delete_key_button) if type(self.plugin_keys) == dict: self._rename_key_button = QtGui.QToolButton(self) self._rename_key_button.setToolTip(_(u"Rename highlighted key")) self._rename_key_button.setIcon(QIcon(I('edit-select-all.png'))) self._rename_key_button.clicked.connect(self.rename_key) button_layout.addWidget(self._rename_key_button) self.export_key_button = QtGui.QToolButton(self) self.export_key_button.setToolTip(u"Save highlighted key to a .{0} file".format(self.keyfile_ext)) self.export_key_button.setIcon(QIcon(I('save.png'))) self.export_key_button.clicked.connect(self.export_key) button_layout.addWidget(self.export_key_button) spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) button_layout.addItem(spacerItem) layout.addSpacing(5) migrate_layout = QHBoxLayout() layout.addLayout(migrate_layout) if self.import_key: migrate_layout.setAlignment(Qt.AlignJustify) self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self) self.migrate_btn.setToolTip(u"Import *.{0} files (created using other tools).".format(self.keyfile_ext)) self.migrate_btn.clicked.connect(self.migrate_wrapper) migrate_layout.addWidget(self.migrate_btn) migrate_layout.addStretch() self.button_box = QDialogButtonBox(QDialogButtonBox.Close) self.button_box.rejected.connect(self.close) migrate_layout.addWidget(self.button_box) self.resize(self.sizeHint()) def populate_list(self): if type(self.plugin_keys) == dict: for key in self.plugin_keys.keys(): self.listy.addItem(QListWidgetItem(key)) else: for key in self.plugin_keys: self.listy.addItem(QListWidgetItem(key)) def add_key(self): d = self.create_key(self) d.exec_() if d.result() != d.Accepted: # New key generation cancelled. return new_key_value = d.key_value if type(self.plugin_keys) == dict: if new_key_value in self.plugin_keys.values(): old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added.".format(old_key_name,self.key_type_name), show=True) return self.plugin_keys[d.key_name] = new_key_value else: if new_key_value in self.plugin_keys: info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name), show=True) return self.plugin_keys.append(d.key_value) self.listy.clear() self.populate_list() def rename_key(self): if not self.listy.currentItem(): errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format(self.key_type_name) r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return d = RenameKeyDialog(self) d.exec_() if d.result() != d.Accepted: # rename cancelled or moot. return keyname = unicode(self.listy.currentItem().text().toUtf8(),'utf8') if not question_dialog(self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?".format(keyname,d.key_name,self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys[d.key_name] = self.plugin_keys[keyname] del self.plugin_keys[keyname] self.listy.clear() self.populate_list() def delete_key(self): if not self.listy.currentItem(): return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return if type(self.plugin_keys) == dict: del self.plugin_keys[keyname] else: self.plugin_keys.remove(keyname) self.listy.clear() self.populate_list() def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. help_file_name = u"{0}_{1}_Help.htm".format(PLUGIN_NAME, self.key_type_name) file_path = os.path.join(config_dir, u"plugins", u"DeDRM", u"help", help_file_name) with open(file_path,'w') as f: f.write(self.parent.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url)) def migrate_files(self): dynamic[PLUGIN_NAME + u"config_dir"] = config_dir files = choose_files(self, PLUGIN_NAME + u"config_dir", u"Select {0} files to import".format(self.key_type_name), [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])], False) counter = 0 skipped = 0 if files: for filename in files: fpath = os.path.join(config_dir, filename) filename = os.path.basename(filename) new_key_name = os.path.splitext(os.path.basename(filename))[0] with open(fpath,'rb') as keyfile: new_key_value = keyfile.read() if self.binary_file: new_key_value = new_key_value.encode('hex') elif self.json_file: new_key_value = json.loads(new_key_value) match = False for key in self.plugin_keys.keys(): if uStrCmp(new_key_name, key, True): skipped += 1 msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file <strong>{1}</strong>.\nRename the existing key and import again".format(new_key_name,filename) inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) match = True break if not match: if new_key_value in self.plugin_keys.values(): old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] skipped += 1 info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True) else: counter += 1 self.plugin_keys[new_key_name] = new_key_value msg = u"" if counter+skipped > 1: if counter > 0: msg += u"Imported <strong>{0:d}</strong> key {1}. ".format(counter, u"file" if counter == 1 else u"files") if skipped > 0: msg += u"Skipped <strong>{0:d}</strong> key {1}.".format(skipped, u"file" if counter == 1 else u"files") inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) return counter > 0 def migrate_wrapper(self): if self.migrate_files(): self.listy.clear() self.populate_list() def export_key(self): if not self.listy.currentItem(): errmsg = u"No keyfile selected to export. Highlight a keyfile first." r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return filter = QString(u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext)) keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if dynamic.get(PLUGIN_NAME + 'save_dir'): defaultname = os.path.join(dynamic.get(PLUGIN_NAME + 'save_dir'), u"{0}.{1}".format(keyname , self.keyfile_ext)) else: defaultname = os.path.join(os.path.expanduser('~'), u"{0}.{1}".format(keyname , self.keyfile_ext)) filename = unicode(QtGui.QFileDialog.getSaveFileName(self, u"Save {0} File as...".format(self.key_type_name), defaultname, u"{0} Files (*.{1})".format(self.key_type_name,self.keyfile_ext), filter)) if filename: dynamic[PLUGIN_NAME + 'save_dir'] = os.path.split(filename)[0] with file(filename, 'w') as fname: if self.binary_file: fname.write(self.plugin_keys[keyname].decode('hex')) elif self.json_file: fname.write(json.dumps(self.plugin_keys[keyname])) else: fname.write(self.plugin_keys[keyname])
class tab_widget(QtGui.QTabWidget): # Initiate Widget. def __init__(self, parent=MainWindow): super(tab_widget, self).__init__() self.initUI() # Create interface, and connect buttons to signals. def initUI(self): vbox_inner = QVBoxLayout() grid = QtGui.QGridLayout() self.genreList = ['Fiction', 'Fact book', 'Poetry'] # Tab 1: Add Data self.author_label = QLabel("Author") self.author_text = QLineEdit() self.author_text.setPlaceholderText("Author") grid.addWidget(self.author_label, 0, 0) grid.addWidget(self.author_text, 1, 0) self.title_label = QLabel("Title") self.title_text = QLineEdit() self.title_text.setPlaceholderText("Title") grid.addWidget(self.title_label, 0, 1) grid.addWidget(self.title_text, 1, 1) self.date_label = QLabel("Date Read") self.date_text = QLineEdit() self.date_text.setPlaceholderText("yy-mm-dd") grid.addWidget(self.date_label, 2, 1) grid.addWidget(self.date_text, 3, 1) self.grade_label = QLabel("Grade") self.grade_text = QLineEdit() self.grade_text.setPlaceholderText("Grade 1-5") grid.addWidget(self.grade_label, 2, 0) grid.addWidget(self.grade_text, 3, 0) self.comments_label = QLabel("Comments") self.comments_text = QLineEdit() self.comments_text.setPlaceholderText("Comments here") grid.addWidget(self.comments_label, 4, 0) grid.addWidget(self.comments_text, 5, 0) self.genre_label = QLabel("Genre") self.genre_list = QListWidget(self) self.genre_list.addItems(self.genreList) self.genre_list.setObjectName('genre_list') self.genre_list.itemClicked.connect(self.item_clicked) grid.addWidget(self.genre_label, 6, 0) grid.addWidget(self.genre_list, 7, 0) self.genre2_label = QLabel("Genre2") self.genre2_list = QListWidget(self) self.genre2_list.setObjectName("genre2") self.genre2_list.addItem("Select genre first") grid.addWidget(self.genre2_label, 6, 1) grid.addWidget(self.genre2_list, 7, 1) # Tab 2:Get Data from file self.authorData = QLineEdit() self.authorData.setPlaceholderText("Author") self.authorData.setReadOnly(True) vbox_inner.addWidget(self.authorData) self.titleData = QLineEdit() self.titleData.setPlaceholderText("Title") self.titleData.setReadOnly(True) vbox_inner.addWidget(self.titleData) self.genreData = QLineEdit() self.genreData.setPlaceholderText("Genre") self.genreData.setReadOnly(True) vbox_inner.addWidget(self.genreData) self.genre2Data = QLineEdit() self.genre2Data.setPlaceholderText("Genre2") self.genre2Data.setReadOnly(True) vbox_inner.addWidget(self.genre2Data) self.dateData = QLineEdit() self.dateData.setPlaceholderText("Date read") self.dateData.setReadOnly(True) vbox_inner.addWidget(self.dateData) self.gradeData = QLineEdit() self.gradeData.setPlaceholderText("Grade") self.gradeData.setReadOnly(True) vbox_inner.addWidget(self.gradeData) self.commentsData = QLineEdit() self.commentsData.setPlaceholderText("Comments") self.commentsData.setReadOnly(True) vbox_inner.addWidget(self.commentsData) self.titles_list = QListWidget(self) self.titles_list.addItems(getTitlesFromFile()) vbox_inner.addWidget(self.titles_list) self.getTitleData = QtGui.QPushButton("Get title data", self) self.getTitleData.clicked.connect(self.buttonClicked) vbox_inner.addWidget(self.getTitleData) self.submit = QtGui.QPushButton("Submit Data", self) self.submit.clicked.connect(self.buttonClicked) grid.addWidget(self.submit, 8, 1) self.quit = QtGui.QPushButton("Exit", self) self.quit.clicked.connect(QtCore.QCoreApplication.instance().quit) self.quit.setMaximumWidth(80) grid.addWidget(self.quit, 8, 0) tab1 = QWidget() tab1.setLayout(grid) tab2 = QWidget() tab2.setLayout(vbox_inner) self.addTab(tab1, "Add Data") self.addTab(tab2, "Get Data") self.move(150, 150) self.show() # Function for when a QListWidgetItem is clicked if the genre_list is # clicked, will check which genre was chosen and populate genre2_list # with subgenres of that genre. def item_clicked(self): genre = self.sender() if genre.objectName() == "genre_list": curr = genre.currentItem().text() if curr == self.genreList[0]: genre2List = ["Detective", "autobiograpyh", "Horror", "Comedy"] elif curr == self.genreList[1]: genre2List = ["Technology", "Biology", "Chemistry", "Mathematics"] elif curr == self.genreList[2]: genre2List = ["Tirade", "Ballads", "Rhyme"] else: genre2List = ["None"] self.genre2_list.clear() self.genre2_list.addItems(genre2List) # Function for when a button is clicked, if 'Submit Data' is clicked, # will check that all input is correct format and if so write # the data to the file. If the button pressed is 'Get title data' # will get the selected title in the QListWidget and show the row data def buttonClicked(self): sender = self.sender() if sender.text() == "Get title data": if self.titles_list.currentItem() != None: titleToGet = str(self.titles_list.currentItem().text()) titleData = findTitleData(titleToGet) splitLine = [] splitLine = titleData.split(",", 7) self.authorData.setText('Author: '+splitLine[0].replace('"', "").lstrip()) self.titleData.setText('Title: '+splitLine[1].replace('"', "").lstrip()) self.genreData.setText('Genre: '+splitLine[2].replace('"', "").lstrip()) self.genre2Data.setText('Genre2: '+splitLine[3].replace('"', "").lstrip()) self.dateData.setText('Date Read: '+splitLine[4].replace('"', "").lstrip()) self.gradeData.setText('Grade: '+splitLine[5].replace('"', "").lstrip()) self.commentsData.setText('Comments: '+splitLine[6].replace('"', "").lstrip()) elif sender.text() == "Submit Data": comments = str(self.comments_text.text()) while True: author = str(self.author_text.text()) if containsDigit(author) == True: QMessageBox.about(self, "Wrong input", "Error: Author cant contain digits") break if len(author) == 0: QMessageBox.about(self, "Wrong input", "Author is a required field") break title = str(self.title_text.text()) try: title = str(self.title_text.text()) except: QMessageBox.about(self, "Wrong input", "Error in comments, only A-z, 1-9 allowed") break if len(title) == 0: QMessageBox.about(self, "Wrong input", "Title is a required field") break if self.genre_list.currentItem() != None: genre = str(self.genre_list.currentItem().text()) else: QMessageBox.about(self, "Wrong input", "Error: Need to pick genre") break if self.genre2_list.currentItem() != None: genre2 = str(self.genre2_list.currentItem().text()) else: QMessageBox.about(self, "Wrong input", "Error: Need to pick genre2") break d = str(self.date_text.text()) if len(d) == 0: QMessageBox.about(self, "Wrong input", "Date is a required field") break try: dateRead = datetime.datetime.strptime(d, '%y-%m-%d').date() except: QMessageBox.about(self, "Wrong input", "Error: Date needs to be in format: yy-mm-dd") break try: grade = int(str(self.grade_text.text())) except: QMessageBox.about(self, "Wrong input", "Error: Grade needs to be a number between 1-5") break if grade > 5 or grade < 1: QMessageBox.about(self, "Wrong input", "Error: Grade needs to be a number between 1-5") break try: comments = str(self.comments_text.text()) except: QMessageBox.about(self, "Wrong input", "Error: in comments, only A-z, 1-9 allowed") break if len(comments) == 0: comments = "No comments" writeDataToFile(author, title, genre, genre2, str(dateRead), str(grade), comments) self.titles_list.clear() self.titles_list.addItems(getTitlesFromFile()) QMessageBox.about(self, "Information", "Data added successfully") break
class PluginObject(object): tabName = 'Pass Phrase Finder' maxVersion = '0.93.99' ############################################################################# def __init__(self, main): self.searchThread = None self.passPhraseFinder = None self.isSearchOver = False def updateResults(resultStr): self.resultStr += resultStr def updateDisplay(): if len(self.resultStr) > 0: self.resultsDisplay.append(self.resultStr) self.resultStr = '' self.resultsDisplay.moveCursor(QtGui.QTextCursor.End) self.resultsDisplay.repaint() if self.isSearchOver: endSearch() # Call this from another thread to end the search def terminateSearch(): self.isSearchOver = True # Call this from the main thread to end the search def endSearch(): self.main.extraHeartbeatAlways.remove(updateDisplay) self.searchButton.setEnabled(True) self.stopButton.setEnabled(False) # If the thread is still searching tell the pass phrase finder to stop if self.passPhraseFinder and self.searchThread and not self.searchThread.isFinished(): self.passPhraseFinder.isStopped = True def searchForPassphrase(): # Get the selected wallet from the main screen wlt = self.getSelectedWlt() if wlt and not wlt.watchingOnly and wlt.isLocked: self.resultStr = '' self.passPhraseFinder = PassPhraseFinder(wlt) self.resultsDisplay.setText(QString('')) self.main.extraHeartbeatAlways.append(updateDisplay) if len(self.segOrdStrSet) > 0: # From self.segOrdStrList, create a list of lists of indexes that describe the segment orderings to search # In other words convert all of the strings in orderings list to lists of integers segOrdIntListList = [] for ordStr in self.segOrdStrSet: # The indexes provided by the users are 1 based, and the list indexes ought to be 0 based segOrdIntListList.append([int(indexStr)-1 for indexStr in ordStr.split(',')]) self.searchThread = PyBackgroundThread(self.passPhraseFinder.searchForPassPhrase, [segDef.getSegList() for segDef in self.segDefList], segOrdIntListList, updateResults, terminateSearch ) # Reset the isSearchOver flag self.isSearchOver = False self.searchThread.start() # Disable search button adn enabled stop button self.stopButton.setEnabled(True) self.searchButton.setEnabled(False) else: QMessageBox.warning(self.main, tr('Invalid'), tr(""" There are no valid segment combinations to search. Please add at least one segment and ordering to search."""), QMessageBox.Ok) else: QMessageBox.warning(self.main, tr('Invalid'), tr(""" No valid wallet is selected. Please select a locked non-watching-only from Available Wallets."""), QMessageBox.Ok) def addKnownSegment(): dlgEnterSegment = DlgEnterSegment(main, main) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) if len(segmentText)>0: self.segDefList.append(KnownSeg(segmentText)) self.segDefTableModel.updateSegList(self.segDefList) def addUnknownCaseSegment(): dlgEnterSegment = DlgEnterSegment(main, main) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) if len(segmentText)>0: self.segDefList.append(UnknownCaseSeg(segmentText)) self.segDefTableModel.updateSegList(self.segDefList) def addUnknownOrderSegment(): dlgEnterSegment = DlgEnterSegment(main, main, isUnknownOrder=True) if dlgEnterSegment.exec_(): segmentText = str(dlgEnterSegment.editSegment.text()) minLen = int(str(dlgEnterSegment.minSelector.currentText())) maxLen = int(str(dlgEnterSegment.maxSelector.currentText())) if len(segmentText)>0: self.segDefList.append(UnknownSeg(segmentText, minLen, maxLen)) self.segDefTableModel.updateSegList(self.segDefList) def addOrdering(): if len(self.segDefList) > 0: dlgSpecifyOrdering = DlgSpecifyOrdering(main, main, len(self.segDefList)) if dlgSpecifyOrdering.exec_(): self.segOrdStrSet.add(str(dlgSpecifyOrdering.parseOrderingList()).strip('[]')) self.updateOrderingListBox() else: QMessageBox.warning(self.main, tr('Not Ready'), tr(""" No segments have been entered. You must enter some segments before you can order them."""), QMessageBox.Ok) self.main = main self.segDefList = [] self.segOrdStrSet = set() segmentHeader = QRichLabel(tr("""<b>Build segments for pass phrase search: </b>"""), doWrap=False) self.knownButton = QPushButton("Add Known Segment") self.unknownCaseButton = QPushButton("Add Unknown Case Segment") self.unknownOrderButton = QPushButton("Add Unknown Order Segment") self.main.connect(self.knownButton, SIGNAL('clicked()'), addKnownSegment) self.main.connect(self.unknownCaseButton, SIGNAL('clicked()'), addUnknownCaseSegment) self.main.connect(self.unknownOrderButton, SIGNAL('clicked()'), addUnknownOrderSegment) topRow = makeHorizFrame([segmentHeader, self.knownButton, self.unknownCaseButton, self.unknownOrderButton, 'stretch']) self.segDefTableModel = SegDefDisplayModel() self.segDefTableView = QTableView() self.segDefTableView.setModel(self.segDefTableModel) self.segDefTableView.setSelectionBehavior(QTableView.SelectRows) self.segDefTableView.setSelectionMode(QTableView.SingleSelection) self.segDefTableView.verticalHeader().setDefaultSectionSize(20) self.segDefTableView.verticalHeader().hide() h = tightSizeNChar(self.segDefTableView, 1)[1] self.segDefTableView.setMinimumHeight(2 * (1.3 * h)) self.segDefTableView.setMaximumHeight(10 * (1.3 * h)) initialColResize(self.segDefTableView, [.1, .2, .4, .1, .1, .1]) self.segDefTableView.customContextMenuRequested.connect(self.showSegContextMenu) self.segDefTableView.setContextMenuPolicy(Qt.CustomContextMenu) segmentOrderingsHeader = QRichLabel(tr("""<b>Specify orderings for pass phrase search: </b>"""), doWrap=False) self.addOrderingButton = QPushButton("Add Ordering") self.main.connect(self.addOrderingButton, SIGNAL('clicked()'), addOrdering) orderingButtonPanel = makeHorizFrame([segmentOrderingsHeader, self.addOrderingButton, 'stretch']) self.segOrdListBox = QListWidget() self.segOrdListBox.customContextMenuRequested.connect(self.showOrdContextMenu) self.segOrdListBox.setContextMenuPolicy(Qt.CustomContextMenu) self.searchButton = QPushButton("Search") self.main.connect(self.searchButton, SIGNAL('clicked()'), searchForPassphrase) self.stopButton = QPushButton("Stop Searching") self.stopButton.setEnabled(False) self.main.connect(self.stopButton, SIGNAL('clicked()'), endSearch) totalSearchLabel = QRichLabel(tr("""<b>Total Passphrase Tries To Search: </b>"""), doWrap=False) self.totalSearchTriesDisplay = QLineEdit() self.totalSearchTriesDisplay.setReadOnly(True) self.totalSearchTriesDisplay.setText(QString('0')) self.totalSearchTriesDisplay.setFont(GETFONT('Fixed')) self.totalSearchTriesDisplay.setMinimumWidth(tightSizeNChar(self.totalSearchTriesDisplay, 6)[0]) self.totalSearchTriesDisplay.setMaximumWidth(tightSizeNChar(self.totalSearchTriesDisplay, 12)[0]) searchButtonPanel = makeHorizFrame([self.searchButton, self.stopButton, 'stretch', totalSearchLabel, self.totalSearchTriesDisplay]) self.resultsDisplay = QTextEdit() self.resultsDisplay.setReadOnly(True) self.resultsDisplay.setFont(GETFONT('Fixed')) self.resultsDisplay.setMinimumHeight(100) self.searchPanel = makeVertFrame([topRow, self.segDefTableView, orderingButtonPanel, self.segOrdListBox, searchButtonPanel, self.resultsDisplay, 'stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(self.searchPanel) def getSelectedWlt(self): wlt = None selectedWltList = self.main.walletsView.selectedIndexes() if len(selectedWltList)>0: row = selectedWltList[0].row() wltID = str(self.main.walletsView.model().index(row, WLTVIEWCOLS.ID).data().toString()) wlt = self.main.walletMap[wltID] return wlt def showSegContextMenu(self): menu = QMenu(self.segDefTableView) if len(self.segDefTableView.selectedIndexes())==0: return row = self.segDefTableView.selectedIndexes()[0].row() deleteSegMenuItem = menu.addAction("Delete Segment") action = menu.exec_(QCursor.pos()) if action == deleteSegMenuItem: self.deleteSegRow(row) def showOrdContextMenu(self): menu = QMenu(self.segOrdListBox) if len(self.segOrdListBox.selectedItems())==0: return item = self.segOrdListBox.currentItem() deleteOrdMenuItem = menu.addAction("Delete Ordering") action = menu.exec_(QCursor.pos()) if action == deleteOrdMenuItem: self.deleteOrdItem(item) def deleteSegRow(self, row): self.segDefList.remove(self.segDefList[row]) self.segDefTableModel.updateSegList(self.segDefList) self.segOrdStrSet.clear() self.updateOrderingListBox() def deleteOrdItem(self, ordItem): ordText = str(ordItem.text()) self.segOrdStrSet.remove(ordText) self.updateOrderingListBox() def getTabToDisplay(self): return self.tabToDisplay def updateOrderingListBox(self): self.segOrdListBox.clear() segOrdList = list(self.segOrdStrSet) segOrdList.sort() totalTries = 0 for ordStr in segOrdList: self.segOrdListBox.addItem(QListWidgetItem(ordStr)) totalTries += self.calculateTries(ordStr) if totalTries > BILLION_INT: self.totalSearchTriesDisplay.setText(OVER_BILLION_STR) else: self.totalSearchTriesDisplay.setText(str(totalTries)) def calculateTries(self, ordStr): ordIntList = [int(indexStr) for indexStr in ordStr.split(',')] totalTries = 1 # Multiply each of the totals of segment instance together. for ordInt in ordIntList: totalTries *= self.segDefList[ordInt-1].getSegListLen() return totalTries
class PM_Clipboard(PM_GroupBox): """ The PM_Clipboard class provides a groupbox containing a list of clipboard items that can be pasted in the 3D Workspace. The selected item in this list is shown by its elementViewer (an instance of L{PM_PreviewGroupBox}) The object being previewed can then be deposited into the 3D workspace. """ def __init__(self, parentWidget, title = 'Clipboard', win = None, elementViewer = None ): """ Appends a PM_Clipboard groupbox widget to I{parentWidget},a L{PM_Dialog} @param parentWidget: The parent dialog (Property manager) containing this widget. @type parentWidget: L{PM_Dialog} @param title: The title (button) text. @type title: str @param win: MainWindow object @type win: L{MWsemantics} or None @param elementViewer: The associated preview pane groupbox. If provided, The selected item in L{self.clipboardListWidget} is shown (previewed) by L{elementViewer}. The object being previewed can then be deposited into the 3D workspace. @type elementViewer: L{PM_PreviewGroupBox} or None """ self.w = win self.elementViewer = elementViewer self.elementViewer.setDisplay(diTUBES) self.pastableItems = None PM_GroupBox.__init__(self, parentWidget, title) self._loadClipboardGroupbox() def _loadClipboardGroupbox(self): """ Load the L{self.clipboardListWidget} widget used to display a list of clipboard items inside this clipboard groupbox. """ self.clipboardListWidget = QListWidget(self) self.gridLayout.addWidget(self.clipboardListWidget) #Append to the widget list. This is important for expand -collapse #functions (of the groupbox) to work properly. self._widgetList.append(self.clipboardListWidget) def _updateElementViewer(self, newModel = None): """ Update the view of L{self.elementViewer} @param newModel: The model correseponding to the item selected in L{self.clipboardListWidget}. @type newModel: L{molecule} or L{Group} """ if not self.elementViewer: return assert isinstance(self.elementViewer, MMKitView) self.elementViewer.resetView() if newModel: self.elementViewer.updateModel(newModel) def update(self): """ Updates the clipboard items in the L{PM_Clipboard} groupbox. Also updates its element viewer. """ PM_GroupBox.update(self) self.pastableItems = self.w.assy.shelf.getPastables() i = self.clipboardListWidget.currentRow() self.clipboardListWidget.clear() newModel = None if len(self.pastableItems): for item in self.pastableItems: self.clipboardListWidget.addItem(item.name) if i >= self.clipboardListWidget.count(): i = self.clipboardListWidget.count() - 1 if i < 0: i = 0 self.clipboardListWidget.setCurrentItem( self.clipboardListWidget.item(i)) newModel = self.pastableItems[i] self._updateElementViewer(newModel) def clipboardListItemChanged(self, currentItem = None, previousItem = None): """ Slot method. Called when user clicks on a different pastable item displayed in this groupbox @param currentItem: Current item in the L{self.clipboardListWidget} that is selected @type currentItem: U{B{QListWidgetItem} <http://doc.trolltech.com/4.2/qlistwidgetitem.html>} @param previousItem: Previously selected item in the L{self.clipboardListWidget} @type previousItem: U{B{QListWidgetItem} <http://doc.trolltech.com/4.2/qlistwidgetitem.html>} """ if not (currentItem or previousItem): return itemId = self.clipboardListWidget.row(currentItem) if itemId != -1: newChunk = self.pastableItems[itemId] self.clipboardListWidget.setCurrentRow(itemId) self._updateElementViewer(newChunk) def connect_or_disconnect_signals(self, isConnect): """ Connect or disconnect widget signals sent to their slot methods. @param isConnect: If True the widget will send the signals to the slot method. @type isConnect: boolean """ if isConnect: change_connect = self.w.connect else: change_connect = self.w.disconnect change_connect( self.clipboardListWidget, SIGNAL("currentItemChanged(QListWidgetItem*,QListWidgetItem*)"), self.clipboardListItemChanged ) def currentRow(self): """ Return the current row of the selected item in this groupbox's listwidget ( L{self.clipboardListWidget} ) @return: Current Row of the selected pastable item in the clipboard groupbox. @rtype: int """ currentRow = self.clipboardListWidget.currentRow() return currentRow
class LetsShareBooksDialog(QDialog): started_calibre_web_server = QtCore.pyqtSignal() calibre_didnt_start = QtCore.pyqtSignal() established_ssh_tunnel = QtCore.pyqtSignal() def __init__(self, gui, icon, do_user_config, qaction, us): QDialog.__init__(self, gui) self.main_gui = gui self.do_user_config = do_user_config self.qaction = qaction self.us = us self.initial = True self.lsb_url_text = 'Be a librarian. Share your library.' self.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.<<<<' self.lsb_url = 'nourl' if prefs['librarian'] == 'l' or prefs['librarian'] == '': self.librarian = get_libranon() else: self.librarian = prefs['librarian'] self.metadata_thread = MetadataLibThread(self.librarian) self.check_connection = ConnectionCheck() self.clip = QApplication.clipboard() self.pxmp = QPixmap() self.pxmp.load('images/icon_connected.png') self.icon_connected = QIcon(self.pxmp) self.setStyleSheet(""" QDialog { background-color: white; } QPushButton { font-size: 16px; border-style: solid; border-color: red; font-family:'BitstreamVeraSansMono',Consolas,monospace; text-transform: uppercase; } QPushButton#arrow { border-width: 16px; border-right-color:white; padding: -10px; color:red; } QPushButton#url { background-color: red; min-width: 460px; color: white; text-align: left; } QPushButton#url:hover { background-color: white; color: red; } QPushButton#share { background-color: red; color: white; margin-right: 10px; } QPushButton#share:hover { background-color: white; color: red; } QPushButton#url2 { color: #222; text-align: left; } QPushButton#url2:hover { color: red; } QLineEdit#edit { background-color: white; color: black; font-size: 16px; border-style: solid; border-color: red; font-family:'BitstreamVeraSansMono',Consolas,monospace; text-transform: uppercase; } """) self.ll = QVBoxLayout() #self.ll.setSpacing(1) self.l = QHBoxLayout() self.l.setSpacing(0) self.l.setMargin(0) #self.l.setContentsMargins(0,0,0,0) self.w = QWidget() self.w.setLayout(self.l) self.setLayout(self.ll) self.setWindowIcon(icon) self.debug_label = QLabel() self.ll.addWidget(self.debug_label) self.debug_label.show() self.lets_share_button = QPushButton() self.lets_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.lets_share_button.setObjectName("share") #self.lets_share_button.clicked.connect(self.lets_share) self.l.addWidget(self.lets_share_button) self.url_label = QPushButton() self.url_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.url_label.setObjectName("url") #self.url_label.clicked.connect(self.open_url) self.l.addWidget(self.url_label) self.arrow_button = QPushButton("_____") self.arrow_button.setObjectName("arrow") self.l.addWidget(self.arrow_button) self.ll.addWidget(self.w) self.ll.addSpacing(5) self.libranon_layout = QHBoxLayout() self.libranon_layout.setSpacing(0) self.libranon_layout.setMargin(0) #self.l.setContentsMargins(0,0,0,0) self.libranon_container = QWidget() self.libranon_container.setLayout(self.libranon_layout) self.edit = QLineEdit() self.edit.setObjectName("edit") self.edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.edit.setToolTip("Change your librarian name") self.edit.setText(self.librarian) #self.edit.textChanged.connect(self.handle_text_changed) self.save_libranon = QPushButton("librarian:") self.save_libranon.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.save_libranon.setObjectName("share") self.save_libranon.setToolTip("Save your librarian name") self.libranon_layout.addWidget(self.save_libranon) self.libranon_layout.addWidget(self.edit) self.save_libranon.clicked.connect(self.save_librarian) self.ll.addWidget(self.libranon_container) self.ll.addSpacing(10) self.chat_button = QPushButton("Chat room: https://chat.memoryoftheworld.org") #self.chat_button.hovered.connect(self.setCursorToHand) self.chat_button.setObjectName("url2") self.chat_button.setToolTip('Meetings every thursday at 23:59 (central eruopean time)') self.chat_button.clicked.connect(functools.partial(self.open_url, "https://chat.memoryoftheworld.org/?nick={}".format(self.librarian.lower().replace(" ", "_")))) self.ll.addWidget(self.chat_button) self.about_project_button = QPushButton('Public Library: http://www.memoryoftheworld.org') self.about_project_button.setObjectName("url2") self.about_project_button.setToolTip('When everyone is librarian, library is everywhere.') self.metadata_thread.uploaded.connect(lambda: self.render_library_button("{}://library.{}".format(prefs['server_prefix'], prefs['lsb_server']), "Building together real-time p2p library infrastructure.")) self.ll.addWidget(self.about_project_button) self.debug_log = QListWidget() self.ll.addWidget(self.debug_log) self.debug_log.addItem("Initiatied!") self.debug_log.hide() from PyQt4 import QtWebKit self.webview = QtWebKit.QWebView() self.webview.setMaximumWidth(680) self.webview.setMaximumHeight(400) self.webview.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.webview.setUrl(QtCore.QUrl( "https://chat.memoryoftheworld.org/?nick={}".format(self.librarian.lower().replace(" ", "_")))) self.ll.addWidget(self.webview) #self.webview.hide() #- check if there is a new version of plugin ---------------------------------------------- self.plugin_url = "https://github.com/marcellmars/letssharebooks/raw/master/calibreletssharebooks/letssharebooks_calibre.zip" self.running_version = ".".join(map(str, lsb.version)) try: r = requests.get('https://raw.github.com/marcellmars/letssharebooks/master/calibreletssharebooks/_version', timeout=3) self.latest_version = r.text[-1] except: self.latest_version = "0.0.0" self.upgrade_button = QPushButton('Please download and upgrade from {0} to {1} version of plugin.'.format(self.us.running_version, self.latest_version)) self.upgrade_button.setObjectName("url2") self.upgrade_button.setToolTip('Running latest version you make developers happy') self.upgrade_button.clicked.connect(functools.partial(self.open_url, self.plugin_url)) version_list = [self.us.running_version, self.us.latest_version] version_list.sort(key=lambda s: map(int, s.split('.'))) if self.us.running_version != self.us.latest_version: if self.us.running_version == version_list[0]: self.ll.addSpacing(20) self.ll.addWidget(self.upgrade_button) #------------------------------------------------------------------------------------------ self.resize(self.sizeHint()) #- parsing/tee log file ------------------------------------------------------------------- self.se = open("/tmp/lsb.log", "w+b") #self.se = tempfile.NamedTemporaryFile() self.so = self.se sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) os.dup2(self.so.fileno(), sys.stdout.fileno()) os.dup2(self.se.fileno(), sys.stderr.fileno()) #- state machine -------------------------------------------------------------------------- self.machine = QtCore.QStateMachine() self.on = QtCore.QState() self.on.setObjectName("on") self.on.entered.connect(lambda: self.render_lsb_button("Start sharing", self.lsb_url_text)) self.calibre_web_server = QtCore.QState() self.calibre_web_server.setObjectName("calibre_web_server") self.calibre_web_server.entered.connect(self.start_calibre_server) self.calibre_web_server.entered.connect(lambda: self.render_lsb_button("Stop sharing", self.lsb_url_text)) self.calibre_web_server.assignProperty(self.debug_label, 'text', 'Starting Calibre web server...') self.ssh_server = QtCore.QState() self.ssh_server.setObjectName("ssh_server") self.ssh_server.entered.connect(lambda: self.render_lsb_button("Stop sharing", "Connecting...")) self.ssh_server.entered.connect(self.establish_ssh_server) self.ssh_server.assignProperty(self.debug_label, 'text', 'Establishing SSH tunnel...') self.ssh_server_established = QtCore.QState() self.ssh_server_established.setObjectName("ssh_server_established") self.ssh_server_established.entered.connect(lambda: self.render_lsb_button("Stop sharing", self.lsb_url_text)) self.ssh_server_established.entered.connect(self.check_connections) self.ssh_server_established.assignProperty(self.debug_label, 'text', 'Established SSH tunnel...') self.url_label_clicked = QtCore.QState() self.url_label_clicked.setObjectName("url_label_clicked") self.url_label_clicked.entered.connect(lambda: self.open_url(self.lsb_url)) self.url_label_clicked.assignProperty(self.debug_label, 'text', 'URL label clicked!') self.about_project_clicked = QtCore.QState() self.about_project_clicked.setObjectName("about_project_clicked") self.about_project_clicked.entered.connect(lambda: self.open_url("{}://library.{}".format(prefs['server_prefix'], prefs['lsb_server']))) self.about_project_clicked.assignProperty(self.debug_label, 'text', 'about_project_button clicked!') self.library_state_changed = QtCore.QState() self.library_state_changed.entered.connect(lambda: self.render_library_button("Uploading library metadata...", "Sharing with the others who share their libraries now...")) self.library_state_changed.setObjectName("library_state_changed") self.library_state_changed.entered.connect(self.sync_metadata) self.off = QtCore.QState() self.off.setObjectName("off") self.off.entered.connect(lambda: self.disconnect_all()) self.off.assignProperty(self.debug_label, 'text', 'Start again...') self.on.addTransition(self.lets_share_button.clicked, self.calibre_web_server) self.calibre_web_server.addTransition(self.lets_share_button.clicked, self.off) self.calibre_web_server.addTransition(self.calibre_didnt_start, self.off) self.calibre_web_server.addTransition(self.started_calibre_web_server, self.ssh_server) self.ssh_server.addTransition(self.lets_share_button.clicked, self.off) self.ssh_server.addTransition(self.check_connection.lost_connection, self.off) self.ssh_server.addTransition(self.established_ssh_tunnel, self.ssh_server_established) self.ssh_server_established.addTransition(self.lets_share_button.clicked, self.off) self.ssh_server_established.addTransition(self.url_label.clicked, self.url_label_clicked) self.ssh_server_established.addTransition(self.about_project_button.clicked, self.about_project_clicked) self.ssh_server_established.addTransition(self.check_connection.lost_connection, self.off) self.ssh_server_established.addTransition(self.us.library_changed, self.library_state_changed) self.url_label_clicked.addTransition(self.ssh_server_established) self.about_project_clicked.addTransition(self.ssh_server_established) self.library_state_changed.addTransition(self.metadata_thread.uploaded, self.ssh_server_established) self.library_state_changed.addTransition(self.metadata_thread.upload_error, self.off) self.library_state_changed.addTransition(self.lets_share_button.clicked, self.off) self.library_state_changed.addTransition(self.url_label.clicked, self.url_label_clicked) self.off.addTransition(self.on) self.machine.addState(self.on) self.machine.addState(self.calibre_web_server) self.machine.addState(self.ssh_server) self.machine.addState(self.ssh_server_established) self.machine.addState(self.url_label_clicked) self.machine.addState(self.about_project_clicked) self.machine.addState(self.library_state_changed) self.machine.addState(self.off) self.machine.setInitialState(self.on) self.machine.start() #------------------------------------------------------------------------------------------ def sql_db_changed(self, event, ids): # this could be used for better update on added/removed books if not self.metadata_thread.isRunning(): self.sync_metadata() else: print("metadata_thread is running! no sync!") def sync_metadata(self): from calibre.gui2.ui import get_gui try: del self.sql_db except: pass self.sql_db = get_gui().current_db self.sql_db.add_listener(self.sql_db_changed) self.metadata_thread.sql_db = self.sql_db self.metadata_thread.port = self.port self.metadata_thread.uploaded.connect(lambda: self.debug_log.addItem("uploaded!")) self.metadata_thread.upload_error.connect(lambda: self.debug_log.addItem("upload_ERROR!")) self.metadata_thread.start() def check_connections(self): #self.webview.show() if self.initial: print("initial!") self.us.library_changed_emit() self.initial = False self.qaction.setIcon(get_icon('images/icon_connected.png')) self.check_connection.add_urls(["http://*****:*****@{2} -R {0}:localhost:{1} -P 722".format(self.port, self.calibre_server_port, prefs['lsb_server']), shell=True) self.lsb_url = "{}://www{}.{}".format(prefs['server_prefix'], self.port, prefs['lsb_server']) self.lsb_url_text = "Go to: {}".format(self.lsb_url) QTimer.singleShot(3000, self.established_ssh_tunnel.emit) else: self.ssh_proc = subprocess.Popen(['ssh', '-T', '-N', '-g', '-o', 'TCPKeepAlive=yes', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no','-o', 'ServerAliveINterval=60', prefs['lsb_server'], '-l', 'tunnel', '-R', '0:localhost:{0}'.format(self.calibre_server_port), '-p', '722']) if self.ssh_proc: def parse_log(): gotcha = False try: self.se.seek(0) result = self.se.readlines() self.se.seek(0) self.se.truncate() for line in result: m = re.match("^Allocated port (.*) for .*", line) try: self.port = m.groups()[0] self.lsb_url = '{}://www{}.{}'.format(prefs['server_prefix'], self.port, prefs['lsb_server']) self.lsb_url_text = "Go to: {0}".format(self.lsb_url) self.url_label_tooltip = 'Copy URL to clipboard and check it out in a browser!' self.established_ssh_tunnel.emit() gotcha = True except: pass finally: if not gotcha: QTimer.singleShot(500, parse_log) parse_log() def start_calibre_server(self): if self.main_gui.content_server is None: self.main_gui.start_content_server() opts, args = server_config().option_parser().parse_args(['calibre-server']) self.calibre_server_port = opts.port self.started_calibre_web_server.emit() else: self.calibre_didnt_start.emit() def config(self): self.do_user_config(parent=self) self.label.setText(prefs['lsb_server']) def save_librarian(self): print('librarian {} saved!'.format(str(self.edit.text()))) if self.edit.text() != "" and self.edit.text() != "l": prefs['librarian'] = str(self.edit.text()) else: prefs['librarian'] = get_libranon() self.edit.setText(prefs['librarian']) def open_url(self, url): self.clip.setText(url) webbrowser.open(url) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: pass def closeEvent(self, e): print("close popup!") self.hide()
__license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __docformat__ = 'restructuredtext en' from calibre.gui2 import Application from PyQt4.Qt import (QDialog, QGridLayout, QListWidget, QDialogButtonBox, QPushButton, QTimer, QIcon) app = Application([], force_calibre_style=True) d = QDialog() d.l = l = QGridLayout() d.setLayout(l) lw = QListWidget() lw.addItem('Some text guy') l.addWidget(lw, 0, 0, 2, 1) bb = QDialogButtonBox() bb.setStandardButtons(bb.Close) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) b = bb.addButton('Action', bb.ActionRole) b.setIcon(QIcon(I('wizard.png'))) l.addWidget(bb, 2, 0, 1, 2) bb.button(bb.Close).setDefault(True) b = QPushButton('Normal') l.addWidget(b, 0, 1, 1, 1) def print_button_sizes():
class tab_widget(QtGui.QTabWidget): # Initiate Widget. def __init__(self, parent=MainWindow): super(tab_widget, self).__init__() self.initUI() # Create all object thats in the AddData tab def makeAddDataTab(self, grid): self.author_label = QLabel("Author") self.author_text = QLineEdit() self.author_text.setPlaceholderText("Author") grid.addWidget(self.author_label, 0, 0) grid.addWidget(self.author_text, 1, 0) self.title_label = QLabel("Title") self.title_text = QLineEdit() self.title_text.setPlaceholderText("Title") grid.addWidget(self.title_label, 0, 1) grid.addWidget(self.title_text, 1, 1) self.date_label = QLabel("Date Read") self.date_text = QLineEdit() self.date_text.setPlaceholderText("yy-mm-dd") grid.addWidget(self.date_label, 2, 1) grid.addWidget(self.date_text, 3, 1) self.grade_label = QLabel("Grade") self.grade_text = QLineEdit() self.grade_text.setPlaceholderText("Grade 1-5") grid.addWidget(self.grade_label, 2, 0) grid.addWidget(self.grade_text, 3, 0) self.comments_label = QLabel("Comments") self.comments_text = QLineEdit() self.comments_text.setPlaceholderText("Comments here") grid.addWidget(self.comments_label, 4, 0) grid.addWidget(self.comments_text, 5, 0) self.genre_label = QLabel("Genre") self.genre_list = QListWidget(self) self.genre_list.addItems(self.genreList) self.genre_list.setObjectName('genre_list') self.genre_list.itemClicked.connect(self.item_clicked) grid.addWidget(self.genre_label, 6, 0) grid.addWidget(self.genre_list, 7, 0) self.genre2_label = QLabel("Genre2") self.genre2_list = QListWidget(self) self.genre2_list.setObjectName("genre2") self.genre2_list.addItem("Select genre first") grid.addWidget(self.genre2_label, 6, 1) grid.addWidget(self.genre2_list, 7, 1) self.submit = QtGui.QPushButton("Submit Data", self) self.submit.clicked.connect(self.buttonClicked) grid.addWidget(self.submit, 8, 1) self.quit = QtGui.QPushButton("Exit", self) self.quit.clicked.connect(self.buttonClicked) self.quit.setMaximumWidth(80) grid.addWidget(self.quit, 8, 0) # Creates all the object thats in the getData tab def makeGetDataTab(self, vbox_inner): self.authorData = QLineEdit() self.authorData.setPlaceholderText("Author") self.authorData.setReadOnly(True) vbox_inner.addWidget(self.authorData) self.titleData = QLineEdit() self.titleData.setPlaceholderText("Title") self.titleData.setReadOnly(True) vbox_inner.addWidget(self.titleData) self.genreData = QLineEdit() self.genreData.setPlaceholderText("Genre") self.genreData.setReadOnly(True) vbox_inner.addWidget(self.genreData) self.genre2Data = QLineEdit() self.genre2Data.setPlaceholderText("Genre2") self.genre2Data.setReadOnly(True) vbox_inner.addWidget(self.genre2Data) self.dateData = QLineEdit() self.dateData.setPlaceholderText("Date read") self.dateData.setReadOnly(True) vbox_inner.addWidget(self.dateData) self.gradeData = QLineEdit() self.gradeData.setPlaceholderText("Grade") self.gradeData.setReadOnly(True) vbox_inner.addWidget(self.gradeData) self.commentsData = QLineEdit() self.commentsData.setPlaceholderText("Comments") self.commentsData.setReadOnly(True) vbox_inner.addWidget(self.commentsData) self.titles_list = QListWidget(self) vbox_inner.addWidget(self.titles_list) hbox_inner = QtGui.QHBoxLayout() self.getTitleData = QtGui.QPushButton("Get title data", self) self.getTitleData.clicked.connect(self.buttonClicked) hbox_inner.addWidget(self.getTitleData) self.refreshList = QtGui.QPushButton("Refresh list", self) self.refreshList.clicked.connect(self.buttonClicked) hbox_inner.addWidget(self.refreshList) return hbox_inner # Initiate the widgets gui def initUI(self): vbox_inner = QVBoxLayout() grid = QtGui.QGridLayout() self.genreList = ['Fiction', 'Fact book', 'Poetry'] # Tab 1: Add Data self.makeAddDataTab(grid) # Tab 2:Get Data from file hbox_inner = self.makeGetDataTab(vbox_inner) tab1 = QWidget() tab1.setLayout(grid) vbox_inner.addLayout(hbox_inner) tab2 = QWidget() tab2.setLayout(vbox_inner) self.addTab(tab1, "Add Book Data") self.addTab(tab2, "Get Book Data") self.move(150, 150) self.show() # Function for when a QListWidgetItem is clicked if the genre_list is # clicked, will check which genre was chosen and populate genre2_list # with subgenres of that genre. def item_clicked(self): genre = self.sender() if genre.objectName() == "genre_list": curr = genre.currentItem().text() if curr == self.genreList[0]: genre2List = ["Detective", "autobiography", "Horror", "Comedy"] elif curr == self.genreList[1]: genre2List = ["Technology", "Biology", "Chemistry", "Mathematics"] elif curr == self.genreList[2]: genre2List = ["Tirade", "Ballads", "Rhyme"] else: genre2List = ["None"] self.genre2_list.clear() self.genre2_list.addItems(genre2List) # Function for when a button is clicked, if 'Submit Data' is clicked, # will check that all input is correct format and if so write # the data to the file. If the button pressed is 'Get title data' # will get the selected title in the QListWidget and show the row data def buttonClicked(self): sender = self.sender() if sender.text() == "Refresh list": if self.parent().dialog.isHidden(): titles = getAllTitles(self.parent()) self.titles_list.clear() if titles != "": self.titles_list.addItems(titles) else: QMessageBox.warning(self.parent(), "Failure", "Connect to the server before refreshing.") if sender.text() == "Exit": if self.parent().dialog.isHidden(): self.parent().disconnect() sys.exit(0) elif sender.text() == "Get title data": if self.titles_list.currentItem() != None: if self.parent().dialog.isHidden(): titleToGet = str(self.titles_list.currentItem().text()) if titleToGet != "": titleData = getTitleData(self.parent(), titleToGet) splitLine = [] splitLine = titleData.split(",", 7) if titleData != "Empty": self.authorData.setText(splitLine[0].replace('"', "").lstrip()) self.titleData.setText(splitLine[1].replace('"', "").lstrip()) self.genreData.setText(splitLine[2].replace('"', "").lstrip()) self.genre2Data.setText(splitLine[3].replace('"', "").lstrip()) self.dateData.setText(splitLine[4].replace('"', "").lstrip()) self.gradeData.setText(splitLine[5].replace('"', "").lstrip()) self.commentsData.setText(splitLine[6].replace('"', "").lstrip()) else: QMessageBox.warning(self, "Failed", "Connect to server first") self.dialog.setWindowTitle("Book Library (Disconnected)") elif sender.text() == "Submit Data": while self.parent().dialog.isHidden(): author = str(self.author_text.text()) if containsDigit(author) == True: QMessageBox.warning(self, "Wrong input", "Error: Author cant contain digits") break if len(author) == 0: QMessageBox.warning(self, "Wrong input", "Author is a required field") break title = str(self.title_text.text()) try: title = str(self.title_text.text()) except: QMessageBox.warning(self, "Wrong input", "Error in comments, only A-z, 1-9 allowed") break if len(title) == 0: QMessageBox.warning(self, "Wrong input", "Title is a required field") break if self.genre_list.currentItem() != None: genre = str(self.genre_list.currentItem().text()) else: QMessageBox.warning(self, "Wrong input", "Error: Need to pick genre") break if self.genre2_list.currentItem() != None: genre2 = str(self.genre2_list.currentItem().text()) else: QMessageBox.warning(self, "Wrong input", "Error: Need to pick genre2") break d = str(self.date_text.text()) if len(d) == 0: QMessageBox.warning(self, "Wrong input", "Date is a required field") break try: dateRead = datetime.datetime.strptime(d, '%y-%m-%d').date() except: QMessageBox.warning(self, "Wrong input", "Error: Date needs to be in format: yy-mm-dd") break try: grade = int(str(self.grade_text.text())) except: QMessageBox.warning(self, "Wrong input", "Error: Grade needs to be a number between 1-5") break if grade > 5 or grade < 1: QMessageBox.warning(self, "Wrong input", "Error: Grade needs to be a number between 1-5") break try: comments = str(self.comments_text.text()) except: QMessageBox.warning(self, "Wrong input", "Error: in comments, only A-z, 1-9 allowed") break if len(comments) == 0: comments = "No comments" self.parent().sendBookData(author, title, genre, genre2, str(dateRead), str(grade), comments) break
class LetsShareBooksDialog(QDialog): def __init__(self, gui, icon, do_user_config, qaction, us): QDialog.__init__(self, gui) self.gui = gui self.do_user_config = do_user_config self.qaction = qaction self.us = us self.clip = QApplication.clipboard() self.main_gui = calibre_main() self.urllib_thread = UrlLibThread(self.us) self.kill_servers_thread = KillServersThread(self.us) self.us.check_finished = True self.pxmp = QPixmap() self.pxmp.load('images/icon_connected.png') self.icon_connected = QIcon(self.pxmp) self.setStyleSheet(""" QDialog { background-color: white; } QPushButton { font-size: 16px; border-style: solid; border-color: red; font-family:'BitstreamVeraSansMono',Consolas,monospace; text-transform: uppercase; } QPushButton#arrow { border-width: 16px; border-right-color:white; padding: -10px; color:red; } QPushButton#url { background-color: red; min-width: 460px; color: white; text-align: left; } QPushButton#url:hover { background-color: white; color: red; } QPushButton#share { background-color: red; color: white; margin-right: 10px; } QPushButton#share:hover { background-color: white; color: red; } QPushButton#url2 { color: #222; text-align: left; } QPushButton#url2:hover { color: red; } """) self.ll = QVBoxLayout() #self.ll.setSpacing(1) self.l = QHBoxLayout() self.l.setSpacing(0) self.l.setMargin(0) #self.l.setContentsMargins(0,0,0,0) self.w = QWidget() self.w.setLayout(self.l) self.setLayout(self.ll) self.setWindowIcon(icon) self.lets_share_button = QPushButton() self.lets_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.lets_share_button.setObjectName("share") self.lets_share_button.clicked.connect(self.lets_share) self.stop_share_button = QPushButton() self.stop_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.stop_share_button.setObjectName("share") self.stop_share_button.clicked.connect(self.stop_share) self.l.addWidget(self.lets_share_button) self.l.addWidget(self.stop_share_button) if self.us.button_state == "start": self.lets_share_button.show() self.stop_share_button.hide() self.lets_share_button.setText(self.us.share_button_text) else: self.lets_share_button.hide() self.stop_share_button.show() self.stop_share_button.setText(self.us.share_button_text) self.url_label = QPushButton() self.url_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.url_label.setObjectName("url") self.url_label.clicked.connect(self.open_url) self.l.addWidget(self.url_label) self.arrow_button = QPushButton("_____") self.arrow_button.setObjectName("arrow") self.l.addWidget(self.arrow_button) self.ll.addWidget(self.w) self.ll.addSpacing(10) self.chat_button = QPushButton("Chat room: https://chat.memoryoftheworld.org") #self.chat_button.hovered.connect(self.setCursorToHand) self.chat_button.setObjectName("url2") self.chat_button.setToolTip('Meetings every thursday at 23:59 (central eruopean time)') self.chat_button.clicked.connect(functools.partial(self.open_url2, "https://chat.memoryoftheworld.org")) self.ll.addWidget(self.chat_button) self.about_project_button = QPushButton('Public Library: http://www.memoryoftheworld.org') self.about_project_button.setObjectName("url2") self.about_project_button.setToolTip('When everyone is librarian, library is everywhere.') self.about_project_button.clicked.connect(functools.partial(self.open_url2, "http://www.memoryoftheworld.org")) self.ll.addWidget(self.about_project_button) self.debug_log = QListWidget() self.ll.addWidget(self.debug_log) self.debug_log.addItem("Initiatied!") self.metadata_thread = MetadataLibThread(self.debug_log) self.metadata_button = QPushButton("Get library metadata!") self.metadata_button.setObjectName("url2") self.metadata_button.setToolTip('Get library metadata!') self.metadata_button.clicked.connect(self.get_metadata) self.ll.addWidget(self.metadata_button) self.upgrade_button = QPushButton('Please download and upgrade from {0} to {1} version of plugin.'.format(self.us.running_version, self.us.latest_version)) self.upgrade_button.setObjectName("url2") self.upgrade_button.setToolTip('Running latest version you make developers happy') self.upgrade_button.clicked.connect(functools.partial(self.open_url2, self.us.plugin_url)) version_list = [self.us.running_version, self.us.latest_version] version_list.sort(key=lambda s: map(int, s.split('.'))) if self.us.running_version != self.us.latest_version: if self.us.running_version == version_list[0]: self.ll.addSpacing(20) self.ll.addWidget(self.upgrade_button) self.resize(self.sizeHint()) self.se = open("lsb.log", "w+b") self.so = self.se sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) os.dup2(self.so.fileno(), sys.stdout.fileno()) os.dup2(self.se.fileno(), sys.stderr.fileno()) self.timer = QTimer() self.timer.timeout.connect(self.check_and_render) self.timer_period = 300 self.timer.start(self.timer_period) self.error_log = "" def lets_share(self): self.lets_share_button.setEnabled(False) self.timer.stop() self.us.share_button_text = "Connecting..." #self.debug_log.addItem("Let's share!") self.us.counter = 0 self.us.lost_connection = False if not self.us.ssh_proc: self.main_gui.start_content_server() opts, args = server_config().option_parser().parse_args(['calibre-server']) self.calibre_server_port = opts.port if sys.platform == "win32": self.win_reg = subprocess.Popen("regedit /s .hosts.reg") self.us.win_port = int(random.random()*40000+10000) self.us.ssh_proc = subprocess.Popen("lsbtunnel.exe -N -T tunnel@{2} -R {0}:localhost:{1} -P 722".format(self.us.win_port, self.calibre_server_port, prefs['lsb_server']), shell=True) self.us.lsb_url = "https://www{0}.{1}".format(self.us.win_port, prefs['lsb_server']) #_dev_self.us.lsb_url = "http://www{0}.{1}".format(self.us.win_port, prefs['lsb_server']) self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url) self.us.found_url = True else: self.us.ssh_proc = subprocess.Popen(['ssh', '-T', '-N', '-g', '-o', 'UserKnownHostsFile=.userknownhostsfile', '-o', 'TCPKeepAlive=yes', '-o', 'ServerAliveINterval=60', prefs['lsb_server'], '-l', 'tunnel', '-R', '0:localhost:{0}'.format(self.calibre_server_port), '-p', '722']) self.us.found_url = None self.qaction.setIcon(get_icon('images/icon_connected.png')) self.us.connecting = True self.us.connecting_now = datetime.datetime.now() self.timer.start(self.timer_period) def stop_share(self): self.stop_share_button.setEnabled(False) #self.debug_log.addItem("Stop Share!") self.timer.stop() self.us.lsb_url = 'nourl' self.us.urllib_result = '' self.us.disconnecting = True self.qaction.setIcon(get_icon('images/icon.png')) self.kill_servers_thread.start() self.timer.start(self.timer_period) def check_and_render(self): #self.show_debug() if self.us.button_state == "start": self.stop_share_button.hide() self.lets_share_button.show() self.lets_share_button.setText(self.us.share_button_text) else: self.lets_share_button.hide() self.stop_share_button.show() self.stop_share_button.setText(self.us.share_button_text) if self.us.disconnecting: self.us.share_button_text = "Disconnecting..." if self.us.lost_connection: self.us.lsb_url_text = 'Lost connection. Please start sharing again.' self.us.url_label_tooltip = '<<<< Click on Start sharing button again.' else: self.us.lsb_url_text = 'Be a librarian. Share your library.' self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.<<<<' if self.us.kill_finished: #self.debug_log.addItem("Let's share connect!") self.us.button_state = "start" self.us.share_button_text = "Start sharing" self.us.disconnecting = False self.us.kill_finished = False self.lets_share_button.setEnabled(True) elif self.us.connecting: if self.us.connecting_now: if (datetime.datetime.now() - self.us.connecting_now) > datetime.timedelta(seconds=10): #self.debug_log.addItem("Timeout!") self.us.http_error = None self.us.lost_connection = True self.us.connecting = False self.us.connecting_now = None self.stop_share() elif self.us.found_url: self.us.check_finished = False self.urllib_thread.start() if self.us.lsb_url == "nourl" and self.us.ssh_proc and sys.platform != "win32": #self.debug_log.addItem("Wait for Allocated port!") self.se.seek(0) result = self.se.readlines() for line in result: m = re.match("^Allocated port (.*) for .*", line) try: #self.debug_log.addItem(self.us.lsb_url) self.us.lsb_url = 'https://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server']) #_dev_self.us.lsb_url = 'http://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server']) self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url) self.us.url_label_tooltip = 'Copy URL to clipboard and check it out in a browser!' self.us.http_error = None self.us.found_url = True except: pass elif self.us.urllib_result == 200: #self.debug_log.addItem("Finish Connecting State!") self.se.seek(0) self.se.truncate() self.us.share_button_text = "Stop sharing" self.us.button_state = "stop" self.stop_share_button.setEnabled(True) self.us.connecting = False self.us.connecting_now = None self.us.found_url = None elif self.us.http_error and self.us.button_state == "stop": #self.debug_log.addItem("Error!") self.us.http_error = None self.us.lost_connection = True self.stop_share() elif self.us.check_finished: #if self.debug_log.item(self.debug_log.count()-1).text()[:10] == "Finally Ca": # self.us.debug_counter = self.us.debug_counter + 1 #else: # self.debug_log.addItem("Finally Called Thread!({0})".format(self.us.debug_counter)) # self.us.debug_counter = 1 self.us.check_finished = False self.urllib_thread.start() if self.us.urllib_result == 200 and self.us.button_state == "stop": self.stop_share_button.setEnabled(True) if self.us.lsb_url == 'nourl' and self.us.button_state == "start": self.lets_share_button.setEnabled(True) self.setWindowTitle("{0} - {1}".format(self.us.window_title, self.us.lsb_url)) self.url_label.setToolTip(self.us.url_label_tooltip) self.url_label.setText(self.us.lsb_url_text) def open_url(self): if self.us.lsb_url == "nourl" and not self.us.http_error: self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.' self.us.lsb_url_text = '<<<< Be a librarian. Click on Start sharing button.' else: self.clip.setText(self.us.lsb_url) webbrowser.open(str(self.us.lsb_url)) if self.us.lsb_url != "nourl": self.us.lsb_url_text = "Library at: {0}".format(self.us.lsb_url) def open_url2(self, url): self.clip.setText(url) webbrowser.open(url) def get_metadata(self): self.metadata_thread.start() def show_debug(self): if self.us.debug_item: self.debug_log.addItem(str(self.us.debug_item)) self.us.debug_item = None self.debug_log.scrollToBottom() self.debug_log.repaint() def closeEvent(self, e): self.hide() #self.urllib_thread.stop() #self.kill_servers_thread.stop() def config(self): self.do_user_config(parent=self) self.label.setText(prefs['lsb_server'])
def addItem(self, *args): try: return QListWidget.addItem(self, *args) finally: self.mark_as_editable()
class LayersFilterDialog(QtGui.QDialog): filterTextChanged = QtCore.pyqtSignal() filterLayersChanged = QtCore.pyqtSignal() def __init__(self, layers, widget, parent): super(LayersFilterDialog, self).__init__(parent) self.checkBox = [] self.layers = layers self.widget = widget self.filterLayers = None self.filterText = "" self.initGui() self.setLayers(layers) def initGui(self): layout = QtGui.QVBoxLayout() self.label = QtGui.QLabel("<b>Filter by layer</b>") layout.addWidget(self.label) self.layersList = QListWidget() layout.addWidget(self.layersList) self.label = QtGui.QLabel("<b>Filter by text</b>") layout.addWidget(self.label) self.text = QtGui.QLineEdit() layout.addWidget(self.text) self.button = QtGui.QPushButton("Apply") self.button.clicked.connect(self.apply) layout.addWidget(self.button) self.setLayout(layout) self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Popup) self.resize(200, 150) def show(self): self.computeLocation() QtGui.QDialog.show(self) def computeLocation(self): point = self.widget.rect().bottomRight() global_point = self.widget.mapToGlobal(point) self.move(global_point) def setLayers(self, layers): for layer in layers: item = QtGui.QListWidgetItem(layer) item.setCheckState(QtCore.Qt.Checked) self.layersList.addItem(item) self.filterLayers = None def setFilterLayers(self, layers): for i in xrange(self.layersList.count()): item = self.layersList.item(i) item.setCheckState(QtCore.Qt.Checked if layers is None or item. text() in layers else QtCore.Qt.Unchecked) def setFilterText(self, text): self.text.setText(text) def apply(self): filterLayers = [] for i in xrange(self.layersList.count()): item = self.layersList.item(i) if item.checkState() == QtCore.Qt.Checked: filterLayers.append(item.text()) if len(filterLayers) == self.layersList.count(): filterLayers = None if filterLayers != self.filterLayers: self.filterLayers = filterLayers self.filterLayersChanged.emit() filterText = self.text.text() if filterText != self.filterText: self.filterText = filterText self.filterTextChanged.emit() self.hide()
class PM_Clipboard(PM_GroupBox): """ The PM_Clipboard class provides a groupbox containing a list of clipboard items that can be pasted in the 3D Workspace. The selected item in this list is shown by its elementViewer (an instance of L{PM_PreviewGroupBox}) The object being previewed can then be deposited into the 3D workspace. """ def __init__(self, parentWidget, title='Clipboard', win=None, elementViewer=None): """ Appends a PM_Clipboard groupbox widget to I{parentWidget},a L{PM_Dialog} @param parentWidget: The parent dialog (Property manager) containing this widget. @type parentWidget: L{PM_Dialog} @param title: The title (button) text. @type title: str @param win: MainWindow object @type win: L{MWsemantics} or None @param elementViewer: The associated preview pane groupbox. If provided, The selected item in L{self.clipboardListWidget} is shown (previewed) by L{elementViewer}. The object being previewed can then be deposited into the 3D workspace. @type elementViewer: L{PM_PreviewGroupBox} or None """ self.w = win self.elementViewer = elementViewer self.elementViewer.setDisplay(diTUBES) self.pastableItems = None PM_GroupBox.__init__(self, parentWidget, title) self._loadClipboardGroupbox() def _loadClipboardGroupbox(self): """ Load the L{self.clipboardListWidget} widget used to display a list of clipboard items inside this clipboard groupbox. """ self.clipboardListWidget = QListWidget(self) self.gridLayout.addWidget(self.clipboardListWidget) #Append to the widget list. This is important for expand -collapse #functions (of the groupbox) to work properly. self._widgetList.append(self.clipboardListWidget) def _updateElementViewer(self, newModel=None): """ Update the view of L{self.elementViewer} @param newModel: The model correseponding to the item selected in L{self.clipboardListWidget}. @type newModel: L{molecule} or L{Group} """ if not self.elementViewer: return assert isinstance(self.elementViewer, MMKitView) self.elementViewer.resetView() if newModel: self.elementViewer.updateModel(newModel) def update(self): """ Updates the clipboard items in the L{PM_Clipboard} groupbox. Also updates its element viewer. """ PM_GroupBox.update(self) self.pastableItems = self.w.assy.shelf.getPastables() i = self.clipboardListWidget.currentRow() self.clipboardListWidget.clear() newModel = None if len(self.pastableItems): for item in self.pastableItems: self.clipboardListWidget.addItem(item.name) if i >= self.clipboardListWidget.count(): i = self.clipboardListWidget.count() - 1 if i < 0: i = 0 self.clipboardListWidget.setCurrentItem( self.clipboardListWidget.item(i)) newModel = self.pastableItems[i] self._updateElementViewer(newModel) def clipboardListItemChanged(self, currentItem=None, previousItem=None): """ Slot method. Called when user clicks on a different pastable item displayed in this groupbox @param currentItem: Current item in the L{self.clipboardListWidget} that is selected @type currentItem: U{B{QListWidgetItem} <http://doc.trolltech.com/4.2/qlistwidgetitem.html>} @param previousItem: Previously selected item in the L{self.clipboardListWidget} @type previousItem: U{B{QListWidgetItem} <http://doc.trolltech.com/4.2/qlistwidgetitem.html>} """ if not (currentItem or previousItem): return itemId = self.clipboardListWidget.row(currentItem) if itemId != -1: newChunk = self.pastableItems[itemId] self.clipboardListWidget.setCurrentRow(itemId) self._updateElementViewer(newChunk) def connect_or_disconnect_signals(self, isConnect): """ Connect or disconnect widget signals sent to their slot methods. @param isConnect: If True the widget will send the signals to the slot method. @type isConnect: boolean """ if isConnect: change_connect = self.w.connect else: change_connect = self.w.disconnect change_connect( self.clipboardListWidget, SIGNAL("currentItemChanged(QListWidgetItem*,QListWidgetItem*)"), self.clipboardListItemChanged) def currentRow(self): """ Return the current row of the selected item in this groupbox's listwidget ( L{self.clipboardListWidget} ) @return: Current Row of the selected pastable item in the clipboard groupbox. @rtype: int """ currentRow = self.clipboardListWidget.currentRow() return currentRow
class PrefsViewerDialog(SizePersistedDialog): def __init__(self, gui, namespace): SizePersistedDialog.__init__(self, gui, 'Prefs Viewer dialog') self.setWindowTitle('Preferences for: ' + namespace) self.gui = gui self.db = gui.current_db self.namespace = namespace self._init_controls() self.resize_dialog() self._populate_settings() if self.keys_list.count(): self.keys_list.setCurrentRow(0) def _init_controls(self): layout = QVBoxLayout(self) self.setLayout(layout) ml = QHBoxLayout() layout.addLayout(ml, 1) self.keys_list = QListWidget(self) self.keys_list.setSelectionMode(QAbstractItemView.SingleSelection) self.keys_list.setFixedWidth(150) self.keys_list.setAlternatingRowColors(True) ml.addWidget(self.keys_list) self.value_text = QTextEdit(self) self.value_text.setTabStopWidth(24) self.value_text.setReadOnly(False) ml.addWidget(self.value_text, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self._apply_changes) button_box.rejected.connect(self.reject) self.clear_button = button_box.addButton('Clear', QDialogButtonBox.ResetRole) self.clear_button.setIcon(get_icon('trash.png')) self.clear_button.setToolTip('Clear all settings for this plugin') self.clear_button.clicked.connect(self._clear_settings) layout.addWidget(button_box) def _populate_settings(self): self.keys_list.clear() ns_prefix = self._get_ns_prefix() keys = sorted([ k[len(ns_prefix):] for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix) ]) for key in keys: self.keys_list.addItem(key) self.keys_list.setMinimumWidth(self.keys_list.sizeHintForColumn(0)) self.keys_list.currentRowChanged[int].connect( self._current_row_changed) def _current_row_changed(self, new_row): if new_row < 0: self.value_text.clear() return key = unicode(self.keys_list.currentItem().text()) val = self.db.prefs.get_namespaced(self.namespace, key, '') self.value_text.setPlainText(self.db.prefs.to_raw(val)) def _get_ns_prefix(self): return 'namespaced:%s:' % self.namespace def _apply_changes(self): from calibre.gui2.dialogs.confirm_delete import confirm message = '<p>Are you sure you want to change your settings in this library for this plugin?</p>' \ '<p>Any settings in other libraries or stored in a JSON file in your calibre plugins ' \ 'folder will not be touched.</p>' \ '<p>You must restart calibre afterwards.</p>' if not confirm(message, self.namespace + '_clear_settings', self): return val = self.db.prefs.raw_to_object( unicode(self.value_text.toPlainText())) key = unicode(self.keys_list.currentItem().text()) self.db.prefs.set_namespaced(self.namespace, key, val) restart = prompt_for_restart( self, 'Settings changed', '<p>Settings for this plugin in this library have been changed.</p>' '<p>Please restart calibre now.</p>') self.close() if restart: self.gui.quit(restart=True) def _clear_settings(self): from calibre.gui2.dialogs.confirm_delete import confirm message = '<p>Are you sure you want to clear your settings in this library for this plugin?</p>' \ '<p>Any settings in other libraries or stored in a JSON file in your calibre plugins ' \ 'folder will not be touched.</p>' \ '<p>You must restart calibre afterwards.</p>' if not confirm(message, self.namespace + '_clear_settings', self): return ns_prefix = self._get_ns_prefix() keys = [k for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix)] for k in keys: del self.db.prefs[k] self._populate_settings() restart = prompt_for_restart( self, 'Settings deleted', '<p>All settings for this plugin in this library have been cleared.</p>' '<p>Please restart calibre now.</p>') self.close() if restart: self.gui.quit(restart=True)
class LayersFilterDialog(QtGui.QDialog): filterTextChanged = QtCore.pyqtSignal() filterLayersChanged = QtCore.pyqtSignal() def __init__(self, layers, widget, parent): super(LayersFilterDialog, self).__init__(parent) self.checkBox = [] self.layers = layers self.widget = widget self.filterLayers = None self.filterText = "" self.initGui() self.setLayers(layers) def initGui(self): layout = QtGui.QVBoxLayout() self.label = QtGui.QLabel("<b>Filter by layer</b>") layout.addWidget(self.label) self.layersList = QListWidget() layout.addWidget(self.layersList) self.label = QtGui.QLabel("<b>Filter by text</b>") layout.addWidget(self.label) self.text = QtGui.QLineEdit() layout.addWidget(self.text) self.button = QtGui.QPushButton("Apply") self.button.clicked.connect(self.apply) layout.addWidget(self.button) self.setLayout(layout) self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Popup) self.resize(200, 150) def show(self): self.computeLocation() QtGui.QDialog.show(self) def computeLocation(self): point = self.widget.rect().bottomRight() global_point = self.widget.mapToGlobal(point) self.move(global_point) def setLayers(self, layers): for layer in layers: item = QtGui.QListWidgetItem(layer) item.setCheckState(QtCore.Qt.Checked) self.layersList.addItem(item) self.filterLayers = None def setFilterLayers(self, layers): for i in xrange(self.layersList.count()): item = self.layersList.item(i) item.setCheckState(QtCore.Qt.Checked if layers is None or item.text() in layers else QtCore.Qt.Unchecked) def setFilterText(self, text): self.text.setText(text) def apply(self): filterLayers = [] for i in xrange(self.layersList.count()): item = self.layersList.item(i) if item.checkState() == QtCore.Qt.Checked: filterLayers.append(item.text()) if len(filterLayers) == self.layersList.count(): filterLayers = None if filterLayers != self.filterLayers: self.filterLayers = filterLayers self.filterLayersChanged.emit() filterText = self.text.text() if filterText != self.filterText: self.filterText = filterText self.filterTextChanged.emit() self.hide()
class PrefsViewerDialog(SizePersistedDialog): def __init__(self, gui, namespace): SizePersistedDialog.__init__(self, gui, 'Prefs Viewer dialog') self.setWindowTitle('Preferences for: '+namespace) self.gui = gui self.db = gui.current_db self.namespace = namespace self._init_controls() self.resize_dialog() self._populate_settings() if self.keys_list.count(): self.keys_list.setCurrentRow(0) def _init_controls(self): layout = QVBoxLayout(self) self.setLayout(layout) ml = QHBoxLayout() layout.addLayout(ml, 1) self.keys_list = QListWidget(self) self.keys_list.setSelectionMode(QAbstractItemView.SingleSelection) self.keys_list.setFixedWidth(150) self.keys_list.setAlternatingRowColors(True) ml.addWidget(self.keys_list) self.value_text = QTextEdit(self) self.value_text.setTabStopWidth(24) self.value_text.setReadOnly(True) ml.addWidget(self.value_text, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok) button_box.accepted.connect(self.accept) self.clear_button = button_box.addButton('Clear', QDialogButtonBox.ResetRole) self.clear_button.setIcon(get_icon('trash.png')) self.clear_button.setToolTip('Clear all settings for this plugin') self.clear_button.clicked.connect(self._clear_settings) layout.addWidget(button_box) def _populate_settings(self): self.keys_list.clear() ns_prefix = self._get_ns_prefix() keys = sorted([k[len(ns_prefix):] for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix)]) for key in keys: self.keys_list.addItem(key) self.keys_list.setMinimumWidth(self.keys_list.sizeHintForColumn(0)) self.keys_list.currentRowChanged[int].connect(self._current_row_changed) def _current_row_changed(self, new_row): if new_row < 0: self.value_text.clear() return key = unicode(self.keys_list.currentItem().text()) val = self.db.prefs.get_namespaced(self.namespace, key, '') self.value_text.setPlainText(self.db.prefs.to_raw(val)) def _get_ns_prefix(self): return 'namespaced:%s:'% self.namespace def _clear_settings(self): from calibre.gui2.dialogs.confirm_delete import confirm message = '<p>Are you sure you want to clear your settings in this library for this plugin?</p>' \ '<p>Any settings in other libraries or stored in a JSON file in your calibre plugins ' \ 'folder will not be touched.</p>' \ '<p>You must restart calibre afterwards.</p>' if not confirm(message, self.namespace+'_clear_settings', self): return ns_prefix = self._get_ns_prefix() keys = [k for k in self.db.prefs.iterkeys() if k.startswith(ns_prefix)] for k in keys: del self.db.prefs[k] self._populate_settings() d = info_dialog(self, 'Settings deleted', '<p>All settings for this plugin in this library have been cleared.</p>' '<p>Please restart calibre now.</p>', show_copy_button=False) b = d.bb.addButton(_('Restart calibre now'), d.bb.AcceptRole) b.setIcon(QIcon(I('lt.png'))) d.do_restart = False def rf(): d.do_restart = True b.clicked.connect(rf) d.set_details('') d.exec_() b.clicked.disconnect() self.close() if d.do_restart: self.gui.quit(restart=True)
class IpetPbHistoryWindow(IpetMainWindow): NO_SELECTION_TEXT = "no selection" default_cmap = 'spectral' imagepath = osp.sep.join((osp.dirname(__file__), osp.pardir, "images")) DEBUG = True def __init__(self, testrunfiles=[], evaluationfile=None): QtGui.QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("application main window") self.file_menu = QtGui.QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) loadaction = self.createAction( "&Load", self.loadTestruns, QKeySequence.Open, icon="Load-icon", tip="Load testrun from trn file (current test run gets discarded)") resetaction = self.createAction( "&Reset selected names", self.resetSelectedTestrunNames, QKeySequence.Undo, icon="", tip="Reset names of selected test runs") self.file_menu.addAction(loadaction) self.help_menu = QtGui.QMenu('&Help', self) self.edit_menu = QtGui.QMenu('&Edit', self) self.edit_menu.addAction(resetaction) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.menuBar().addMenu(self.edit_menu) self.help_menu.addAction('&About', self.about) self.main_widget = QtGui.QWidget(self) lwframe = QFrame(self.main_widget) l = QtGui.QVBoxLayout(self.main_widget) self.sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100) toolbar = IpetNavigationToolBar(self.sc, self.main_widget) l.addWidget(toolbar) l.addWidget(self.sc) h = QtGui.QHBoxLayout(lwframe) l.addWidget(lwframe) self.trListWidget = QListWidget() # for item in list("ABC"): # self.trListWidget.addItem((item)) self.trListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) h.addWidget(self.trListWidget) self.connect(self.trListWidget, SIGNAL("itemSelectionChanged()"), self.selectionChanged) self.trListWidget.itemChanged.connect(self.testrunItemChanged) v = QtGui.QVBoxLayout(lwframe) self.probListWidget = QListWidget() # for item in list("12345"): # self.probListWidget.addItem((item)) self.probListWidget.setSelectionMode( QAbstractItemView.ExtendedSelection) v.addWidget(self.probListWidget) self.connect(self.probListWidget, SIGNAL("itemSelectionChanged()"), self.selectionChanged) self.testSetWidget = QListWidget() v.addWidget(self.testSetWidget) self.testSetWidget.addItem(self.NO_SELECTION_TEXT) for t in TestSets.getTestSets(): self.testSetWidget.addItem(str(t)) h.addLayout(v) self.connect(self.testSetWidget, SIGNAL("itemSelectionChanged()"), self.selectionChanged) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) self.testruns = [] self.testrunnames = {} for tr in testrunfiles: tr = TestRun.loadFromFile(str(tr)) try: self.addTestrun(tr) except Exception as e: print(e) self.evaluation = None if evaluationfile is not None: self.evaluation = IPETEvaluation.fromXMLFile(evaluationfile) # self.primallines = {} # self.duallines = {} # self.primalpatches = {} self.statusBar().showMessage("Ready to load some test run data!", 5000) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon( QIcon(osp.sep.join((self.imagepath, "%s.png" % icon)))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action def getSelectedProblist(self): selectedprobs = [ str(item.text()) for item in self.probListWidget.selectedItems() ] selitem = self.testSetWidget.selectedItems()[0] if selitem.text() != self.NO_SELECTION_TEXT: testsetprobs = set(TestSets.getTestSetByName(selitem.text())) selectedprobs = [p for p in selectedprobs if p in testsetprobs] return selectedprobs def getSelectedTestrunList(self): return [ tr for idx, tr in enumerate(self.testruns) if self.trListWidget.isItemSelected(self.trListWidget.item(idx)) ] def selectionChanged(self): if len(self.testruns) == 0: return problist = self.getSelectedProblist() if len(problist) == 0: return testruns = self.getSelectedTestrunList() if len(testruns) == 0: return self.update_Axis(problist, testruns) def testrunItemChanged(self): curritem = self.trListWidget.currentItem() if not curritem: return rowindex = self.trListWidget.currentRow() if rowindex < 0 or rowindex > len(self.testruns): return newtext = str(curritem.text()) testrun = self.testruns[rowindex] self.setTestrunName(testrun, newtext) def resetSelectedTestrunNames(self): for tr in self.getSelectedTestrunList(): self.resetTestrunName(tr) def getTestrunName(self, testrun): """ returns the test run name as specified by the user """ return self.testrunnames.get(testrun.getName(), testrun.getName()) def setTestrunName(self, testrun, newname): self.debugMessage("Changing testrun name from %s to %s" % (self.getTestrunName(testrun), newname)) self.testrunnames[testrun.getName()] = newname def resetTestrunName(self, testrun): try: del self.testrunnames[testrun.getName()] item = self.trListWidget.item(self.testruns.index(testrun)) item.setText((self.getTestrunName(testrun))) except KeyError: pass def updateStatus(self, message): self.statusBar().showMessage(message, 5000) def fileQuit(self): self.close() def addTestrun(self, tr): self.testruns.append(tr) self.probListWidget.clear() self.trListWidget.clear() for testrun in self.testruns: item = QListWidgetItem((self.getTestrunName(testrun))) self.trListWidget.addItem(item) item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable) problems = [] if len(self.testruns) > 0: problems = self.testruns[0].getProblemNames() if len(self.testruns) > 1: for testrun in self.testruns[1:]: problems = [ p for p in problems if p in set(testrun.getProblemNames()) ] for prob in sorted(problems): self.probListWidget.addItem(str(prob)) self.trListWidget.selectAll() def closeEvent(self, ce): self.fileQuit() def debugMessage(self, message): if self.DEBUG: print(message) else: pass def loadTestruns(self): thedir = str(".") filenames = QFileDialog.getOpenFileNames( self, caption=("%s - Load testruns" % QApplication.applicationName()), directory=thedir, filter=str("Testrun files (*.trn)")) if filenames: loadedtrs = 0 notloadedtrs = 0 for filename in filenames: try: print(filename) tr = TestRun.loadFromFile(str(filename)) try: self.addTestrun(tr) except Exception as e: print(e) loadedtrs += 1 except Exception: notloadedtrs += 1 message = "Loaded %d/%d test runs" % (loadedtrs, loadedtrs + notloadedtrs) self.updateStatus(message) pass def update_Axis(self, probnames, testruns): """ update method called every time a new instance was selected """ #self.resetAxis() # make up data for plotting method x = {} y = {} z = {} zx = {} kws = {} duallinekws = {} dualbarkws = {} baseline = 0 if len(probnames) == 1: self.updateStatus("Showing problem %s on %d test runs" % (probnames[0], len(testruns))) else: self.updateStatus("Showing mean over %d problems on %d test runs" % (len(probnames), len(testruns))) self.resetAxis() usenormalization = True showdualbound = True xmax = xmin = ymax = ymin = 0 labelorder = [] for testrun in testruns: testrunname = self.getTestrunName(testrun) if len(probnames) == 1: x[testrunname], y[testrunname] = getProcessPlotData( testrun, probnames[0], usenormalization, access="name") else: x[testrunname], y[testrunname] = getMeanIntegral(testrun, probnames, access="name") if not usenormalization and len(probnames) == 1: baseline = testrun.problemGetOptimalSolution(probnames[0]) y[testrunname] -= baseline xmax = max(xmax, max(x[testrunname])) ymax = max(ymax, max(y[testrunname])) ymin = min(ymin, min(y[testrunname])) print(y[testrunname]) print(y[testrunname][1:] - y[testrunname][:-1] > 0) if numpy.any(y[testrunname][1:] - y[testrunname][:-1] > 0): logging.warn( "Error: Increasing primal gap function on problems {}". format(probnames)) if showdualbound: arguments = { "historytouse": Key.DualBoundHistory, "boundkey": Key.DualBound } if len(probnames) == 1: zx[testrunname], z[testrunname] = getProcessPlotData( testrun, probnames[0], usenormalization, access="name", **arguments) else: zx[testrunname], z[testrunname] = getMeanIntegral( testrun, probnames, access="name", **arguments) # normalization requires negative dual gap if usenormalization: z[testrunname] = -numpy.array(z[testrunname]) ymin = min(ymin, min(z[testrunname])) duallinekws[testrunname] = dict(linestyle='dashed') dualbarkws = dict(alpha=0.1) # set special key words for the testrun kws[testrunname] = dict(alpha=0.1) labelorder.append(testrunname) # for now, only one color cycle exists #colormap = cm.get_cmap(name='spectral', lut=128) #self.axes.set_color_cycle([colormap(i) for i in numpy.linspace(0.1, 0.9, len(self.gui.getTestrunList()))]) # call the plot on the collected data self.primalpatches, self.primallines, _ = self.axisPlotForTestrunData( x, y, baseline=baseline, legend=False, labelsuffix=" (primal)", plotkw=kws, barkw=kws, labelorder=labelorder) if showdualbound: __, self.duallines, _ = self.axisPlotForTestrunData( zx, z, step=False, baseline=0, legend=False, labelsuffix=" (dual)", plotkw=duallinekws, barkw=dualbarkws, labelorder=labelorder) # set a legend and limits self.sc.axes.legend(fontsize=8) self.sc.axes.set_xlim( (xmin - 0.05 * (xmax - xmin), xmax + 0.05 * (xmax - xmin))) self.sc.axes.set_ylim( (ymin - 0.1 * (ymax - ymin), ymax + 0.1 * (ymax - ymin)), emit=True) self.sc.draw() def axisPlotForTestrunData(self, dataX, dataY, bars=False, step=True, barwidthfactor=1.0, baseline=0, testrunnames=None, legend=True, labelsuffix="", colormapname="spectral", plotkw=None, barkw=None, labelorder=[]): """ create a plot for your X and Y data. The data can either be specified as matrix, or as a dictionary specifying containing the labels as keys. - returns the axes object and a dictionary {label:line} of the line plots that were added arguments: -dataX : The X data for the plot, exspected either as 1: A dictionary with the plot labels as keys and some iterable as value-list OR 2: A list of some iterables which denote the X values. -dataY : The y plot data of the plot. Must be specified in the same way as the X data -testrunnames: labels for axis legend. they will overwrite the labels specified by dictionary-organized data. if testrunnames == None, the primallines will either be labelled from '0' to 'len(dataX)-1', or inferred from the dataX-keys(). -ax: matplotlib axes object, will be created as new axis if not specified -legend: specify if legend should be created, default True -colormapname: name of the colormap to use in case no colors are specified by the 'colors' argument -kw, other keywords for the plotting function, such as transparency, etc. can be specified for every plot separately, either as a dictionary with the dataX-keys, or as a kw-list with the same length as the dataX list """ # index everything by labels, either given as dictionary keys, or integer indices ranging from 0 to len(dataX) - 1 assert type(dataX) is type(dataY) if type(dataX) is dict: labels = list(dataX.keys()) if testrunnames is None: testrunnames = {label: label for label in labels} else: assert type(dataX) is list labels = list(range(len(dataX))) if testrunnames is None: testrunnames = {label: repr(label) for label in labels} # init colors if not given try: colormap = cm.get_cmap(name=colormapname, lut=128) except ValueError: print("Colormap of name ", colormapname, " does not exist") colormap = cm.get_cmap(name=IpetPbHistoryWindow.default_cmap, lut=128) colortransform = numpy.linspace(0.1, 0.9, len(labels)) colors = { label: colormap(colortransform[index]) for index, label in enumerate(labels) } patches = {} lines = {} if not labelorder: labelorder = sorted(labels) for label in labelorder: # retrieve special key words, or use the entire keyword dictionary if plotkw is not None: linekw = plotkw.get(testrunnames[label], plotkw) else: linekw = {} if barkw is not None: bkw = barkw.get(testrunnames[label], barkw) else: bkw = {} x = dataX[label] y = dataY[label] idd = testrunnames[label] if bars: patches[idd] = self.sc.axes.bar(x[:-1], y[:-1], width=barwidthfactor * (x[1:] - x[:-1]), bottom=baseline, color=colors[label], linewidth=0, **bkw) else: patches[idd] = [] # # use step functions for primal and plot for dual plots plotlabel = idd + labelsuffix if step: #lines[idd], = ax.step(x, y + baseline, color=colors[label], label=idd, where='post') lines[idd], = self.sc.axes.step(x, y, label=plotlabel, where='post') else: #lines[idd], = ax.plot(x, y + baseline, color=colors[label], label=idd, **linekw) lines[idd], = self.sc.axes.plot(x, y + baseline, label=plotlabel, **linekw) if len(labels) > 0 and legend: self.sc.axes.legend(fontsize=8) return (patches, lines, self.sc.axes) def resetAxis(self): """ reset axis by removing all primallines and primalpatches previously drawn. """ self.sc.axes.cla() def about(self): QtGui.QMessageBox.about( self, "About", """embedding_in_qt4.py example Copyright 2005 Florent Rougon, 2006 Darren Dale This program is a simple example of a Qt4 application embedding matplotlib canvases. It may be used and modified with no restriction; raw copies as well as modified versions may be distributed without limitation.""")
class ManageKeysDialog(QDialog): def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext=u""): QDialog.__init__(self, parent) self.parent = parent self.key_type_name = key_type_name self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext self.import_key = (keyfile_ext != u"") self.binary_file = (key_type_name == u"Adobe Digital Editions Key") self.json_file = (key_type_name == u"Kindle for Mac and PC Key") self.setWindowTitle("{0} {1}: Manage {2}s".format( PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) # Start Qt Gui dialog layout layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) layout.addWidget(keys_group_box) keys_group_box_layout = QHBoxLayout() keys_group_box.setLayout(keys_group_box_layout) self.listy = QListWidget(self) self.listy.setToolTip( u"{0}s that will be used to decrypt ebooks".format( self.key_type_name)) self.listy.setSelectionMode(QAbstractItemView.SingleSelection) self.populate_list() keys_group_box_layout.addWidget(self.listy) button_layout = QVBoxLayout() keys_group_box_layout.addLayout(button_layout) self._add_key_button = QtGui.QToolButton(self) self._add_key_button.setToolTip(u"Create new {0}".format( self.key_type_name)) self._add_key_button.setIcon(QIcon(I('plus.png'))) self._add_key_button.clicked.connect(self.add_key) button_layout.addWidget(self._add_key_button) self._delete_key_button = QtGui.QToolButton(self) self._delete_key_button.setToolTip(_(u"Delete highlighted key")) self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) self._delete_key_button.clicked.connect(self.delete_key) button_layout.addWidget(self._delete_key_button) if type(self.plugin_keys) == dict: self._rename_key_button = QtGui.QToolButton(self) self._rename_key_button.setToolTip(_(u"Rename highlighted key")) self._rename_key_button.setIcon(QIcon(I('edit-select-all.png'))) self._rename_key_button.clicked.connect(self.rename_key) button_layout.addWidget(self._rename_key_button) self.export_key_button = QtGui.QToolButton(self) self.export_key_button.setToolTip( u"Save highlighted key to a .{0} file".format( self.keyfile_ext)) self.export_key_button.setIcon(QIcon(I('save.png'))) self.export_key_button.clicked.connect(self.export_key) button_layout.addWidget(self.export_key_button) spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) button_layout.addItem(spacerItem) layout.addSpacing(5) migrate_layout = QHBoxLayout() layout.addLayout(migrate_layout) if self.import_key: migrate_layout.setAlignment(Qt.AlignJustify) self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self) self.migrate_btn.setToolTip( u"Import *.{0} files (created using other tools).".format( self.keyfile_ext)) self.migrate_btn.clicked.connect(self.migrate_wrapper) migrate_layout.addWidget(self.migrate_btn) migrate_layout.addStretch() self.button_box = QDialogButtonBox(QDialogButtonBox.Close) self.button_box.rejected.connect(self.close) migrate_layout.addWidget(self.button_box) self.resize(self.sizeHint()) def populate_list(self): if type(self.plugin_keys) == dict: for key in self.plugin_keys.keys(): self.listy.addItem(QListWidgetItem(key)) else: for key in self.plugin_keys: self.listy.addItem(QListWidgetItem(key)) def add_key(self): d = self.create_key(self) d.exec_() if d.result() != d.Accepted: # New key generation cancelled. return new_key_value = d.key_value if type(self.plugin_keys) == dict: if new_key_value in self.plugin_keys.values(): old_key_name = [ name for name, value in self.plugin_keys.iteritems() if value == new_key_value ][0] info_dialog( None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name), u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added." .format(old_key_name, self.key_type_name), show=True) return self.plugin_keys[d.key_name] = new_key_value else: if new_key_value in self.plugin_keys: info_dialog( None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name), u"This {0} is already in the list of {0}s has not been added." .format(self.key_type_name), show=True) return self.plugin_keys.append(d.key_value) self.listy.clear() self.populate_list() def rename_key(self): if not self.listy.currentItem(): errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format( self.key_type_name) r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return d = RenameKeyDialog(self) d.exec_() if d.result() != d.Accepted: # rename cancelled or moot. return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog( self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?" .format(keyname, d.key_name, self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys[d.key_name] = self.plugin_keys[keyname] del self.plugin_keys[keyname] self.listy.clear() self.populate_list() def delete_key(self): if not self.listy.currentItem(): return keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if not question_dialog( self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?". format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return if type(self.plugin_keys) == dict: del self.plugin_keys[keyname] else: self.plugin_keys.remove(keyname) self.listy.clear() self.populate_list() def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. help_file_name = u"{0}_{1}_Help.htm".format( PLUGIN_NAME, self.key_type_name) file_path = os.path.join(config_dir, u"plugins", u"DeDRM", u"help", help_file_name) with open(file_path, 'w') as f: f.write(self.parent.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url)) def migrate_files(self): dynamic[PLUGIN_NAME + u"config_dir"] = config_dir files = choose_files( self, PLUGIN_NAME + u"config_dir", u"Select {0} files to import".format(self.key_type_name), [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])], False) counter = 0 skipped = 0 if files: for filename in files: fpath = os.path.join(config_dir, filename) filename = os.path.basename(filename) new_key_name = os.path.splitext(os.path.basename(filename))[0] with open(fpath, 'rb') as keyfile: new_key_value = keyfile.read() if self.binary_file: new_key_value = new_key_value.encode('hex') elif self.json_file: new_key_value = json.loads(new_key_value) match = False for key in self.plugin_keys.keys(): if uStrCmp(new_key_name, key, True): skipped += 1 msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file <strong>{1}</strong>.\nRename the existing key and import again".format( new_key_name, filename) inf = info_dialog(None, "{0} {1}".format( PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) match = True break if not match: if new_key_value in self.plugin_keys.values(): old_key_name = [ name for name, value in self.plugin_keys.iteritems() if value == new_key_value ][0] skipped += 1 info_dialog( None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped." .format(filename, old_key_name), show_copy_button=False, show=True) else: counter += 1 self.plugin_keys[new_key_name] = new_key_value msg = u"" if counter + skipped > 1: if counter > 0: msg += u"Imported <strong>{0:d}</strong> key {1}. ".format( counter, u"file" if counter == 1 else u"files") if skipped > 0: msg += u"Skipped <strong>{0:d}</strong> key {1}.".format( skipped, u"file" if counter == 1 else u"files") inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(msg), show_copy_button=False, show=True) return counter > 0 def migrate_wrapper(self): if self.migrate_files(): self.listy.clear() self.populate_list() def export_key(self): if not self.listy.currentItem(): errmsg = u"No keyfile selected to export. Highlight a keyfile first." r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return filter = QString(u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext)) keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') if dynamic.get(PLUGIN_NAME + 'save_dir'): defaultname = os.path.join( dynamic.get(PLUGIN_NAME + 'save_dir'), u"{0}.{1}".format(keyname, self.keyfile_ext)) else: defaultname = os.path.join( os.path.expanduser('~'), u"{0}.{1}".format(keyname, self.keyfile_ext)) filename = unicode( QtGui.QFileDialog.getSaveFileName( self, u"Save {0} File as...".format(self.key_type_name), defaultname, u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext), filter)) if filename: dynamic[PLUGIN_NAME + 'save_dir'] = os.path.split(filename)[0] with file(filename, 'w') as fname: if self.binary_file: fname.write(self.plugin_keys[keyname].decode('hex')) elif self.json_file: fname.write(json.dumps(self.plugin_keys[keyname])) else: fname.write(self.plugin_keys[keyname])
from __future__ import unicode_literals, division, absolute_import, print_function __license__ = "GPL v3" __copyright__ = "2012, Kovid Goyal <kovid at kovidgoyal.net>" __docformat__ = "restructuredtext en" from calibre.gui2 import Application from PyQt4.Qt import QDialog, QGridLayout, QListWidget, QDialogButtonBox, QPushButton, QTimer, QIcon app = Application([], force_calibre_style=True) d = QDialog() d.l = l = QGridLayout() d.setLayout(l) lw = QListWidget() lw.addItem("Some text guy") l.addWidget(lw, 0, 0, 2, 1) bb = QDialogButtonBox() bb.setStandardButtons(bb.Close) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) b = bb.addButton("Action", bb.ActionRole) b.setIcon(QIcon(I("wizard.png"))) l.addWidget(bb, 2, 0, 1, 2) bb.button(bb.Close).setDefault(True) b = QPushButton("Normal") l.addWidget(b, 0, 1, 1, 1) def print_button_sizes():