def show_report(changed, title, report, parent, show_current_diff): report = format_report(title, report) d = QDialog(parent) d.setWindowTitle(_('Action report')) d.l = QVBoxLayout() d.setLayout(d.l) d.e = QTextBrowser(d) d.l.addWidget(d.e) d.e.setHtml(report) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) d.show_changes = False if changed: b = d.b = d.bb.addButton(_('See what &changed'), d.bb.AcceptRole) b.setIcon(QIcon(I('diff.png'))), b.setAutoDefault(False) connect_lambda(b.clicked, d, lambda d: setattr(d, 'show_changes', True)) b = d.bb.addButton(_('&Copy to clipboard'), d.bb.ActionRole) b.setIcon(QIcon(I('edit-copy.png'))), b.setAutoDefault(False) def copy_report(): text = re.sub(r'</.+?>', '\n', report) text = re.sub(r'<.+?>', '', text) cp = QApplication.instance().clipboard() cp.setText(text) b.clicked.connect(copy_report) d.bb.button(d.bb.Close).setDefault(True) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) d.resize(600, 400) d.exec_() b.clicked.disconnect() if d.show_changes: show_current_diff(allow_revert=True)
def view_server_logs(self): from calibre.srv.embedded import log_paths log_error_file, log_access_file = log_paths() d = QDialog(self) d.resize(QSize(800, 600)) layout = QVBoxLayout() d.setLayout(layout) layout.addWidget(QLabel(_('Error log:'))) el = QPlainTextEdit(d) layout.addWidget(el) try: el.setPlainText( lopen(log_error_file, 'rb').read().decode('utf8', 'replace')) except EnvironmentError: el.setPlainText(_('No error log found')) layout.addWidget(QLabel(_('Access log:'))) al = QPlainTextEdit(d) layout.addWidget(al) try: al.setPlainText( lopen(log_access_file, 'rb').read().decode('utf8', 'replace')) except EnvironmentError: al.setPlainText(_('No access log found')) loc = QLabel( _('The server log files are in: {}').format( os.path.dirname(log_error_file))) loc.setWordWrap(True) layout.addWidget(loc) bx = QDialogButtonBox(QDialogButtonBox.Ok) layout.addWidget(bx) bx.accepted.connect(d.accept) d.show()
def customize_remove_unused_css(name, parent, ans): d = QDialog(parent) d.l = l = QVBoxLayout() d.setLayout(d.l) d.setWindowTitle(_('Remove unused CSS')) def label(text): la = QLabel(text) la.setWordWrap(True), l.addWidget(la), la.setMinimumWidth(450) l.addWidget(la) return la d.la = label(_( 'This will remove all CSS rules that do not match any actual content.' ' There are a couple of additional cleanups you can enable, below:')) d.c = c = QCheckBox(_('Remove unused &class attributes')) c.setChecked(tprefs['remove_unused_classes']) l.addWidget(c) d.la2 = label('<span style="font-size:small; font-style: italic">' + _( 'Remove all class attributes from the HTML that do not match any existing CSS rules')) d.m = m = QCheckBox(_('Merge identical CSS rules')) m.setChecked(tprefs['merge_identical_selectors']) l.addWidget(m) d.la3 = label('<span style="font-size:small; font-style: italic">' + _( 'Merge CSS rules in the same stylesheet that have identical selectors.' ' Note that in rare cases merging can result in a change to the effective styling' ' of the book, so use with care.')) d.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) if d.exec_() != d.Accepted: raise Abort() ans['remove_unused_classes'] = tprefs['remove_unused_classes'] = c.isChecked() ans['merge_identical_selectors'] = tprefs['merge_identical_selectors'] = m.isChecked()
def add_builtin_recipe(self): from calibre.web.feeds.recipes.collection import \ get_builtin_recipe_collection, get_builtin_recipe_by_id from PyQt5.Qt import QDialog, QVBoxLayout, QListWidgetItem, \ QListWidget, QDialogButtonBox, QSize d = QDialog(self) d.l = QVBoxLayout() d.setLayout(d.l) d.list = QListWidget(d) d.list.doubleClicked.connect(lambda x: d.accept()) d.l.addWidget(d.list) d.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel, Qt.Horizontal, d) d.bb.accepted.connect(d.accept) d.bb.rejected.connect(d.reject) d.l.addWidget(d.bb) d.setWindowTitle(_('Choose builtin recipe')) items = [] for r in get_builtin_recipe_collection(): id_ = r.get('id', '') title = r.get('title', '') lang = r.get('language', '') if id_ and title: items.append((title + ' [%s]'%lang, id_)) items.sort(key=lambda x:sort_key(x[0])) for title, id_ in items: item = QListWidgetItem(title) item.setData(Qt.UserRole, id_) d.list.addItem(item) d.resize(QSize(450, 400)) ret = d.exec_() d.list.doubleClicked.disconnect() if ret != d.Accepted: return items = list(d.list.selectedItems()) if not items: return item = items[-1] id_ = unicode(item.data(Qt.UserRole) or '') title = unicode(item.data(Qt.DisplayRole) or '').rpartition(' [')[0] profile = get_builtin_recipe_by_id(id_, download_recipe=True) if profile is None: raise Exception('Something weird happened') if self._model.has_title(title): if question_dialog(self, _('Replace recipe?'), _('A custom recipe named %s already exists. Do you want to ' 'replace it?')%title): self._model.replace_by_title(title, profile) else: return else: self.model.add(title, profile) self.clear()
def test(): app = QApplication([]) app d = QDialog() d.setLayout(QVBoxLayout()) d.layout().addWidget(FontFamilyChooser(d)) d.layout().addWidget(QFontComboBox(d)) d.exec_()
def do_user_config(self, parent=None): ''' This method shows a configuration dialog for this plugin. It returns True if the user clicks OK, False otherwise. The changes are automatically applied. ''' from PyQt5.Qt import (QDialog, QDialogButtonBox, QVBoxLayout, QLabel, Qt, QLineEdit, QCheckBox) config_dialog = QDialog(parent) button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) v = QVBoxLayout(config_dialog) def size_dialog(): config_dialog.resize(config_dialog.sizeHint()) button_box.accepted.connect(config_dialog.accept) button_box.rejected.connect(config_dialog.reject) config_dialog.setWindowTitle(_('Customize') + ' ' + self.name) from calibre.customize.ui import (plugin_customization, customize_plugin) help_text = self.customization_help(gui=True) help_text = QLabel(help_text, config_dialog) help_text.setWordWrap(True) help_text.setTextInteractionFlags( Qt.TextInteractionFlag.LinksAccessibleByMouse | Qt.TextInteractionFlag.LinksAccessibleByKeyboard) help_text.setOpenExternalLinks(True) v.addWidget(help_text) bf = QCheckBox(_('Add linked files in breadth first order')) bf.setToolTip( _('Normally, when following links in HTML files' ' calibre does it depth first, i.e. if file A links to B and ' ' C, but B links to D, the files are added in the order A, B, D, C. ' ' With this option, they will instead be added as A, B, C, D')) sc = plugin_customization(self) if not sc: sc = '' sc = sc.strip() enc = sc.partition('|')[0] bfs = sc.partition('|')[-1] bf.setChecked(bfs == 'bf') sc = QLineEdit(enc, config_dialog) v.addWidget(sc) v.addWidget(bf) v.addWidget(button_box) size_dialog() config_dialog.exec_() if config_dialog.result() == QDialog.DialogCode.Accepted: sc = unicode_type(sc.text()).strip() if bf.isChecked(): sc += '|bf' customize_plugin(self, sc) return config_dialog.result()
def view_server_logs(self): from calibre.srv.embedded import log_paths log_error_file, log_access_file = log_paths() d = QDialog(self) d.resize(QSize(800, 600)) layout = QVBoxLayout() d.setLayout(layout) layout.addWidget(QLabel(_('Error log:'))) el = QPlainTextEdit(d) layout.addWidget(el) try: el.setPlainText( lopen(log_error_file, 'rb').read().decode('utf8', 'replace')) except EnvironmentError: el.setPlainText(_('No error log found')) layout.addWidget(QLabel(_('Access log:'))) al = QPlainTextEdit(d) layout.addWidget(al) try: al.setPlainText( lopen(log_access_file, 'rb').read().decode('utf8', 'replace')) except EnvironmentError: al.setPlainText(_('No access log found')) loc = QLabel( _('The server log files are in: {}').format( os.path.dirname(log_error_file))) loc.setWordWrap(True) layout.addWidget(loc) bx = QDialogButtonBox(QDialogButtonBox.Ok) layout.addWidget(bx) bx.accepted.connect(d.accept) b = bx.addButton(_('&Clear logs'), bx.ActionRole) def clear_logs(): if getattr(self.server, 'is_running', False): return error_dialog( d, _('Server running'), _('Cannot clear logs while the server is running. First stop the server.' ), show=True) if self.server: self.server.access_log.clear() self.server.log.clear() else: for x in (log_error_file, log_access_file): try: os.remove(x) except EnvironmentError as err: if err.errno != errno.ENOENT: raise el.setPlainText(''), al.setPlainText('') b.clicked.connect(clear_logs) d.show()
def get_bulk_rename_settings(parent, number, msg=None, sanitize=sanitize_file_name_unicode, leading_zeros=True, prefix=None, category='text', allow_spine_order=False): # {{{ d = QDialog(parent) d.setWindowTitle(_('Bulk rename items')) d.l = l = QFormLayout(d) d.setLayout(l) d.prefix = p = QLineEdit(d) default_prefix = {k: v for k, __, v in CATEGORIES}.get(category, _('Chapter-')) previous = tprefs.get('file-list-bulk-rename-prefix', {}) prefix = prefix or previous.get(category, default_prefix) p.setText(prefix) p.selectAll() d.la = la = QLabel( msg or _('All selected files will be renamed to the form prefix-number')) l.addRow(la) l.addRow(_('&Prefix:'), p) d.num = num = QSpinBox(d) num.setMinimum(0), num.setValue(1), num.setMaximum(1000) l.addRow(_('Starting &number:'), num) if allow_spine_order: d.spine_order = QCheckBox( _('Rename files according to their book order')) d.spine_order.setToolTip( textwrap.fill( _('Rename the selected files according to the order they appear in the book, instead of the order they were selected in.' ))) l.addRow(d.spine_order) d.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) l.addRow(bb) ans = {'prefix': None, 'start': None} if d.exec_() == d.Accepted: prefix = sanitize(unicode(d.prefix.text())) previous[category] = prefix tprefs.set('file-list-bulk-rename-prefix', previous) num = d.num.value() fmt = '%d' if leading_zeros: largest = num + number - 1 fmt = '%0{0}d'.format(len(str(largest))) ans['prefix'] = prefix + fmt ans['start'] = num if allow_spine_order: ans['spine_order'] = d.spine_order.isChecked() return ans
def ask_link(self): d = QDialog(self) d.setWindowTitle(_('Create link')) l = QFormLayout() l.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) d.setLayout(l) d.url = QLineEdit(d) d.name = QLineEdit(d) d.treat_as_image = QCheckBox(d) d.setMinimumWidth(600) d.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) d.br = b = QPushButton(_('&Browse')) b.setIcon(QIcon(I('document_open.png'))) def cf(): files = choose_files(d, 'select link file', _('Choose file'), select_only_single_file=True) if files: path = files[0] d.url.setText(path) if path and os.path.exists(path): with lopen(path, 'rb') as f: q = what(f) is_image = q in {'jpeg', 'png', 'gif'} d.treat_as_image.setChecked(is_image) b.clicked.connect(cf) d.la = la = QLabel( _('Enter a URL. If you check the "Treat the URL as an image" box ' 'then the URL will be added as an image reference instead of as ' 'a link. You can also choose to create a link to a file on ' 'your computer. ' 'Note that if you create a link to a file on your computer, it ' 'will stop working if the file is moved.')) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-bottom: 1.5ex }') l.setWidget(0, l.SpanningRole, la) l.addRow(_('Enter &URL:'), d.url) l.addRow(_('Treat the URL as an &image'), d.treat_as_image) l.addRow(_('Enter &name (optional):'), d.name) l.addRow(_('Choose a file on your computer:'), d.br) l.addRow(d.bb) d.bb.accepted.connect(d.accept) d.bb.rejected.connect(d.reject) d.resize(d.sizeHint()) link, name, is_image = None, None, False if d.exec_() == d.Accepted: link, name = unicode_type(d.url.text()).strip(), unicode_type( d.name.text()).strip() is_image = d.treat_as_image.isChecked() return link, name, is_image
def link_stylesheets(self, names): s = self.categories['styles'] sheets = [ unicode(s.child(i).data(0, NAME_ROLE) or '') for i in xrange(s.childCount()) ] if not sheets: return error_dialog( self, _('No stylesheets'), _('This book currently has no stylesheets. You must first create a stylesheet' ' before linking it.'), show=True) d = QDialog(self) d.l = l = QVBoxLayout(d) d.setLayout(l) d.setWindowTitle(_('Choose stylesheets')) d.la = la = QLabel( _('Choose the stylesheets to link. Drag and drop to re-arrange')) la.setWordWrap(True) l.addWidget(la) d.s = s = QListWidget(d) l.addWidget(s) s.setDragEnabled(True) s.setDropIndicatorShown(True) s.setDragDropMode(self.InternalMove) s.setAutoScroll(True) s.setDefaultDropAction(Qt.MoveAction) for name in sheets: i = QListWidgetItem(name, s) flags = Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable i.setFlags(flags) i.setCheckState(Qt.Checked) d.r = r = QCheckBox(_('Remove existing links to stylesheets')) r.setChecked(tprefs['remove_existing_links_when_linking_sheets']) l.addWidget(r) d.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) l.addWidget(bb) if d.exec_() == d.Accepted: tprefs['remove_existing_links_when_linking_sheets'] = r.isChecked() sheets = [ unicode(s.item(il).text()) for il in xrange(s.count()) if s.item(il).checkState() == Qt.Checked ] if sheets: self.link_stylesheets_requested.emit(names, sheets, r.isChecked())
def show_devtools(self): if not hasattr(self, '_devtools_page'): self._devtools_page = QWebEnginePage() self._devtools_view = QWebEngineView(self) self._devtools_view.setPage(self._devtools_page) self._page.setDevToolsPage(self._devtools_page) self._devtools_dialog = d = QDialog(self) d.setWindowTitle('Inspect Lookup page') v = QVBoxLayout(d) v.addWidget(self._devtools_view) d.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) d.bb.rejected.connect(d.reject) v.addWidget(d.bb) d.resize(QSize(800, 600)) d.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False) self._devtools_dialog.show() self._page.triggerAction(QWebEnginePage.WebAction.InspectElement)
def customize_recipe(self): d = QDialog(self) d.l = QVBoxLayout() d.setLayout(d.l) d.list = QListWidget(d) connect_lambda(d.list.doubleClicked, d, lambda d: d.accept()) d.l.addWidget(d.list) d.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, d) d.bb.accepted.connect(d.accept) d.bb.rejected.connect(d.reject) d.l.addWidget(d.bb) d.setWindowTitle(_('Choose builtin recipe')) items = [] for r in get_builtin_recipe_collection(): id_ = r.get('id', '') title = r.get('title', '') lang = r.get('language', '') if id_ and title: items.append((title + ' [%s]' % lang, id_)) items.sort(key=lambda x: sort_key(x[0])) for title, id_ in items: item = QListWidgetItem(title) item.setData(Qt.UserRole, id_) d.list.addItem(item) d.resize(QSize(450, 400)) ret = d.exec_() d.list.doubleClicked.disconnect() if ret != d.Accepted: return items = list(d.list.selectedItems()) if not items: return item = items[-1] id_ = unicode_type(item.data(Qt.UserRole) or '') title = unicode_type(item.data(Qt.DisplayRole) or '').rpartition(' [')[0] src = get_builtin_recipe_by_id(id_, download_recipe=True) if src is None: raise Exception('Something weird happened') src = as_unicode(src) self.edit_recipe(None, src)
def change_builtin(self): d = QDialog(self) lw = QListWidget(d) for (trigger, syntaxes), snip in iteritems(builtin_snippets): snip = copy.deepcopy(snip) snip['trigger'], snip['syntaxes'] = trigger, syntaxes i = QListWidgetItem(self.snip_to_text(snip), lw) i.setData(Qt.ItemDataRole.UserRole, snip) d.l = l = QVBoxLayout(d) l.addWidget(QLabel(_('Choose the built-in snippet to modify:'))) l.addWidget(lw) lw.itemDoubleClicked.connect(d.accept) d.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) l.addWidget(bb) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) if d.exec_() == QDialog.DialogCode.Accepted and lw.currentItem() is not None: self.stack.setCurrentIndex(1) self.edit_snip.apply_snip(lw.currentItem().data(Qt.ItemDataRole.UserRole), creating_snippet=True)
def do_config(self): # Save values that need to be synced between the dialog and the # search widget. self.config['open_external'] = self.open_external.isChecked() # Create the config dialog. It's going to put two config widgets # into a QTabWidget for displaying all of the settings. d = QDialog(self) button_box = QDialogButtonBox(QDialogButtonBox.Close) v = QVBoxLayout(d) button_box.accepted.connect(d.accept) button_box.rejected.connect(d.reject) d.setWindowTitle(_('Customize Get books search')) tab_widget = QTabWidget(d) v.addWidget(tab_widget) v.addWidget(button_box) chooser_config_widget = StoreChooserWidget() search_config_widget = StoreConfigWidget(self.config) tab_widget.addTab(chooser_config_widget, _('Choose s&tores')) tab_widget.addTab(search_config_widget, _('Configure s&earch')) # Restore dialog state. geometry = self.config.get('config_dialog_geometry', None) if geometry: QApplication.instance().safe_restore_geometry(d, geometry) else: d.resize(800, 600) tab_index = self.config.get('config_dialog_tab_index', 0) tab_index = min(tab_index, tab_widget.count() - 1) tab_widget.setCurrentIndex(tab_index) d.exec_() # Save dialog state. self.config['config_dialog_geometry'] = bytearray(d.saveGeometry()) self.config['config_dialog_tab_index'] = tab_widget.currentIndex() search_config_widget.save_settings() self.config_changed() self.gui.load_store_plugins() self.setup_store_checks()
def show_debug_info(self): info = self.device.device_debug_info() d = QDialog(self) d.l = l = QVBoxLayout() d.setLayout(l) d.v = v = QPlainTextEdit() d.setWindowTitle(self.device.get_gui_name()) v.setPlainText(info) v.setMinimumWidth(400) v.setMinimumHeight(350) l.addWidget(v) bb = d.bb = QDialogButtonBox(QDialogButtonBox.Close) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) l.addWidget(bb) bb.addButton(_('Copy to clipboard'), bb.ActionRole) bb.clicked.connect( lambda: QApplication.clipboard().setText(v.toPlainText())) d.exec_()
def manual_input(self): self.status_label.setText("") edit_dialog = QDialog(self) verticalLayout = QVBoxLayout(edit_dialog) title_input = QLineEdit('title here', edit_dialog) editor = QTextEdit(edit_dialog) verticalLayout.addWidget(title_input) verticalLayout.addWidget(editor) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.manual_input_text = "" self.manual_input_title = "" def editor_accepted(): if editor.toPlainText(): self.manual_input_text = editor.toHtml() self.manual_input_title = title_input.text().strip() edit_dialog.close() def editor_rejected(): edit_dialog.close() buttonBox.accepted.connect(editor_accepted) buttonBox.rejected.connect(editor_rejected) verticalLayout.addWidget(buttonBox) edit_dialog.exec_() if self.manual_input_text: existing_doc_id_list_part = [] # existing feed id between now and mark conn = sqlite3.connect(get_path("user_files", "doc.db"), detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES) cur = conn.cursor() cur.execute("select feed_id from doc where feed_id between ? and ?", (int(time.time()*1000), int(time.time()*1000)+10000)) while True: doc_id = int(time.time()*1000) if doc_id not in existing_doc_id_list_part: break cur.execute("""insert into doc (doc_id, title, descr, doc_type) values (?, ?, ?, 'mi')""", (doc_id, self.manual_input_title, self.manual_input_text)) conn.commit() conn.close() self.manual_input_text = "" self.status_label.setText("Manual Load Completed")
def show_report(changed, title, report, parent, show_current_diff): report = format_report(title, report) d = QDialog(parent) d.l = QVBoxLayout() d.setLayout(d.l) d.e = QTextBrowser(d) d.l.addWidget(d.e) d.e.setHtml(report) d.bb = QDialogButtonBox(QDialogButtonBox.Close) if changed: b = d.b = d.bb.addButton(_('See what &changed'), d.bb.AcceptRole) b.setIcon(QIcon(I('diff.png'))), b.setAutoDefault(False) b.clicked.connect(partial(show_current_diff, allow_revert=True)) d.bb.button(d.bb.Close).setDefault(True) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) d.resize(600, 400) d.exec_()
def get_bulk_rename_settings(parent, number, msg=None, sanitize=sanitize_file_name_unicode, leading_zeros=True, prefix=None, category='text'): # {{{ d = QDialog(parent) d.setWindowTitle(_('Bulk rename items')) d.l = l = QFormLayout(d) d.setLayout(l) d.prefix = p = QLineEdit(d) default_prefix = {k: v for k, __, v in CATEGORIES}.get(category, _('Chapter-')) previous = tprefs.get('file-list-bulk-rename-prefix', {}) prefix = prefix or previous.get(category, default_prefix) p.setText(prefix) p.selectAll() d.la = la = QLabel( msg or _('All selected files will be renamed to the form prefix-number')) l.addRow(la) l.addRow(_('&Prefix:'), p) d.num = num = QSpinBox(d) num.setMinimum(0), num.setValue(1), num.setMaximum(1000) l.addRow(_('Starting &number:'), num) d.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(d.accept), bb.rejected.connect(d.reject) l.addRow(bb) if d.exec_() == d.Accepted: prefix = sanitize(unicode(d.prefix.text())) previous[category] = prefix tprefs.set('file-list-bulk-rename-prefix', previous) num = d.num.value() fmt = '%d' if leading_zeros: largest = num + number - 1 fmt = '%0{0}d'.format(len(str(largest))) return prefix + fmt, num return None, None
def customize_remove_unused_css(name, parent, ans): d = QDialog(parent) d.l = l = QVBoxLayout() d.setLayout(d.l) d.setWindowTitle(_('Remove unused CSS')) d.la = la = QLabel( _('This will remove all CSS rules that do not match any actual content. You' ' can also have it automatically remove any class attributes from the HTML' ' that do not match any CSS rules, by using the check box below:')) la.setWordWrap(True), l.addWidget(la) d.c = c = QCheckBox(_('Remove unused &class attributes')) c.setChecked(tprefs['remove_unused_classes']) l.addWidget(c) d.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) d.l.addWidget(d.bb) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) if d.exec_() != d.Accepted: raise Abort() ans['remove_unused_classes'] = tprefs[ 'remove_unused_classes'] = c.isChecked()
def do_user_config(self, parent=None): ''' This method shows a configuration dialog for this plugin. It returns True if the user clicks OK, False otherwise. The changes are automatically applied. ''' from PyQt5.Qt import QDialog, QDialogButtonBox, QVBoxLayout from calibre.gui2 import gprefs prefname = 'plugin config dialog:' + self.type + ':' + self.name geom = gprefs.get(prefname, None) config_dialog = QDialog(parent) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) layout = QVBoxLayout(config_dialog) def size_dialog(): '''Sets size of dialog''' if geom is None: config_dialog.resize(config_dialog.sizeHint()) else: config_dialog.restoreGeometry(geom) button_box.accepted.connect( lambda: self.validate(config_dialog, config_widget)) button_box.rejected.connect(config_dialog.reject) config_dialog.setWindowTitle('Customize ' + self.name) config_widget = self.config_widget() layout.addWidget(config_widget) layout.addWidget(button_box) size_dialog() config_dialog.exec_() geom = bytearray(config_dialog.saveGeometry()) gprefs[prefname] = geom return config_dialog.result()
def _onMenuBarItemSelectComPort(self): ''' Selection of COM port. Starts model on valid port selection. ''' #Stop model self._model.stop() #We are no more connected self.setStatusIndicator(Status.TARGET_OFFLINE) #Create dialog for COM port selection qDialog = QDialog() settingWindow = Ui_AppSettings() settingWindow.setupUi(qDialog) #Get COM ports with connected devices ports = sorted([port.device for port in list_ports.comports()]) #Populate comboBox with found COM ports settingWindow.comboBoxComPorts.clear() settingWindow.comboBoxComPorts.addItems(ports) #Show dialog qDialog.exec_() #Evaluate user selection if QDialog.Accepted == qDialog.result(): # User has accepted by pressing OK button #Get selected COM-Port selectedIdx = settingWindow.comboBoxComPorts.currentIndex() comPort = ports[selectedIdx] self._model.start(comPort) else: # User has rejected by pressing CANCEL button pass
return False # }}} if __name__ == '__main__': from calibre.gui2 import Application from calibre.devices.kobo.driver import KOBOTOUCH from calibre.devices.scanner import DeviceScanner s = DeviceScanner() s.scan() app = Application([]) debug_print("KOBOTOUCH:", KOBOTOUCH) dev = KOBOTOUCH(None) # dev.startup() # cd = dev.detect_managed_devices(s.devices) # dev.open(cd, 'test') cw = dev.config_widget() d = QDialog() d.l = QVBoxLayout() d.setLayout(d.l) d.l.addWidget(cw) bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) d.l.addWidget(bb) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) if d.exec_() == d.Accepted: cw.commit() dev.shutdown()
def __init__(self, model): ''' initialization of class ''' super().__init__() self.value = str() # Current Model we use self._model = model # Application's UI main window self._ui = Ui_MainWindow() # Setup main window self._ui.setupUi(self) #setup numpad self.qDialog = QDialog() self.numpadWindow = Ui_Numpad() self.numpadWindow.setupUi(self.qDialog) self.numpadWindow.numberToSet.setAlignment(QtCore.Qt.AlignRight) self.numpadWindow.numberToSet.setMaxLength(6) self.numpadWindow.numberToSet.setReadOnly(True) self.qLineValidator = QtGui.QIntValidator self.numpadButtons = [ self.numpadWindow.button0, self.numpadWindow.button1, self.numpadWindow.button2, self.numpadWindow.button3, self.numpadWindow.button4, self.numpadWindow.button5, self.numpadWindow.button6, self.numpadWindow.button7, self.numpadWindow.button8, self.numpadWindow.button9 ] for idx, item in enumerate(self.numpadButtons): #print(type(item)) #print(idx) item.setText(str(idx)) item.clicked.connect(lambda: self._buttonpres()) self.numpadWindow.buttonBackspace.clicked.connect(self._dellast) self.numpadWindow.buttonSub.clicked.connect(self._negateValue) # Set UI input objects to default state/value self._setUiInputsToDefault() # Connect UI elements/objects signals and slots self._connectSignalSlots() # Add menu bar items self._addMenubarItems() # Setup Plots self._bvddPlot = self._ui.graphicsViewBVDD.plot([], [], pen=(0, 0, 255)) self._ui.graphicsViewBVDD.setLabel('left', 'BVDD', units='V') self._ui.graphicsViewBVDD.setLabel('bottom', 'Time', units='s') self._ui.graphicsViewBVDD.showGrid(x=True, y=True) self._ui.graphicsViewBVDD.setYRange( DefinedValues.BVDD_Y_MIN_RANGE.value, DefinedValues.BVDD_Y_MAX_RANGE.value, 0, True) self._temperaturePlot = self._ui.graphicsViewTemperature.plot([], [], pen=(0, 255, 0)) self._ui.graphicsViewTemperature.setLabel('left', 'Tj', units='°C') self._ui.graphicsViewTemperature.setLabel('bottom', 'Time', units='s') self._ui.graphicsViewTemperature.showGrid(x=True, y=True) self._ui.graphicsViewTemperature.setYRange( DefinedValues.TJ_Y_MIN_RANGE.value, DefinedValues.TJ_Y_MAX_RANGE.value, 0, True) self._rotorSpeedPlot = self._ui.graphicsViewRotorSpeed.plot([], [], pen=(255, 0, 0)) self._ui.graphicsViewRotorSpeed.setLabel('left', 'Rotor Speed', units='PPS') self._ui.graphicsViewRotorSpeed.setLabel('bottom', 'Time', units='s') self._ui.graphicsViewRotorSpeed.showGrid(x=True, y=True) self._ui.graphicsViewRotorSpeed.setYRange( DefinedValues.RS_Y_MIN_RANGE.value, DefinedValues.RS_Y_MAX_RANGE.value, 0, True) self.__rawCurrentSpeed = 0 self.__currentSpeed = 0 self._picIndex = 0 # first image to be replaced self._picTimer = QTimer() self._picTimer.timeout.connect(self.updatePic) self._picTimer.start(DefinedValues.PIC_SWAP_TIME.value)
def __init__(self): # ---------------------------------------------------------------------------------------------------------- # # START OF APPLICATION # ------------------------ # ------------------------ # Set flags # ------------------------ # *** SET AS SWITCH UP/DOWN *** # self.UP = True self.DOWN = False # *** IMAGES *** # self.ALL_IMG_FORMAT = "All Supported (*.jpg *.jpeg *.jpe *.png *.bmp *.tif *.tiff " \ "*.dib *.pbm *.pgm *.ppm *.sr *.ras)" self.JPG_FORMAT = "JPG (*.jpg *.jpeg *.jpe)" self.PNG_FORMAT = "PNG (*.png)" self.BMP_FORMAT = "BMP (*.bmp)" self.TIF_FORMAT = "TIFF (*.tif *.tiff)" self.DIB_FORMAT = "DIB (*.dib)" self.PBM_FORMAT = "PBM (*.pbm)" self.PGM_FORMAT = "PGM (*.pgm)" self.PPM_FORMAT = "PPM (*.ppm)" self.SR__FORMAT = "SR (*.sr)" self.RAS_FORMAT = "RAS (*.ras)" self.DD = ";;" self.IMG_FILTER = self.ALL_IMG_FORMAT + self.DD + self.JPG_FORMAT + self.DD + self.PNG_FORMAT + self.DD + \ self.BMP_FORMAT + self.DD + self.TIF_FORMAT + self.DD + self.DIB_FORMAT + self.DD + \ self.PBM_FORMAT + self.DD + self.PGM_FORMAT + self.DD + self.PPM_FORMAT + self.DD + \ self.SR__FORMAT + self.DD + self.RAS_FORMAT # *** VIDEOS *** # self.ALL_VID_FORMAT = "All Supported (*.mov *.MOV *.mp4 *.avi)" self.MOV_FORMAT = "MOV (*.mov *.MOV)" self.MP4_FORMAT = "MP4 (*.mp4)" self.AVI_FORMAT = "AVI (*.avi)" self.VID_FILTER = self.ALL_VID_FORMAT + self.DD + self.MOV_FORMAT + self.DD + self.MP4_FORMAT + self.DD\ + self.AVI_FORMAT # *** Qt FLAGS *** # self.DIALOG_FLAG = QFileDialog.DontUseNativeDialog self.Q_ASPECT_RATIO = Qt.KeepAspectRatio # *** FEATURE OPTION FLAG *** # self.F_SIFT = IMG_SIFT self.F_SURF = IMG_SURF self.F_ORB = IMG_ORB self.F_AKAZE = IMG_AKAZE # ------------------------ # Flags Section ends here # ---------------------------------------------------------------------------------------------------------- # # # ------------------------ # Set class items # ------------------------ self.video_list = [] self.image_list = [] self.image_block = ImageBlock() self.img_view_index = 0 self.draw_kp = self.DOWN # ------------------------ # Class items ends here # ---------------------------------------------------------------------------------------------------------- # # ------------------------ # Set up the ui # ------------------------ # *** MAIN_UI *** # self.app = QtWidgets.QApplication(sys.argv) self.ui_main_win = Ui_MainWindow() self.MainWindow = QtWidgets.QMainWindow() self.ui_main_win.setupUi(self.MainWindow) # *** VIDEO TO IMAGES UI *** # self.ui_video2images = Ui_Video2Images() self.Video2Images = QDialog() self.ui_video2images.setupUi(self.Video2Images) # *** SIMPLE IMAGE VIEWER *** # self.ui_simple_img_viewer = Ui_SimpleImageViewer() self.SimpleImageViewer = QDialog() self.ui_simple_img_viewer.setupUi(self.SimpleImageViewer) # *** CRABS SFM UI *** # self.ui_crabSFM = Ui_CrabsSFM() self.WinCrabSFM = QDialog() self.ui_crabSFM.setupUi(self.WinCrabSFM) # ------------------------ # Setting up ends here # ---------------------------------------------------------------------------------------------------------- # # ------------------------ # Actions list starts here # ------------------------ # *** UI_MAIN_WIN *** # # ** FILE ** # self.ui_main_win.actionExit.triggered.connect(self.exit_window) # actionExit # *** IMAGE *** # self.ui_main_win.actionImageImport.triggered.connect(self.image_import) # actionImageImport self.ui_main_win.button_add_image.clicked.connect(self.image_import) # button_add_image self.ui_main_win.button_del_image.clicked.connect(self.image_delete) # button_del_image self.ui_main_win.actionImage_Viewer.triggered.connect(self.simgv_open) # actionImage_Viewer self.ui_main_win.actionApproximate_Interior_Orientation.triggered.connect(self.image_approximate_camera) self.ui_main_win.actionSIFT.triggered.connect(lambda: self.image_find_feature_points(self.F_SIFT)) self.ui_main_win.actionSURF.triggered.connect(lambda: self.image_find_feature_points(self.F_SURF)) self.ui_main_win.actionORB.triggered.connect(lambda: self.image_find_feature_points(self.F_ORB)) self.ui_main_win.actionAKAZE.triggered.connect(lambda: self.image_find_feature_points(self.F_AKAZE)) self.ui_main_win.actionCreate_Block.triggered.connect(self.image_create_block) self.ui_main_win.actionAll_Images_Matching.triggered.connect(lambda: self.image_matching(fast=False)) self.ui_main_win.actionFast_Matching.triggered.connect(lambda: self.image_matching(fast=True)) self.ui_main_win.actionCreate_Model.triggered.connect(self.image_create_model) self.ui_main_win.actionCrabSFM.triggered.connect(self.crabSFM_open) # *** SIMPLE IMAGE VIEWER *** # self.ui_simple_img_viewer.button_previous.clicked.connect(self.simgv_button_previous) self.ui_simple_img_viewer.button_next.clicked.connect(self.simgv_button_next) self.ui_simple_img_viewer.check_box_draw_keypoints.stateChanged.connect(self.simgv_kp_view_check) # *** CrabSFM UI *** # self.ui_crabSFM.button_cancel.clicked.connect(self.crabSFM_cancel) self.ui_crabSFM.button_compute.clicked.connect(self.crabSFM_compute_threading) # *** VIDEO *** # self.ui_main_win.actionVideoImport.triggered.connect(self.video_import) # actionVideoImport self.ui_main_win.actionVideo_to_Images.triggered.connect(self.video2images) # actionVideo_to_Images self.ui_main_win.button_add_video.clicked.connect(self.video_import) # button_add_video self.ui_main_win.button_del_video.clicked.connect(self.video_delete) # button_del_video # *** UI_VIDEO_2_IMAGES *** # self.ui_video2images.button_cancel.clicked.connect(self.video2images_cancel) self.ui_video2images.button_compute.clicked.connect(self.video2images_compute) self.ui_video2images.combo_box_select_video.currentTextChanged.connect(self.video2images_set_fps_for_video) self.ui_video2images.button_export_images_at.clicked.connect(self.video2images_set_export_folder) # ------------------------ # Actions list ends here # ---------------------------------------------------------------------------------------------------------- # # ------------------------ # Main loop and exit app # ------------------------ self.MainWindow.show() # Main Loop sys.exit(self.app.exec_()) # Close application
def do_user_config(self, parent=None): ''' This method shows a configuration dialog for this plugin. It returns True if the user clicks OK, False otherwise. The changes are automatically applied. ''' from PyQt5.Qt import QDialog, QDialogButtonBox, QVBoxLayout, \ QLabel, Qt, QLineEdit from calibre.gui2 import gprefs prefname = 'plugin config dialog:' + self.type + ':' + self.name geom = gprefs.get(prefname, None) config_dialog = QDialog(parent) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) v = QVBoxLayout(config_dialog) def size_dialog(): if geom is None: config_dialog.resize(config_dialog.sizeHint()) else: from PyQt5.Qt import QApplication QApplication.instance().safe_restore_geometry( config_dialog, geom) button_box.accepted.connect(config_dialog.accept) button_box.rejected.connect(config_dialog.reject) config_dialog.setWindowTitle(_('Customize') + ' ' + self.name) try: config_widget = self.config_widget() except NotImplementedError: config_widget = None if isinstance(config_widget, tuple): from calibre.gui2 import warning_dialog warning_dialog(parent, _('Cannot configure'), config_widget[0], det_msg=config_widget[1], show=True) return False if config_widget is not None: v.addWidget(config_widget) v.addWidget(button_box) size_dialog() config_dialog.exec_() if config_dialog.result() == QDialog.Accepted: if hasattr(config_widget, 'validate'): if config_widget.validate(): self.save_settings(config_widget) else: self.save_settings(config_widget) else: from calibre.customize.ui import plugin_customization, \ customize_plugin help_text = self.customization_help(gui=True) help_text = QLabel(help_text, config_dialog) help_text.setWordWrap(True) help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_text.setOpenExternalLinks(True) v.addWidget(help_text) sc = plugin_customization(self) if not sc: sc = '' sc = sc.strip() sc = QLineEdit(sc, config_dialog) v.addWidget(sc) v.addWidget(button_box) size_dialog() config_dialog.exec_() if config_dialog.result() == QDialog.Accepted: sc = unicode_type(sc.text()).strip() customize_plugin(self, sc) geom = bytearray(config_dialog.saveGeometry()) gprefs[prefname] = geom return config_dialog.result()
def update(self, sim_data_items): """Adds all elements in the iterable *sim_data_items* to the tree or replaces them if they are already present. Issues the *items_changed* signal, after all sim data items are added/replaced. :param sim_data_items: Iterable collection of :class: `SimDataItem`s to be added """ additional_param_found = [] all_enc_configs = {} diff_dict = {} # build up a diff dict in order let the software handle multiple different parameters # in one simulation directory # some of the diffs should not be interpreted as parameters # those are removed from the dict; for sure QP, RealFormat, InternalFormat, and Warning # are not parameters # if you want to simulate with your own parameters, make sure that they appear in the # logfile try: for sim_data_item in sim_data_items: if sim_data_item.__class__ not in all_enc_configs: all_enc_configs[sim_data_item.__class__] = [] diff_dict[sim_data_item.__class__] = {} all_enc_configs[sim_data_item.__class__].append( sim_data_item.encoder_config) # print(sim_data_item.summary_data['encoder_config']) value_filter = ['.yuv', '.bin', '.hevc', '.jem'] key_filter = [] for sim_class in all_enc_configs.keys(): for i in range(len(all_enc_configs[sim_class]) - 1): current_item, next_item = all_enc_configs[sim_class][ i], all_enc_configs[sim_class][i + 1] diff = set(current_item.values()) ^ set(next_item.values()) for (key, value) in set(current_item.items()) ^ set( next_item.items()): if all(y not in key for y in key_filter): if all(x not in value for x in value_filter): if key not in diff_dict[sim_class]: diff_dict[sim_class][key] = [] diff_dict[sim_class][key].append(value) else: if value not in diff_dict[sim_class][key]: diff_dict[sim_class][key].append(value) # dialog window which displays all parameters with varying values in a list # the user can drag the parameters, he wants to analyse further into an other list # the order of the parameters in the list determines the order of the parameter tree if diff_dict[sim_class]: par_list = [ item for item in diff_dict[sim_class] if item != 'QP' ] qp_item = QtWidgets.QListWidgetItem('QP') chosen_par = QtWidgets.QListWidget() chosen_par.addItem(qp_item) chosen_par.setDragDropMode(QAbstractItemView.DragDrop) chosen_par.setDefaultDropAction(QtCore.Qt.MoveAction) not_chosen_par = QtWidgets.QListWidget() not_chosen_par.addItems(par_list) not_chosen_par.setDragDropMode(QAbstractItemView.DragDrop) not_chosen_par.setDefaultDropAction(QtCore.Qt.MoveAction) if len(diff_dict[sim_class]) > 1: main_layout = QVBoxLayout() dialog = QDialog() dialog.setWindowTitle('Choose Parameters') dialog.setLayout(main_layout) msg = QtWidgets.QLabel() msg.setText( 'Additional Parameters have been found.\n' 'Move Parameters you want to consider further to the right list.\n' ) main_layout.addWidget(msg) list_layout = QHBoxLayout() main_layout.addLayout(list_layout) # TODO: all items dragged into chosen_par should appear above the qp_item list_layout.addWidget(not_chosen_par) list_layout.addWidget(chosen_par) not_chosen_par.show() chosen_par.show() ok_button = QPushButton('OK') main_layout.addWidget(ok_button) ok_button.clicked.connect(dialog.close) dialog.exec() for i in range(len(not_chosen_par)): diff_dict[sim_class].pop( not_chosen_par.item(i).text(), None) additional_param_found.append(sim_class) except (AttributeError): # maybe do something useful here # This is for conformance with rd data written out by older versions of rdplot pass for sim_data_item in sim_data_items: has_additional_params = False if sim_data_item.__class__ in additional_param_found: sim_data_item.additional_params = [ chosen_par.item(i).text() for i in range(len(chosen_par)) ] has_additional_params = True # Get *item* of the tree corresponding to *sim_data_item* item = self.create_path(*sim_data_item.tree_identifier_list) # This prevents an sim data item overwriting another one # with same *tree_identifier_list* but different absolute path for value in item.values: condition = (value.tree_identifier_list == sim_data_item.tree_identifier_list and value.path != sim_data_item.path and not has_additional_params) if condition: raise AmbiguousSimDataItems( ("Ambigious sim data items: Sim Data Item {} and {}" " have different absolute paths but the same" " position at the tree {}").format( sim_data_item, value, AbstractEncLog.tree_identifier_list)) # Add *sim_data_item* to the set of values of the tree item *item* item.values.add(sim_data_item) self.items_changed.emit()
def ask_about_cc_mismatch(gui, db, newdb, missing_cols, incompatible_cols): # {{{ source_metadata = db.field_metadata.custom_field_metadata( include_composites=True) dest_library_path = newdb.library_path ndbname = os.path.basename(dest_library_path) d = QDialog(gui) d.setWindowTitle(_('Different custom columns')) l = QFormLayout() tl = QVBoxLayout() d.setLayout(tl) d.s = QScrollArea(d) tl.addWidget(d.s) d.w = QWidget(d) d.s.setWidget(d.w) d.s.setWidgetResizable(True) d.w.setLayout(l) d.setMinimumWidth(600) d.setMinimumHeight(500) d.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) msg = _( 'The custom columns in the <i>{0}</i> library are different from the ' 'custom columns in the <i>{1}</i> library. As a result, some metadata might not be copied.' ).format(os.path.basename(db.library_path), ndbname) d.la = la = QLabel(msg) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-bottom: 1.5ex }') l.addRow(la) if incompatible_cols: la = d.la2 = QLabel( _('The following columns are incompatible - they have the same name' ' but different data types. They will be ignored: ') + ', '.join(sorted(incompatible_cols, key=sort_key))) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-bottom: 1.5ex }') l.addRow(la) missing_widgets = [] if missing_cols: la = d.la3 = QLabel( _('The following columns are missing in the <i>{0}</i> library.' ' You can choose to add them automatically below.').format( ndbname)) la.setWordWrap(True) l.addRow(la) for k in missing_cols: widgets = (k, QCheckBox(_('Add to the %s library') % ndbname)) l.addRow(QLabel(k), widgets[1]) missing_widgets.append(widgets) d.la4 = la = QLabel( _('This warning is only shown once per library, per session')) la.setWordWrap(True) tl.addWidget(la) tl.addWidget(d.bb) d.bb.accepted.connect(d.accept) d.bb.rejected.connect(d.reject) d.resize(d.sizeHint()) if d.exec_() == d.Accepted: changes_made = False for k, cb in missing_widgets: if cb.isChecked(): col_meta = source_metadata[k] newdb.create_custom_column(col_meta['label'], col_meta['name'], col_meta['datatype'], len(col_meta['is_multiple']) > 0, col_meta['is_editable'], col_meta['display']) changes_made = True if changes_made: # Unload the db so that the changes are available # when it is next accessed from calibre.gui2.ui import get_gui library_broker = get_gui().library_broker library_broker.unload_library(dest_library_path) return True return False
def exec_(self): dialog = QDialog(self.parent) textEdit = QTextEdit(dialog) buttonBox = QDialogButtonBox(dialog) layout = QVBoxLayout(dialog) labels = [] html = '' width = 400 height = 25 def triggeredCredit(): if textEdit.isVisible(): for i in range(2 if self.logo else 1, len(labels)): labels[i].show() textEdit.hide() else: for i in range(2 if self.logo else 1, len(labels)): labels[i].hide() textEdit.show() def triggeredClose(arg): dialog.close() dialog.setWindowTitle('About {}'.format(self.programName)) for key in self.__labelsKeys: value = self.__labels.get(key) if value: label = QLabel(dialog) label.setAlignment(Qt.AlignCenter) if key == 'website' or key == 'license': label.setText('<a href="{}">{}</a>'.format( value['url'], value['label'] if value['label'] else value['url'])) label.setTextFormat(Qt.RichText) label.setTextInteractionFlags(Qt.TextBrowserInteraction) label.setOpenExternalLinks(True) elif key == 'logo': image = QPixmap(self.logo) label.setPixmap(image.scaled(128, 128)) else: label.setText(value) labels.append(label) layout.addWidget(labels[len(labels) - 1]) for key in self.__creditsKeys: value = self.__credits.get(key) if len(value.get('contributors')) > 0: html += '<p><strong>{}</strong><br />{}</p>'.format( value.get('label'), '<br />'.join(value.get('contributors'))) if html: textEdit.setHtml('<center>{}</center>'.format(html)) layout.addWidget(textEdit) buttonBox.addButton( 'Credits', QDialogButtonBox.YesRole).clicked.connect(triggeredCredit) textEdit.close() textEdit.setReadOnly(True) buttonBox.addButton( 'Close', QDialogButtonBox.NoRole).clicked.connect(triggeredClose) layout.addWidget(buttonBox) dialog.setLayout(layout) height *= len(dialog.children()) if self.logo: height += 128 dialog.setFixedSize(width, height) return dialog.exec_()
def on_action_triggered(self): a = Ui_Dialog() d = QDialog() a.setupUi(d) d.exec()