def save(self): if self.model_data_changed: focused_widget = QApplication.focusWidget() if isinstance(focused_widget, QLineEdit) and focused_widget.parent() != self: focused_widget.clearFocus() focused_widget = QApplication.focusWidget() validation_results = self._validate() if validation_results != True: showErrorBox(_("The data are not correct"), "<br>-" + "<br>-".join(validation_results)) return False mainlog.debug("save : supplier_id : {}".format( self.current_supplier.supplier_id)) obj = blank_dto(SupplyOrder) obj.supply_order_id = self.current_supply_order_id obj.creation_date = date.today() obj.description = self.edit_comment_widget.toPlainText() obj.supplier_id = self.current_supplier.supplier_id obj.expected_delivery_date = self.delivery_date_widget.value() obj.supplier_reference = self.supplier_reference_widget.text() obj.accounting_label = self.accounting_label def factory(): return blank_dto(SupplyOrderPart) parts_actions = self.model.model_to_objects(factory) try: mainlog.debug("Saving") self.current_supply_order_id = supply_order_service.save( obj, parts_actions) # Reload the data self.reload() mainlog.debug("Emitting change signal") self.supply_order_saved.emit() # self.current_supply_order_id) except Exception as ex: showErrorBox( _("Error while saving"), _("There was an unexpected error while saving your data"), ex, object_name="saveError") if focused_widget: focused_widget.setFocus(Qt.OtherFocusReason)
def combinePages(self): widget = QApplication.focusWidget() say("Looking for overlapping pages…") with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.CombinePages.Form(self.state, self.window) form.exec_() Lib.restoreFocus(widget)
def about(self): widget = QApplication.focusWidget() year = datetime.date.today().year year = "2015-{}".format(str(year)[-2:]) if year != 2015 else "2015" w = self.window.frameGeometry().width() h = self.window.frameGeometry().height() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): app = QApplication.applicationName() version = QApplication.applicationVersion() bits = 64 if IS64BIT else 32 QMessageBox.about( self.window, "About — {}".format(QApplication.applicationName()), f""" <p><b><font color=navy>{app} {version}</font></b></p> <p><font color=navy>{app} is an easy to learn and use application for creating, editing, and outputting indexes (e.g., for books).</font> </p> <p>Copyright © Qtrac Ltd {year}. All Rights Reserved.</p> <p>License: GPLv3.</p> <hr> <p>Window size: {w:,}x{h:,}</p> <p> Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}/{ bits}-bit<br> PySide {PySide.__version__}<br> Qt {qVersion()}<br> APSW {apsw.apswversion()}<br> SQLite {apsw.sqlitelibversion()}<br> {platform.platform()}</p>""") Lib.restoreFocus(widget)
def backup(self): model = self.state.model if not model: return widget = QApplication.focusWidget() filename = Lib.incrementedFilename(model.filename) with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): filename, _ = QFileDialog.getSaveFileName( self.window, "Backup Index — {}".format(QApplication.applicationName()), filename, "{} index (*{})".format(QApplication.applicationName(), EXTENSION)) if filename: with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): self.state.saving = True try: self.state.maybeSave() if not filename.endswith(EXTENSION): filename += EXTENSION say("Backing up to “{}”...".format( QDir.toNativeSeparators(filename))) model.optimize() model.backup(filename, "Backing up", self.window.reportProgress) say("Backed up to “{}”".format( QDir.toNativeSeparators(filename))) finally: self.state.saving = False Lib.restoreFocus(widget)
def outputIndexAs(self): widget = QApplication.focusWidget() extensions = [] for extension, desc in EXPORT_EXTENSIONS.items(): extensions.append("{} (*{})".format(desc, extension)) with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = QFileDialog( self.window, "Output As — {}".format(QApplication.applicationName())) form.setNameFilters(extensions) form.setAcceptMode(QFileDialog.AcceptSave) form.setDirectory(self.state.outputPath) form.selectFile(str(pathlib.Path(self.state.model.filename).stem)) if form.exec_(): filename = form.selectedFiles()[0] extension = form.selectedNameFilter() if filename: # Must have some extension if not re.match(r"^.*[.].+$", filename): if extension: filename += EXTENSION_EXTRACT_RX.sub( r"\1", extension) else: filename += ".rtf" self._outputIndex(filename, widget) Lib.restoreFocus(widget)
def deleteXRef(self): widget = QApplication.focusWidget() self.state.maybeSave() item = self.state.entryPanel.xrefList.currentItem() if item is not None: xref = Xix.Util.xref_for_data(item.data(Qt.UserRole)) from_term = self.state.model.term(xref.from_eid) kind = "see" if xref.kind is XrefKind.SEE else "see also" if xref.kind in {XrefKind.SEE, XrefKind.SEE_ALSO}: term = self.state.model.term(xref.to_eid) elif xref.kind in { XrefKind.SEE_GENERIC, XrefKind.SEE_ALSO_GENERIC }: term = xref.term kind += " (generic)" with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): reply = QMessageBox.question( self.window, "Delete Cross-reference — {}".format( QApplication.applicationName()), "<p>Delete cross-reference from<br>“{}” to {} “{}”?". format(from_term, kind, term), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: if xref.kind in {XrefKind.SEE, XrefKind.SEE_ALSO}: self.state.model.deleteXRef(xref.from_eid, xref.to_eid, xref.kind) elif xref.kind in { XrefKind.SEE_GENERIC, XrefKind.SEE_ALSO_GENERIC }: self.state.model.deleteGenericXRef(xref.from_eid, xref.term, xref.kind) Lib.restoreFocus(widget)
def addXRef(self): widget = QApplication.focusWidget() self.state.maybeSave() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.AddXRef.Form(self.state, self.state.window) form.exec_() Lib.restoreFocus(widget)
def printIndex(self): widget = QApplication.focusWidget() if self.state.printer is None: self.state.printer = QPrinter(QPrinter.HighResolution) self.state.printer.setColorMode(QPrinter.GrayScale) settings = QSettings() size = PaperSizeKind( int(settings.value(Gopt.Key.PaperSize, Gopt.Default.PaperSize))) self.state.printer.setPaperSize( QPrinter.Letter if size is PaperSizeKind.LETTER else QPrinter. A4) with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = QPrintDialog(self.state.printer, self.state.window) form.setWindowTitle("Print Index") if form.exec_(): try: with Lib.DisableUI(*self.window.widgets()): config = self.state.model.configs().copy() config.Filename = "print.$$$" config.Printer = self.state.printer Output.outputEntries(self.state.model, config, "Printing", self.window.reportProgress) say("Printed") except Output.Error as err: say("Failed to print: {}".format(err)) logging.error("printIndex failed: {}".format(err)) Lib.restoreFocus(widget)
def copy(self): widget = QApplication.focusWidget() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.CopyEntry.Form(self.state, self.state.window) if form.exec_(): widget = None self.state.entryPanel.termEdit.setFocus() self.state.entryPanel.termEdit.selectAll() Lib.restoreFocus(widget)
def editGroups(self): widget = QApplication.focusWidget() eid = self.state.viewAllPanel.view.selectedEid term = (Lib.htmlToPlainText(self.state.model.term(eid)) if eid is not None else "NEW") with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.Groups.Form(term, self.state, self.window) form.exec_() self.state.viewFilteredPanel.requery() Lib.restoreFocus(widget)
def redo(self): widget = QApplication.focusWidget() if self.model.isRedoMacro: say("Redoing…") eid = self.viewAllPanel.view.selectedEid with Lib.DisableUI(*self.window.widgets()): self.model.redo() say("Redone", SAY_TIMEOUT) else: eid = self.model.redo() self._postUndoOrRedoRefresh(eid, widget)
def eventFilter(self, obj, event): focusWidget = QApplication.focusWidget() if not focusWidget: try: Tool_global.currentGlWidget.removeEventFilter( Tool_global.currentEventFilter ) except: pass return None widgetChildren = focusWidget.children() if not widgetChildren: try: Tool_global.currentGlWidget.removeEventFilter( Tool_global.currentEventFilter ) except: pass return None glWidget = None for widgetObj in widgetChildren: widgetChildren2 = widgetObj.children() if not len( widgetChildren2 ): continue for widgetObj2 in widgetChildren2: if widgetObj2.metaObject().className() != "QmayaGLWidget": continue glWidget = widgetObj2 break if glWidget: break if not glWidget: if Tool_global.currentGlWidget: try:Tool_global.currentGlWidget.removeEventFilter( Tool_global.currentEventFilter ) except:pass Tool_global.currentGlWidget = None else: if Tool_global.currentGlWidget != glWidget: if Tool_global.currentGlWidget: try:Tool_global.currentGlWidget.removeEventFilter( Tool_global.currentEventFilter ) except:pass Tool_global.currentGlWidget = glWidget Tool_global.currentGlWidget.installEventFilter( Tool_global.currentEventFilter ) return False
def delete(self): widget = QApplication.focusWidget() if self.state.mode in {ModeKind.NO_INDEX, ModeKind.CHANGE}: return # Can't delete if there's no index or big changes if self.state.mode in {ModeKind.ADD, ModeKind.EDIT}: self.save() # Save outstanding changes & set to view mode first if self.state.entryPanel.entry is None: return # Should never happen eid = self.state.entryPanel.entry.eid if eid is None: return # Should never happen eids = list(self.state.model.deletableEntries(eid)) if not eids: return # Should never happen message = "Delete entry “{}”".format(self.state.model.term(eid)) if len(eids) == 2: message += ", and its subentry" elif len(eids) > 2: count = Lib.spellNumber(len(eids) - 1, limit=20) message += ", and its {} subentries".format(count) message += (", and any related cross-references, and also " "remove from any groups") with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): reply = QMessageBox.question( self.window, "Delete Entry — {}".format(QApplication.applicationName()), "<p>{}?".format(message), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.state.model.deleteEntry(eid, message[0].lower() + message[1:]) with Lib.BlockSignals(self.state.entryPanel): self.state.entryPanel.clearForm() self.state.window.refreshBookmarks() self.state.viewFilteredPanel.setMatch() selectedEid = self.state.viewAllPanel.view.selectedEid if len(self.state.model): if selectedEid == eid: self.state.viewAllPanel.view.goUp() elif selectedEid is None: self.state.viewAllPanel.view.goEnd() else: self.state.viewEntry(selectedEid) Lib.restoreFocus(widget)
def delete(self): widget = QApplication.focusWidget() item = self.listWidget.currentItem() if item: eid = item.data(Qt.UserRole) if self.state.model.hasDeletedEntry(eid): with Lib.Qt.DisableUI(self, forModalDialog=True): reply = QMessageBox.question( self, "Delete Revivable Entry — {}".format( QApplication.applicationName()), "<p>Permanently delete revivable entry<br>“{}”?". format(item.text()), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: with Lib.DisableUI(self): self.state.model.deleteDeletedEntry(eid) self.populate() self.updateUi() Lib.restoreFocus(widget)
def _calculateSortAs(self, term, candidates): widget = QApplication.focusWidget() if len(candidates) == 1: sortas = candidates[0].candidate saf = candidates[0].saf else: result = Forms.SortAs.Result() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.SortAs.Form(self, term, candidates, result, self.window) form.exec_() sortas = result.sortas saf = result.saf if saf == Saf.CUSTOM: with Lib.BlockSignals(self.entryPanel.calcSortAsCheckBox): self.entryPanel.calcSortAsCheckBox.setChecked(False) self.entryPanel.sortAsEdit.setPlainText(sortas) self.entryPanel.saf = saf self.maybeSave() Lib.restoreFocus(widget)
def editSubentryIgnoreFirsts(self): desc = """<p> Manage the current index's list of function words and phrases that should be ignored when sorting if they appear at the beginning of a subentry (providing the <b>Index→Options</b>, <b>Rules</b>, <b>Ignore Subentries Function Words</b> checkbox is checked).</p> <p> All words and phrases in this list are case-folded (lower-cased) and have any accents stripped.</p> """ info = Forms.List.Info( "Ignored Subentry Function Words", desc, "xix_ref_dlg_subignore.html", self.state.model._xix.db, Sql.SORTED_IGNORED_FIRSTS_WORDS, Sql.INSERT_IGNORED_FIRSTS_WORD, Sql.UPDATE_IGNORED_FIRSTS_WORD, Sql.DELETE_IGNORED_FIRSTS_WORD) widget = QApplication.focusWidget() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.List.Form(self.state, info, self.window) form.exec_() self.state.model.ignoredFirstsWords.cache_clear() Lib.restoreFocus(widget)
def info(self): widget = QApplication.focusWidget() with Lib.Qt.DisableUI(*self.window.widgets(), forModalDialog=True): form = Forms.Info.Form(self.state, self.window) form.exec_() Lib.restoreFocus(widget)
def circle(self): self.state.maybeSave() widget = QApplication.focusWidget() self.state.viewAllPanel.view.circle() if widget is not None: widget.setFocus()
def outputDocx(self): widget = QApplication.focusWidget() self._outputIndex( Lib.replace_extension(self.state.model.filename, ".docx"), widget)
def testNoFocusWindow(self): widget = QApplication.focusWidget() self.assertTrue(widget == None)