class ChannelPropertiesDialog(QDialog): def __init__(self, parent, info, title="Channel Properties"): super().__init__(parent) self.setWindowTitle(title) self.model = QStandardItemModel(info["nchan"], 4) self.model.setHorizontalHeaderLabels(["#", "Label", "Type", "Bad"]) for index, ch in enumerate(info["chs"]): item = QStandardItem() item.setData(index, Qt.DisplayRole) item.setFlags(item.flags() & ~Qt.ItemIsEditable) self.model.setItem(index, 0, item) self.model.setItem(index, 1, QStandardItem(ch["ch_name"])) kind = channel_type(info, index).upper() self.model.setItem(index, 2, QStandardItem(str(kind))) bad = QStandardItem() bad.setData(ch["ch_name"] in info["bads"], Qt.UserRole) bad.setCheckable(True) bad.setEditable(False) checked = ch["ch_name"] in info["bads"] bad.setCheckState(Qt.Checked if checked else Qt.Unchecked) self.model.setItem(index, 3, bad) self.model.itemChanged.connect(bad_changed) self.proxymodel = MySortFilterProxyModel() self.proxymodel.setDynamicSortFilter(False) self.proxymodel.setSourceModel(self.model) self.view = QTableView() self.view.setModel(self.proxymodel) self.view.setItemDelegateForColumn(2, ComboBoxDelegate(self.view)) self.view.setEditTriggers(QAbstractItemView.AllEditTriggers) self.view.verticalHeader().setVisible(False) self.view.horizontalHeader().setStretchLastSection(True) self.view.setShowGrid(False) self.view.setSelectionMode(QAbstractItemView.NoSelection) self.view.setSortingEnabled(True) self.view.sortByColumn(0, Qt.AscendingOrder) vbox = QVBoxLayout(self) vbox.addWidget(self.view) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) vbox.addWidget(self.buttonbox) self.buttonbox.accepted.connect(self.accept) self.buttonbox.rejected.connect(self.reject) self.resize(475, 650) self.view.setColumnWidth(0, 70) self.view.setColumnWidth(1, 155) self.view.setColumnWidth(2, 90)
class ConfigFlagsWindow(QDialog): def __init__(self, parent): super().__init__() self.parent = parent # set title self.setWindowTitle(config.thisTranslation["menu_config_flags"]) self.setMinimumSize(830, 500) # set variables self.setupVariables() # setup interface self.setupUI() def setupVariables(self): self.isUpdating = False def setupUI(self): mainLayout = QVBoxLayout() title = QLabel(config.thisTranslation["menu_config_flags"]) title.mouseReleaseEvent = self.openWiki mainLayout.addWidget(title) filterLayout = QHBoxLayout() filterLayout.addWidget(QLabel(config.thisTranslation["menu5_search"])) self.filterEntry = QLineEdit() self.filterEntry.textChanged.connect(self.resetItems) filterLayout.addWidget(self.filterEntry) mainLayout.addLayout(filterLayout) self.dataView = QTableView() self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.dataView.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.dataView) self.dataView.setModel(self.dataViewModel) self.resetItems() self.dataViewModel.itemChanged.connect(self.itemChanged) mainLayout.addWidget(self.dataView) buttonLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["close"]) button.clicked.connect(self.close) buttonLayout.addWidget(button) button = QPushButton(config.thisTranslation["restoreAllDefaults"]) button.clicked.connect(self.restoreAllDefaults) buttonLayout.addWidget(button) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) def getOptions(self): options = [ ("showControlPanelOnStartup", config.showControlPanelOnStartup, self.showControlPanelOnStartupChanged, False, config.thisTranslation["showControlPanelOnStartup"]), ("preferControlPanelForCommandLineEntry", config.preferControlPanelForCommandLineEntry, self.preferControlPanelForCommandLineEntryChanged, False, config.thisTranslation["preferControlPanelForCommandLineEntry"]), ("closeControlPanelAfterRunningCommand", config.closeControlPanelAfterRunningCommand, self.closeControlPanelAfterRunningCommandChanged, True, config.thisTranslation["closeControlPanelAfterRunningCommand"]), ("restrictControlPanelWidth", config.restrictControlPanelWidth, self.restrictControlPanelWidthChanged, False, config.thisTranslation["restrictControlPanelWidth"]), ("clearCommandEntry", config.clearCommandEntry, self.clearCommandEntryChanged, False, config.thisTranslation["clearCommandEntry"]), ("openBibleWindowContentOnNextTab", config.openBibleWindowContentOnNextTab, self.openBibleWindowContentOnNextTabChanged, False, config.thisTranslation["openBibleWindowContentOnNextTab"]), ("openStudyWindowContentOnNextTab", config.openStudyWindowContentOnNextTab, self.openStudyWindowContentOnNextTabChanged, True, config.thisTranslation["openStudyWindowContentOnNextTab"]), ("populateTabsOnStartup", config.populateTabsOnStartup, self.populateTabsOnStartupChanged, False, config.thisTranslation["populateTabsOnStartup"]), ("qtMaterial", config.qtMaterial, self.qtMaterialChanged, False, config.thisTranslation["qtMaterial"]), ("addBreakAfterTheFirstToolBar", config.addBreakAfterTheFirstToolBar, self.addBreakAfterTheFirstToolBarChanged, True, config.thisTranslation["addBreakAfterTheFirstToolBar"]), ("addBreakBeforeTheLastToolBar", config.addBreakBeforeTheLastToolBar, self.addBreakBeforeTheLastToolBarChanged, False, config.thisTranslation["addBreakBeforeTheLastToolBar"]), ("parserStandarisation", (config.parserStandarisation == "YES"), self.parserStandarisationChanged, False, config.thisTranslation["parserStandarisation"]), ("useLiteVerseParsing", config.useLiteVerseParsing, self.useLiteVerseParsingChanged, False, config.thisTranslation["useLiteVerseParsing"]), ("parseEnglishBooksOnly", config.parseEnglishBooksOnly, self.parseEnglishBooksOnlyChanged, False, config.thisTranslation["parseEnglishBooksOnly"]), ("parseWordDocument", config.parseWordDocument, self.parseWordDocumentChanged, True, config.thisTranslation["parseWordDocument"]), ("convertChapterVerseDotSeparator", config.convertChapterVerseDotSeparator, self.convertChapterVerseDotSeparatorChanged, True, config.thisTranslation["convertChapterVerseDotSeparator"]), ("parseBookChapterWithoutSpace", config.parseBookChapterWithoutSpace, self.parseBookChapterWithoutSpaceChanged, True, config.thisTranslation["parseBookChapterWithoutSpace"]), ("parseBooklessReferences", config.parseBooklessReferences, self.parseBooklessReferencesChanged, True, config.thisTranslation["parseBooklessReferences"]), ("searchBibleIfCommandNotFound", config.searchBibleIfCommandNotFound, self.searchBibleIfCommandNotFoundChanged, True, config.thisTranslation["searchBibleIfCommandNotFound"]), ("regexSearchBibleIfCommandNotFound", config.regexSearchBibleIfCommandNotFound, self.regexSearchBibleIfCommandNotFoundChanged, False, config.thisTranslation["regexSearchBibleIfCommandNotFound"]), ("preferHtmlMenu", config.preferHtmlMenu, self.preferHtmlMenuChanged, False, config.thisTranslation["preferHtmlMenu"]), ("showVerseNumbersInRange", config.showVerseNumbersInRange, self.showVerseNumbersInRangeChanged, True, config.thisTranslation["showVerseNumbersInRange"]), ("addFavouriteToMultiRef", config.addFavouriteToMultiRef, self.addFavouriteToMultiRefChanged, False, config.thisTranslation["addFavouriteToMultiRef"]), ("enableVerseHighlighting", config.enableVerseHighlighting, self.enableVerseHighlightingChanged, True, config.thisTranslation["enableVerseHighlighting"]), ("regexCaseSensitive", config.regexCaseSensitive, self.regexCaseSensitiveChanged, False, config.thisTranslation["regexCaseSensitive"]), ("alwaysDisplayStaticMaps", config.alwaysDisplayStaticMaps, self.alwaysDisplayStaticMapsChanged, False, config.thisTranslation["alwaysDisplayStaticMaps"]), ("exportEmbeddedImages", config.exportEmbeddedImages, self.exportEmbeddedImagesChanged, True, config.thisTranslation["exportEmbeddedImages"]), ("clickToOpenImage", config.clickToOpenImage, self.clickToOpenImageChanged, True, config.thisTranslation["clickToOpenImage"]), ("showNoteIndicatorOnBibleChapter", config.showNoteIndicatorOnBibleChapter, self.parent.enableNoteIndicatorButtonClicked, True, config.thisTranslation["showNoteIndicatorOnBibleChapter"]), ("openBibleNoteAfterSave", config.openBibleNoteAfterSave, self.openBibleNoteAfterSaveChanged, False, config.thisTranslation["openBibleNoteAfterSave"]), ("openBibleNoteAfterEditorClosed", config.openBibleNoteAfterEditorClosed, self.openBibleNoteAfterEditorClosedChanged, False, config.thisTranslation["openBibleNoteAfterEditorClosed"]), ("hideNoteEditorStyleToolbar", config.hideNoteEditorStyleToolbar, self.hideNoteEditorStyleToolbarChanged, False, config.thisTranslation["hideNoteEditorStyleToolbar"]), ("hideNoteEditorTextUtility", config.hideNoteEditorTextUtility, self.hideNoteEditorTextUtilityChanged, True, config.thisTranslation["hideNoteEditorTextUtility"]), ("overwriteNoteFont", config.overwriteNoteFont, self.overwriteNoteFontChanged, True, config.thisTranslation["overwriteNoteFont"]), ("overwriteNoteFontSize", config.overwriteNoteFontSize, self.overwriteNoteFontSizeChanged, True, config.thisTranslation["overwriteNoteFontSize"]), ("overwriteBookFont", config.overwriteBookFont, self.overwriteBookFontChanged, True, config.thisTranslation["overwriteBookFont"]), ("overwriteBookFontSize", config.overwriteBookFontSize, self.overwriteBookFontSizeChanged, True, config.thisTranslation["overwriteBookFontSize"]), ("openBookInNewWindow", config.openBookInNewWindow, self.openBookInNewWindowChanged, False, config.thisTranslation["openBookInNewWindow"]), ("openPdfViewerInNewWindow", config.openPdfViewerInNewWindow, self.openPdfViewerInNewWindowChanged, False, config.thisTranslation["openPdfViewerInNewWindow"]), ("virtualKeyboard", config.virtualKeyboard, self.virtualKeyboardChanged, False, config.thisTranslation["virtualKeyboard"]), ("useWebbrowser", config.useWebbrowser, self.useWebbrowserChanged, True, config.thisTranslation["useWebbrowser"]), ("removeHighlightOnExit", config.removeHighlightOnExit, self.removeHighlightOnExitChanged, False, config.thisTranslation["removeHighlightOnExit"]), ("disableModulesUpdateCheck", config.disableModulesUpdateCheck, self.disableModulesUpdateCheckChanged, True, config.thisTranslation["disableModulesUpdateCheck"]), ("updateWithGitPull", config.updateWithGitPull, self.updateWithGitPullChanged, False, config.thisTranslation["updateWithGitPull"]), ("enableGist", config.enableGist, self.enableGistChanged, False, config.thisTranslation["enableGist"]), ("enableMacros", config.enableMacros, self.enableMacrosChanged, False, config.thisTranslation["enableMacros"]), ("enablePlugins", config.enablePlugins, self.enablePluginsChanged, True, config.thisTranslation["enablePlugins"]), ("hideBlankVerseCompare", config.hideBlankVerseCompare, self.hideBlankVerseCompareChanged, False, config.thisTranslation["hideBlankVerseCompare"]), ("enforceCompareParallel", config.enforceCompareParallel, self.parent.enforceCompareParallelButtonClicked, False, config.thisTranslation["enforceCompareParallel"]), ("enableMenuUnderline", config.enableMenuUnderline, self.enableMenuUnderlineChanged, True, config.thisTranslation["enableMenuUnderline"]), ("openBibleInMainViewOnly", config.openBibleInMainViewOnly, self.parent.enableStudyBibleButtonClicked, False, config.thisTranslation["openBibleInMainViewOnly"]), ("addOHGBiToMorphologySearch", config.addOHGBiToMorphologySearch, self.addOHGBiToMorphologySearchChanged, True, config.thisTranslation["addOHGBiToMorphologySearch"]), ("includeStrictDocTypeInNote", config.includeStrictDocTypeInNote, self.includeStrictDocTypeInNoteChanged, False, config.thisTranslation["includeStrictDocTypeInNote"]), ("parseTextConvertNotesToBook", config.parseTextConvertNotesToBook, self.parseTextConvertNotesToBookChanged, False, config.thisTranslation["parseTextConvertNotesToBook"]), ("parseTextConvertHTMLToBook", config.parseTextConvertHTMLToBook, self.parseTextConvertHTMLToBookChanged, False, config.thisTranslation["parseTextConvertHTMLToBook"]), ("displayCmdOutput", config.displayCmdOutput, self.displayCmdOutputChanged, False, config.thisTranslation["displayCmdOutput"]), ("disableLoadLastOpenFilesOnStartup", config.disableLoadLastOpenFilesOnStartup, self.disableLoadLastOpenFilesOnStartupChanged, False, config.thisTranslation["disableLoadLastOpenFilesOnStartup"]), ("disableOpenPopupWindowOnStartup", config.disableOpenPopupWindowOnStartup, self.disableOpenPopupWindowOnStartupChanged, True, config.thisTranslation["disableOpenPopupWindowOnStartup"]), ("showMiniKeyboardInMiniControl", config.showMiniKeyboardInMiniControl, self.showMiniKeyboardInMiniControlChanged, False, config.thisTranslation["showMiniKeyboardInMiniControl"]), ] if config.isTtsInstalled: options += [ ("useLangDetectOnTts", config.useLangDetectOnTts, self.useLangDetectOnTtsChanged, False, config.thisTranslation["useLangDetectOnTts"]), ("ttsEnglishAlwaysUS", config.ttsEnglishAlwaysUS, self.ttsEnglishAlwaysUSChanged, False, config.thisTranslation["ttsEnglishAlwaysUS"]), ("ttsEnglishAlwaysUK", config.ttsEnglishAlwaysUK, self.ttsEnglishAlwaysUKChanged, False, config.thisTranslation["ttsEnglishAlwaysUK"]), ("ttsChineseAlwaysMandarin", config.ttsChineseAlwaysMandarin, self.ttsChineseAlwaysMandarinChanged, False, config.thisTranslation["ttsChineseAlwaysMandarin"]), ("ttsChineseAlwaysCantonese", config.ttsChineseAlwaysCantonese, self.ttsChineseAlwaysCantoneseChanged, False, config.thisTranslation["ttsChineseAlwaysCantonese"]), ] if platform.system() == "Linux": options += [ ("linuxStartFullScreen", config.linuxStartFullScreen, self.linuxStartFullScreenChanged, False, config.thisTranslation["linuxStartFullScreen"]), ("fcitx", config.fcitx, self.fcitxChanged, False, config.thisTranslation["fcitx"]), ("ibus", config.ibus, self.ibusChanged, False, config.thisTranslation["ibus"]), ("espeak", config.espeak, self.espeakChanged, False, config.thisTranslation["espeak"]), ] if config.developer: options += [ ("forceGenerateHtml", config.forceGenerateHtml, self.forceGenerateHtmlChanged, False, config.thisTranslation["forceGenerateHtml"]), ("enableLogging", config.enableLogging, self.enableLoggingChanged, False, config.thisTranslation["enableLogging"]), ("logCommands", config.logCommands, self.logCommandsChanged, False, config.thisTranslation["logCommands"]), ] data = {} for flag, configValue, action, default, tooltip in options: data[flag] = [configValue, default, tooltip, action] return data def restoreAllDefaults(self): for key, value in self.data.items(): code = "config.{0} = {1}".format(key, value[1]) exec(code) self.resetItems() self.displayMessage(config.thisTranslation["message_restart"]) def itemChanged(self, standardItem): flag = standardItem.text() if flag in self.data and not self.isUpdating: self.data[flag][-1]() def resetItems(self): self.isUpdating = True # Empty the model before reset self.dataViewModel.clear() # Reset self.data = self.getOptions() filterEntry = self.filterEntry.text().lower() rowCount = 0 for flag, value in self.data.items(): configValue, default, tooltip, *_ = value if filterEntry == "" or (filterEntry != "" and (filterEntry in flag.lower() or filterEntry in tooltip.lower())): # 1st column item = QStandardItem(flag) item.setToolTip(tooltip) item.setCheckable(True) item.setCheckState(Qt.CheckState.Checked if configValue else Qt.CheckState.Unchecked) self.dataViewModel.setItem(rowCount, 0, item) # 2nd column item = QStandardItem(str(default)) self.dataViewModel.setItem(rowCount, 1, item) # 3rd column tooltip = tooltip.replace("\n", " ") item = QStandardItem(tooltip) item.setToolTip(tooltip) self.dataViewModel.setItem(rowCount, 2, item) # add row count rowCount += 1 self.dataViewModel.setHorizontalHeaderLabels([ config.thisTranslation["flag"], config.thisTranslation["default"], config.thisTranslation["description"] ]) self.dataView.resizeColumnsToContents() self.isUpdating = False def displayMessage(self, message="", title="UniqueBible"): QMessageBox.information(self, title, message) def openWiki(self, event): wikiLink = "https://github.com/eliranwong/UniqueBible/wiki/Config-file-reference" webbrowser.open(wikiLink) def ibusChanged(self): config.ibus = not config.ibus if config.fcitx and config.ibus: config.fcitx = not config.fcitx if config.virtualKeyboard and config.ibus: config.virtualKeyboard = not config.virtualKeyboard self.displayMessage(config.thisTranslation["message_restart"]) def fcitxChanged(self): config.fcitx = not config.fcitx if config.fcitx and config.ibus: config.ibus = not config.ibus if config.fcitx and config.virtualKeyboard: config.virtualKeyboard = not config.virtualKeyboard self.displayMessage(config.thisTranslation["message_restart"]) def virtualKeyboardChanged(self): config.virtualKeyboard = not config.virtualKeyboard if config.fcitx and config.virtualKeyboard: config.fcitx = not config.fcitx if config.virtualKeyboard and config.ibus: config.ibus = not config.ibus self.displayMessage(config.thisTranslation["message_restart"]) def parseWordDocumentChanged(self): config.parseWordDocument = not config.parseWordDocument def useLangDetectOnTtsChanged(self): config.useLangDetectOnTts = not config.useLangDetectOnTts def ttsEnglishAlwaysUSChanged(self): config.ttsEnglishAlwaysUS = not config.ttsEnglishAlwaysUS if config.ttsEnglishAlwaysUK and config.ttsEnglishAlwaysUS: config.ttsEnglishAlwaysUK = not config.ttsEnglishAlwaysUK def ttsEnglishAlwaysUKChanged(self): config.ttsEnglishAlwaysUK = not config.ttsEnglishAlwaysUK if config.ttsEnglishAlwaysUK and config.ttsEnglishAlwaysUS: config.ttsEnglishAlwaysUS = not config.ttsEnglishAlwaysUS def ttsChineseAlwaysMandarinChanged(self): config.ttsChineseAlwaysMandarin = not config.ttsChineseAlwaysMandarin if config.ttsChineseAlwaysMandarin and config.ttsChineseAlwaysCantonese: config.ttsChineseAlwaysCantonese = not config.ttsChineseAlwaysCantonese def ttsChineseAlwaysCantoneseChanged(self): config.ttsChineseAlwaysCantonese = not config.ttsChineseAlwaysCantonese if config.ttsChineseAlwaysMandarin and config.ttsChineseAlwaysCantonese: config.ttsChineseAlwaysMandarin = not config.ttsChineseAlwaysMandarin def showVerseNumbersInRangeChanged(self): config.showVerseNumbersInRange = not config.showVerseNumbersInRange #def customPythonOnStartupChanged(self): # config.customPythonOnStartup = not config.customPythonOnStartup def openBibleWindowContentOnNextTabChanged(self): config.openBibleWindowContentOnNextTab = not config.openBibleWindowContentOnNextTab self.newTabException = False def showControlPanelOnStartupChanged(self): config.showControlPanelOnStartup = not config.showControlPanelOnStartup self.displayMessage(config.thisTranslation["message_restart"]) def preferControlPanelForCommandLineEntryChanged(self): config.preferControlPanelForCommandLineEntry = not config.preferControlPanelForCommandLineEntry self.displayMessage(config.thisTranslation["message_restart"]) def closeControlPanelAfterRunningCommandChanged(self): config.closeControlPanelAfterRunningCommand = not config.closeControlPanelAfterRunningCommand def restrictControlPanelWidthChanged(self): config.restrictControlPanelWidth = not config.restrictControlPanelWidth self.parent.reloadControlPanel(False) def regexCaseSensitiveChanged(self): config.regexCaseSensitive = not config.regexCaseSensitive def openStudyWindowContentOnNextTabChanged(self): config.openStudyWindowContentOnNextTab = not config.openStudyWindowContentOnNextTab self.newTabException = False def addFavouriteToMultiRefChanged(self): config.addFavouriteToMultiRef = not config.addFavouriteToMultiRef def addOHGBiToMorphologySearchChanged(self): config.addOHGBiToMorphologySearch = not config.addOHGBiToMorphologySearch def exportEmbeddedImagesChanged(self): config.exportEmbeddedImages = not config.exportEmbeddedImages def clickToOpenImageChanged(self): config.clickToOpenImage = not config.clickToOpenImage def openBibleNoteAfterEditorClosedChanged(self): config.openBibleNoteAfterEditorClosed = not config.openBibleNoteAfterEditorClosed def preferHtmlMenuChanged(self): config.preferHtmlMenu = not config.preferHtmlMenu def hideNoteEditorStyleToolbarChanged(self): config.hideNoteEditorStyleToolbar = not config.hideNoteEditorStyleToolbar def hideNoteEditorTextUtilityChanged(self): config.hideNoteEditorTextUtility = not config.hideNoteEditorTextUtility def populateTabsOnStartupChanged(self): config.populateTabsOnStartup = not config.populateTabsOnStartup def openBookInNewWindowChanged(self): config.openBookInNewWindow = not config.openBookInNewWindow def convertChapterVerseDotSeparatorChanged(self): config.convertChapterVerseDotSeparator = not config.convertChapterVerseDotSeparator def updateWithGitPullChanged(self): config.updateWithGitPull = not config.updateWithGitPull if config.updateWithGitPull and not os.path.isdir(".git"): config.updateWithGitPull = False def parseBookChapterWithoutSpaceChanged(self): config.parseBookChapterWithoutSpace = not config.parseBookChapterWithoutSpace def parseBooklessReferencesChanged(self): config.parseBooklessReferences = not config.parseBooklessReferences def openPdfViewerInNewWindowChanged(self): config.openPdfViewerInNewWindow = not config.openPdfViewerInNewWindow def searchBibleIfCommandNotFoundChanged(self): config.searchBibleIfCommandNotFound = not config.searchBibleIfCommandNotFound def regexSearchBibleIfCommandNotFoundChanged(self): config.regexSearchBibleIfCommandNotFound = not config.regexSearchBibleIfCommandNotFound if config.regexSearchBibleIfCommandNotFound and not config.searchBibleIfCommandNotFound: config.searchBibleIfCommandNotFound = True def overwriteNoteFontChanged(self): config.overwriteNoteFont = not config.overwriteNoteFont def overwriteNoteFontSizeChanged(self): config.overwriteNoteFontSize = not config.overwriteNoteFontSize def overwriteBookFontChanged(self): config.overwriteBookFont = not config.overwriteBookFont def useWebbrowserChanged(self): config.useWebbrowser = not config.useWebbrowser def removeHighlightOnExitChanged(self): config.removeHighlightOnExit = not config.removeHighlightOnExit def overwriteBookFontSizeChanged(self): config.overwriteBookFontSize = not config.overwriteBookFontSize def alwaysDisplayStaticMapsChanged(self): config.alwaysDisplayStaticMaps = not config.alwaysDisplayStaticMaps def openBibleNoteAfterSaveChanged(self): config.openBibleNoteAfterSave = not config.openBibleNoteAfterSave def addBreakAfterTheFirstToolBarChanged(self): config.addBreakAfterTheFirstToolBar = not config.addBreakAfterTheFirstToolBar self.displayMessage(config.thisTranslation["message_restart"]) def addBreakBeforeTheLastToolBarChanged(self): config.addBreakBeforeTheLastToolBar = not config.addBreakBeforeTheLastToolBar self.displayMessage(config.thisTranslation["message_restart"]) def disableModulesUpdateCheckChanged(self): config.disableModulesUpdateCheck = not config.disableModulesUpdateCheck def forceGenerateHtmlChanged(self): config.forceGenerateHtml = not config.forceGenerateHtml def parserStandarisationChanged(self): if config.parserStandarisation == "YES": config.parserStandarisation = "NO" else: config.parserStandarisation = "YES" def linuxStartFullScreenChanged(self): config.linuxStartFullScreen = not config.linuxStartFullScreen self.displayMessage(config.thisTranslation["message_restart"]) def espeakChanged(self): config.espeak = not config.espeak self.displayMessage(config.thisTranslation["message_restart"]) def enableLoggingChanged(self): config.enableLogging = not config.enableLogging self.displayMessage(config.thisTranslation["message_restart"]) def logCommandsChanged(self): config.logCommands = not config.logCommands def enableVerseHighlightingChanged(self): config.enableVerseHighlighting = not config.enableVerseHighlighting self.displayMessage(config.thisTranslation["message_restart"]) def useLiteVerseParsingChanged(self): config.useLiteVerseParsing = not config.useLiteVerseParsing def parseEnglishBooksOnlyChanged(self): config.parseEnglishBooksOnly = not config.parseEnglishBooksOnly def enableMacrosChanged(self): config.enableMacros = not config.enableMacros self.displayMessage(config.thisTranslation["message_restart"]) def enablePluginsChanged(self): config.enablePlugins = not config.enablePlugins self.parent.setMenuLayout(config.menuLayout) def clearCommandEntryChanged(self): config.clearCommandEntry = not config.clearCommandEntry def qtMaterialChanged(self): if not config.qtMaterial: self.parent.enableQtMaterial(True) else: self.parent.enableQtMaterial(False) def enableGistChanged(self): if not config.enableGist and config.isPygithubInstalled: config.enableGist = True self.displayMessage(config.thisTranslation["message_restart"]) elif config.enableGist: config.enableGist = not config.enableGist self.displayMessage(config.thisTranslation["message_restart"]) else: self.displayMessage(config.thisTranslation["message_noSupport"]) def hideBlankVerseCompareChanged(self): config.hideBlankVerseCompare = not config.hideBlankVerseCompare def enableMenuUnderlineChanged(self): config.enableMenuUnderline = not config.enableMenuUnderline if config.enableMenuUnderline: config.menuUnderline = "&" else: config.menuUnderline = "" self.parent.setMenuLayout(config.menuLayout) def includeStrictDocTypeInNoteChanged(self): config.includeStrictDocTypeInNote = not config.includeStrictDocTypeInNote def parseTextConvertNotesToBookChanged(self): config.parseTextConvertNotesToBook = not config.parseTextConvertNotesToBook def parseTextConvertHTMLToBookChanged(self): config.parseTextConvertHTMLToBook = not config.parseTextConvertHTMLToBook def displayCmdOutputChanged(self): config.displayCmdOutput = not config.displayCmdOutput def disableLoadLastOpenFilesOnStartupChanged(self): config.disableLoadLastOpenFilesOnStartup = not config.disableLoadLastOpenFilesOnStartup def disableOpenPopupWindowOnStartupChanged(self): config.disableOpenPopupWindowOnStartup = not config.disableOpenPopupWindowOnStartup def showMiniKeyboardInMiniControlChanged(self): config.showMiniKeyboardInMiniControl = not config.showMiniKeyboardInMiniControl
class LibraryCatalogDialog(QDialog): def __init__(self, parent): super().__init__() self.parent = parent self.setWindowTitle(config.thisTranslation["libraryCatalog"]) self.setMinimumSize(700, 500) self.setupVariables() self.setupUI() def setupVariables(self): self.isUpdating = False self.catalogEntryId = None self.localCatalog = CatalogUtil.loadLocalCatalog() self.remoteCatalog = gitHubRepoCacheData self.localCatalogData = self.getLocalCatalogItems() self.remoteCatalogData = self.getRemoteCatalogItems() self.location = "local" self.textButtonStyle = "QPushButton {background-color: #333972; color: white;} QPushButton:hover {background-color: #333972;} QPushButton:pressed { background-color: #515790;}" def setupUI(self): mainLayout = QVBoxLayout() filterLayout = QHBoxLayout() filterLayout.addWidget(QLabel(config.thisTranslation["menu5_search"])) self.filterEntry = QLineEdit() self.filterEntry.setClearButtonEnabled(True) self.filterEntry.textChanged.connect(self.resetItems) filterLayout.addWidget(self.filterEntry) mainLayout.addLayout(filterLayout) self.searchTypeBox = QGroupBox("") locationLayout = QHBoxLayout() self.localRadioButton = QRadioButton("Local") self.localRadioButton.setChecked(True) self.localRadioButton.toggled.connect( lambda: self.setLocation("local")) locationLayout.addWidget(self.localRadioButton) self.remoteRadioButton = QRadioButton("Remote") self.remoteRadioButton.toggled.connect( lambda: self.setLocation("remote")) locationLayout.addWidget(self.remoteRadioButton) self.searchTypeBox.setLayout(locationLayout) mainLayout.addWidget(self.searchTypeBox) typesLayout = QHBoxLayout() button = QPushButton("All") button.setStyleSheet(self.textButtonStyle) button.clicked.connect(lambda: self.selectAllTypes(True)) typesLayout.addWidget(button) button = QPushButton("None") button.setStyleSheet(self.textButtonStyle) button.clicked.connect(lambda: self.selectAllTypes(False)) typesLayout.addWidget(button) self.bookCheckbox = QCheckBox("BOOK") self.bookCheckbox.setChecked(True) self.bookCheckbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.bookCheckbox) self.pdfCheckbox = QCheckBox("PDF") self.pdfCheckbox.setChecked(True) self.pdfCheckbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.pdfCheckbox) self.docxCheckbox = QCheckBox("DOCX") self.docxCheckbox.setChecked(True) self.docxCheckbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.docxCheckbox) self.devotionalCheckbox = QCheckBox("DEVOTIONAL") self.devotionalCheckbox.setChecked(True) self.devotionalCheckbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.devotionalCheckbox) self.commCheckbox = QCheckBox("COMM") self.commCheckbox.setChecked(True) self.commCheckbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.commCheckbox) self.mp3Checkbox = QCheckBox("MP3") self.mp3Checkbox.setChecked(True) self.mp3Checkbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.mp3Checkbox) self.mp4Checkbox = QCheckBox("MP4") self.mp4Checkbox.setChecked(True) self.mp4Checkbox.stateChanged.connect(self.resetItems) typesLayout.addWidget(self.mp4Checkbox) mainLayout.addLayout(typesLayout) self.dataView = QTableView() self.dataView.clicked.connect(self.itemClicked) self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.dataView.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.dataView) self.dataView.setModel(self.dataViewModel) self.resetItems() mainLayout.addWidget(self.dataView) buttonLayout = QHBoxLayout() self.openButton = QPushButton(config.thisTranslation["open"]) self.openButton.setEnabled(True) self.openButton.setStyleSheet(self.textButtonStyle) self.openButton.clicked.connect(self.open) buttonLayout.addWidget(self.openButton) self.downloadButton = QPushButton(config.thisTranslation["download"]) self.downloadButton.setEnabled(False) self.downloadButton.clicked.connect(self.download) buttonLayout.addWidget(self.downloadButton) button = QPushButton(config.thisTranslation["close"]) button.setStyleSheet(self.textButtonStyle) button.clicked.connect(self.close) buttonLayout.addWidget(button) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) def setLocation(self, location): self.location = location self.resetItems() if location == "local": self.openButton.setEnabled(True) self.openButton.setStyleSheet(self.textButtonStyle) self.downloadButton.setEnabled(False) else: self.openButton.setEnabled(False) self.openButton.setStyleSheet("") self.downloadButton.setEnabled(True) def selectAllTypes(self, value): self.pdfCheckbox.setChecked(value) self.mp3Checkbox.setChecked(value) self.mp4Checkbox.setChecked(value) self.bookCheckbox.setChecked(value) self.docxCheckbox.setChecked(value) self.devotionalCheckbox.setChecked(value) self.commCheckbox.setChecked(value) def getLocalCatalogItems(self): return self.getCatalogItems(self.localCatalog) def getRemoteCatalogItems(self): return self.getCatalogItems(self.remoteCatalog) def getCatalogItems(self, catalog): data = {} pdfCount = 0 mp3Count = 0 mp4Count = 0 bookCount = 0 docxCount = 0 commCount = 0 lexCount = 0 devotionalCount = 0 for filename, type, directory, file, description, repo, installDirectory, sha in catalog: id = "UNKNOWN" if type == "PDF": pdfCount += 1 id = "{0}-{1}".format(type, pdfCount) elif type == "MP3": mp3Count += 1 id = "{0}-{1}".format(type, mp3Count) elif type == "MP4": mp4Count += 1 id = "{0}-{1}".format(type, mp4Count) elif type == "BOOK": bookCount += 1 id = "{0}-{1}".format(type, bookCount) elif type == "DOCX": docxCount += 1 id = "{0}-{1}".format(type, docxCount) elif type == "COMM": commCount += 1 id = "{0}-{1}".format(type, commCount) elif type == "LEX": lexCount += 1 id = "{0}-{1}".format(type, lexCount) elif type == "DEVOTIONAL": devotionalCount += 1 id = "{0}-{1}".format(type, devotionalCount) data[id] = [ id, filename, type, directory, file, description, repo, installDirectory, sha ] return data def resetItems(self): self.isUpdating = True self.dataViewModel.clear() filterEntry = self.filterEntry.text().lower() rowCount = 0 colCount = 0 catalogData = self.localCatalogData if self.location == "remote": catalogData = self.remoteCatalogData for id, value in catalogData.items(): id2, filename, type, directory, file, description, repo, installDirectory, sha = value if (filterEntry == "" or filterEntry in filename.lower() or filterEntry in description.lower()): if (not self.pdfCheckbox.isChecked() and type == "PDF") or \ (not self.mp3Checkbox.isChecked() and type == "MP3") or \ (not self.mp4Checkbox.isChecked() and type == "MP4") or \ (not self.bookCheckbox.isChecked() and type == "BOOK") or \ (not self.docxCheckbox.isChecked() and type == "DOCX") or \ (not self.devotionalCheckbox.isChecked() and type == "DEVOTIONAL") or \ (not self.commCheckbox.isChecked() and type == "COMM"): continue enable = True if self.location == "remote": installDirectory = os.path.join(config.marvelData, installDirectory) if FileUtil.regexFileExists( "{0}.*".format(GithubUtil.getShortname(filename)), installDirectory): enable = False item = QStandardItem(id) item.setEnabled(enable) self.dataViewModel.setItem(rowCount, colCount, item) colCount += 1 item = QStandardItem(file) item.setEnabled(enable) self.dataViewModel.setItem(rowCount, colCount, item) colCount += 1 item = QStandardItem(directory) item.setEnabled(enable) self.dataViewModel.setItem(rowCount, colCount, item) colCount += 1 # item = QStandardItem(description) # self.dataViewModel.setItem(rowCount, colCount, item) # colCount += 1 # add row count rowCount += 1 colCount = 0 self.dataViewModel.setHorizontalHeaderLabels([ "#", config.thisTranslation["file"], config.thisTranslation["directory"], # config.thisTranslation["description"] ]) self.dataView.resizeColumnsToContents() self.isUpdating = False def itemClicked(self, index): selectedRow = index.row() self.catalogEntryId = self.dataViewModel.item(selectedRow, 0).text() if self.location == "remote": item = self.remoteCatalogData[self.catalogEntryId] id, filename, type, directory, file, description, repo, installDirectory, sha = item installDirectory = os.path.join(config.marvelData, installDirectory) if FileUtil.regexFileExists( "{0}.*".format(GithubUtil.getShortname(filename)), installDirectory): self.downloadButton.setEnabled(False) self.downloadButton.setStyleSheet("") else: self.downloadButton.setEnabled(True) self.downloadButton.setStyleSheet(self.textButtonStyle) def displayMessage(self, message="", title="UniqueBible"): QMessageBox.information(self, title, message) def saveRemoteCatalogToCache(self): data = CatalogUtil.loadRemoteCatalog() with open("util/GitHubRepoCache.py", "w", encoding="utf-8") as fileObj: fileObj.write("gitHubRepoCacheData = {0}\n".format( pprint.pformat(data))) def fixDirectory(self, directory, type): if type == "PDF": directory = directory.replace(config.marvelData, "") directory = directory.replace("/pdf", "") if len(directory) > 0 and not directory.endswith("/"): directory += "/" if len(directory) > 0 and directory.startswith("/"): directory = directory[1:] return directory def open(self): item = self.localCatalogData[self.catalogEntryId] id, filename, type, directory, file, description, repo, installDirectory, sha = item directory = self.fixDirectory(directory, type) command = "" if type == "PDF": command = "PDF:::{0}{1}".format(directory, file) elif type == "MP3": command = "VLC:::{0}{1}".format(directory, file) elif type == "MP4": command = "VLC:::{0}{1}".format(directory, file) elif type == "BOOK": if file.endswith(".book"): file = file.replace(".book", "") config.booksFolder = directory command = "BOOK:::{0}".format(file) elif type == "COMM": file = file.replace(".commentary", "") file = file[1:] config.commentariesFolder = directory command = "COMMENTARY:::{0}:::{1} {2}".format( file, BibleBooks.eng[str(config.mainB)][0], config.mainC) elif type == "DOCX": command = "DOCX:::{0}".format(file) elif type == "DEVOTIONAL": file = file.replace(".devotional", "") command = "DEVOTIONAL:::{0}".format(file) self.parent.runTextCommand(command) def download(self): self.downloadButton.setEnabled(False) self.downloadButton.setStyleSheet("") item = self.remoteCatalogData[self.catalogEntryId] id, filename, type, directory, file, description, repo, installDirectory, sha = item github = GithubUtil(repo) installDirectory = os.path.join(config.marvelData, installDirectory) file = os.path.join(installDirectory, filename + ".zip") github.downloadFile(file, sha) with zipfile.ZipFile(file, 'r') as zipped: zipped.extractall(installDirectory) os.remove(file) self.displayMessage(filename + " " + config.thisTranslation["message_installed"]) self.localCatalog = CatalogUtil.reloadLocalCatalog() self.localCatalogData = self.getLocalCatalogItems() self.resetItems()
class InterlinearDataWindow(QWidget): translation = ( "Interlinear Data", "Enter a reference:", "No bible verse reference is found!", "Export to Spreadsheet", "Close", ) def __init__(self, parent, initialVerse=""): super().__init__() self.parent = parent # set title self.setWindowTitle(self.translation[0]) self.setMinimumSize(830, 500) # set variables self.setupVariables() # setup interface self.setupUI(initialVerse) def setupVariables(self): import os, sqlite3 # connect bibles.sqlite self.database = os.path.join(config.marvelData, "morphology.sqlite") self.connection = sqlite3.connect(self.database) self.cursor = self.connection.cursor() # Spreadsheet headers self.headers = ("WordID", "ClauseID", "Book", "Chapter", "Verse", "Word", "LexicalEntry", "MorphologyCode", "Morphology", "Lexeme", "Transliteration", "Pronunciation", "Interlinear", "Translation", "Gloss") def __del__(self): self.connection.close() def setupUI(self, initialVerse=""): from qtpy.QtGui import QStandardItemModel from qtpy.QtWidgets import (QPushButton, QLabel, QTableView, QHBoxLayout, QVBoxLayout, QLineEdit) #from qtpy.QtWidgets import QAbstractItemView mainLayout = QVBoxLayout() mainLayout.addWidget(QLabel(self.translation[0])) layout = QHBoxLayout() layout.addWidget(QLabel(self.translation[1])) self.searchEntry = QLineEdit() # Set initial entry self.searchEntry.setText(initialVerse if initialVerse else "John 3:16") self.searchEntry.returnPressed.connect(self.resetItems) layout.addWidget(self.searchEntry) mainLayout.addLayout(layout) self.dataView = QTableView() # Allow editing so that users can select text and copy #self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.dataView.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.dataView) self.dataView.setModel(self.dataViewModel) self.resetItems() mainLayout.addWidget(self.dataView) buttonLayout = QHBoxLayout() button = QPushButton(self.translation[4]) button.clicked.connect(self.close) buttonLayout.addWidget(button) button = QPushButton(self.translation[3]) button.clicked.connect(self.exportSpreadsheet) buttonLayout.addWidget(button) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) def resetItems(self): from util.BibleVerseParser import BibleVerseParser from qtpy.QtGui import QStandardItem # Empty the model before reset self.dataViewModel.clear() # Reset # Parse entered reference reference = self.searchEntry.text().strip() verses = BibleVerseParser( config.parserStandarisation).extractAllReferences( reference, False) if verses: # Search morphology database bcv = verses[0][0:3] query = "SELECT * FROM morphology WHERE Book = ? AND Chapter = ? AND Verse = ?" self.cursor.execute(query, bcv) self.results = self.cursor.fetchall() # Display data # TABLE morphology (WordID INT, ClauseID INT, Book INT, Chapter INT, Verse INT, Word TEXT, LexicalEntry TEXT, MorphologyCode TEXT, Morphology TEXT, Lexeme TEXT, Transliteration TEXT, Pronunciation TEXT, Interlinear TEXT, Translation TEXT, Gloss TEXT) #for wordID, clauseID, b, c, v, textWord, lexicalEntry, morphologyCode, morphology, lexeme, transliteration, pronuciation, interlinear, translation, gloss in self.results: for row, result in enumerate(self.results): for column in range(0, len(result)): text = str( result[column]) if column < 5 else result[column] item = QStandardItem(text) self.dataViewModel.setItem(row, column, item) self.dataViewModel.setHorizontalHeaderLabels([ "WordID", "ClauseID", "Book", "Chapter", "Verse", "Word", "LexicalEntry", "MorphologyCode", "Morphology", "Lexeme", "Transliteration", "Pronunciation", "Interlinear", "Translation", "Gloss" ]) else: self.results = [] self.displayMessage(self.translation[2]) self.dataView.resizeColumnsToContents() def displayMessage(self, message): from qtpy.QtWidgets import QMessageBox QMessageBox.information(self, self.translation[0], message) def exportSpreadsheet(self): import sys from install.module import installmodule module = "openpyxl" # Check if essential module is installed try: from openpyxl import Workbook moduleInstalled = True except: moduleInstalled = False # Install essential module if it is absent if not moduleInstalled: installmodule(module) if not module in sys.modules: try: from openpyxl import Workbook self.runExportSpreadsheet() except: #self.displayMessage("Package '{0}' is required but not installed!\nRun 'pip3 install {0}' to install it first.".format(module)) # openpyxl requires pyton version 3.6+, try alternative 'xlsxwriter' self.exportSpreadsheet2() else: self.runExportSpreadsheet() def runExportSpreadsheet(self): from openpyxl import Workbook from openpyxl.styles import Font # Specify excel file path #filePath = os.path.join(os.getcwd(), "plugins", "menu", "Interlinear_Data.xlsx") filePath = self.getFilePath() if filePath: # Documentation on openpyxl: https://openpyxl.readthedocs.io/en/stable/ wb = Workbook() # grab the active worksheet ws = wb.active ws.title = "UniqueBible.app" # Append rows ws.append(self.headers) font = Font(bold=True) for i in range(0, len(self.headers)): # row and column number starts from 1 when calling ws.cell ws.cell(row=1, column=i + 1).font = font if self.results: for result in self.results: ws.append(result) # Apply style # Documentation: https://openpyxl.readthedocs.io/en/stable/styles.html font = Font( name="Calibri") if self.results[0][2] >= 40 else Font( name="Ezra SIL") for column in ("F", "J"): for row in range(0, len(self.results)): ws["{0}{1}".format(column, row + 2)].font = font font = Font(name="Calibri") for column in ("K", "L"): for row in range(0, len(self.results)): ws["{0}{1}".format(column, row + 2)].font = font # Save and open the file wb.save(filePath) self.openFile(filePath) # Use 'xlsxwriter' to export excel file if 'openpyxl' is not installed. def exportSpreadsheet2(self): import sys from install.module import installmodule module = "xlsxwriter" # Check if essential module is installed try: import xlsxwriter moduleInstalled = True except: moduleInstalled = False # Install essential module if it is absent if not moduleInstalled: installmodule(module) if not module in sys.modules: try: import xlsxwriter self.runExportSpreadsheet2() except: #self.displayMessage("Package '{0}' is required but not installed!\nRun 'pip3 install {0}' to install it first.".format(module)) self.exportSpreadsheet3() else: self.runExportSpreadsheet2() def runExportSpreadsheet2(self): import xlsxwriter # Specify excel file path #filePath = os.path.join(os.getcwd(), "plugins", "menu", "Interlinear_Data.xlsx") filePath = self.getFilePath() if filePath: # Create an new Excel file and add a worksheet. # Documentation on xlsxwriter: https://pypi.org/project/XlsxWriter/ workbook = xlsxwriter.Workbook(filePath) worksheet = workbook.add_worksheet("UniqueBible.app") # Add formats to cells. bold = workbook.add_format({'bold': True}) format_right_to_left = workbook.add_format({'reading_order': 2}) # Text with formatting. for index, header in enumerate(self.headers): worksheet.write(0, index, header, bold) if self.results: for row, result in enumerate(self.results): for column, item in enumerate(result): if column in (5, 9) and self.results[0][2] < 40: worksheet.write(row + 1, column, item, format_right_to_left) else: worksheet.write(row + 1, column, item) workbook.close() # Open the saved file self.openFile(filePath) # export to csv when users cannot install either openpyxl or xlsxwriter for some reasons def exportSpreadsheet3(self): # Define a file path #filePath = os.path.join(os.getcwd(), "plugins", "menu", "Interlinear_Data.csv") filePath = self.getFilePath("csv") if filePath: # Format data fileContent = '"{0}"'.format('","'.join(self.headers)) if self.results: for result in self.results: row = [ str(item) if index < 5 else item for index, item in enumerate(result) ] fileContent += '\n"{0}"'.format('","'.join(row)) # Write data into file with open(filePath, "w") as fileObj: fileObj.write(fileContent) self.openFile(filePath) def getFilePath(self, fileExtension="xlsx"): from qtpy.QtWidgets import QFileDialog defaultName = "Interlinear_Data.{0}".format(fileExtension) options = QFileDialog.Options() filePath, *_ = QFileDialog.getSaveFileName( self, config.thisTranslation["note_saveAs"], defaultName, "Spreadsheet File (*.{0})".format(fileExtension), "", options) if filePath: filePath = filePath.replace(" ", "_") if not filePath.endswith(".{0}".format(fileExtension)): filePath = "{0}.{1}".format(filePath, fileExtension) return filePath else: return "" def openFile(self, filePath): import platform, subprocess, os if platform.system() == "Linux": subprocess.Popen([config.open, filePath]) elif platform.system() == "Windows": try: subprocess("excel.exe {0}".format(filePath), shell=True) except: try: subprocess("start {0}".format(filePath), shell=True) except: pass else: os.system("{0} {1}".format(config.open, filePath))
class DownloadBibleMp3Dialog(QDialog): def __init__(self, parent): super().__init__() self.bibles = { "BBE (British accent)": ("BBE", "otseng/UniqueBible_MP3_BBE_british", "british"), "KJV (American accent)": ("KJV", "otseng/UniqueBible_MP3_KJV", "default"), "KJV (American soft music)": ("KJV", "otseng/UniqueBible_MP3_KJV_soft_music", "soft-music"), "NHEB (Indian accent)": ("NHEB", "otseng/UniqueBible_MP3_NHEB_indian", "indian"), "WEB (American accent)": ("WEB", "otseng/UniqueBible_MP3_WEB", "default"), "CUV (Chinese)": ("CUV", "otseng/UniqueBible_MP3_CUV", "default"), "HHBD (Hindi)": ("HHBD", "otseng/UniqueBible_MP3_HHBD", "default"), "RVA (Spanish)": ("RVA", "otseng/UniqueBible_MP3_RVA", "default"), "TR (Modern Greek)": ("TR", "otseng/UniqueBible_MP3_TR", "modern"), } self.parent = parent self.setWindowTitle(config.thisTranslation["gitHubBibleMp3Files"]) self.setMinimumSize(150, 450) self.selectedRendition = None self.selectedText = None self.selectedRepo = None self.selectedDirectory = None self.settingBibles = False self.thread = None self.setupUI() def setupUI(self): mainLayout = QVBoxLayout() title = QLabel(config.thisTranslation["gitHubBibleMp3Files"]) mainLayout.addWidget(title) self.versionsLayout = QVBoxLayout() self.renditionsList = QListWidget() self.renditionsList.itemClicked.connect(self.selectItem) for rendition in self.bibles.keys(): self.renditionsList.addItem(rendition) self.renditionsList.setMaximumHeight(100) self.versionsLayout.addWidget(self.renditionsList) mainLayout.addLayout(self.versionsLayout) self.downloadTable = QTableView() self.downloadTable.setEnabled(False) self.downloadTable.setFocusPolicy(Qt.StrongFocus) self.downloadTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.downloadTable.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.downloadTable) self.downloadTable.setModel(self.dataViewModel) mainLayout.addWidget(self.downloadTable) buttonsLayout = QHBoxLayout() selectAllButton = QPushButton(config.thisTranslation["selectAll"]) selectAllButton.setFocusPolicy(Qt.StrongFocus) selectAllButton.clicked.connect(self.selectAll) buttonsLayout.addWidget(selectAllButton) selectNoneButton = QPushButton(config.thisTranslation["selectNone"]) selectNoneButton.setFocusPolicy(Qt.StrongFocus) selectNoneButton.clicked.connect(self.selectNone) buttonsLayout.addWidget(selectNoneButton) otButton = QPushButton("1-39") otButton.setFocusPolicy(Qt.StrongFocus) otButton.clicked.connect(self.selectOT) buttonsLayout.addWidget(otButton) ntButton = QPushButton("40-66") ntButton.setFocusPolicy(Qt.StrongFocus) ntButton.clicked.connect(self.selectNT) buttonsLayout.addWidget(ntButton) # buttonsLayout.addStretch() mainLayout.addLayout(buttonsLayout) self.downloadButton = QPushButton(config.thisTranslation["download"]) self.downloadButton.setFocusPolicy(Qt.StrongFocus) self.downloadButton.setAutoDefault(True) self.downloadButton.setFocus() self.downloadButton.clicked.connect(self.download) mainLayout.addWidget(self.downloadButton) self.status = QLabel("") mainLayout.addWidget(self.status) buttonLayout = QHBoxLayout() self.closeButton = QPushButton(config.thisTranslation["close"]) self.closeButton.setFocusPolicy(Qt.StrongFocus) self.closeButton.clicked.connect(self.closeDialog) buttonLayout.addWidget(self.closeButton) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.renditionsList.item(0).setSelected(True) bible = self.renditionsList.item(0).text() self.selectRendition(bible) self.downloadButton.setDefault(True) QTimer.singleShot(0, self.downloadButton.setFocus) def selectItem(self, item): self.selectRendition(item.text()) def selectRendition(self, rendition): from util.GithubUtil import GithubUtil self.selectedRendition = rendition self.downloadTable.setEnabled(True) self.selectedText, self.selectedRepo, self.selectedDirectory = self.bibles[ self.selectedRendition] self.github = GithubUtil(self.selectedRepo) self.repoData = self.github.getRepoData() self.settingBibles = True self.dataViewModel.clear() rowCount = 0 for file in self.repoData.keys(): if len(str(file)) > 3: engFullBookName = file[3:] else: engFullBookName = BibleBooks().eng[str(int(file))][1] item = QStandardItem(file[:3].strip()) folder = os.path.join("audio", "bibles", self.selectedText, self.selectedDirectory, file) folderWithName = os.path.join("audio", "bibles", self.selectedText, self.selectedDirectory, file + " " + engFullBookName) if os.path.exists(folder) or os.path.exists(folderWithName): item.setCheckable(False) item.setCheckState(Qt.Unchecked) item.setEnabled(False) else: item.setCheckable(True) item.setCheckState(Qt.Checked) item.setEnabled(True) self.dataViewModel.setItem(rowCount, 0, item) item = QStandardItem(engFullBookName) self.dataViewModel.setItem(rowCount, 1, item) if os.path.exists(folder) or os.path.exists(folderWithName): item = QStandardItem("Installed") self.dataViewModel.setItem(rowCount, 2, item) else: item = QStandardItem("") self.dataViewModel.setItem(rowCount, 2, item) rowCount += 1 self.dataViewModel.setHorizontalHeaderLabels([ config.thisTranslation["menu_book"], config.thisTranslation["name"], "" ]) self.downloadTable.setColumnWidth(0, 90) self.downloadTable.setColumnWidth(1, 125) self.downloadTable.setColumnWidth(2, 125) # self.downloadTable.resizeColumnsToContents() self.settingBibles = False def selectAll(self): for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) if item.isEnabled(): item.setCheckState(Qt.Checked) def selectNone(self): for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) item.setCheckState(Qt.Unchecked) def selectOT(self): for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) bookNum = int(item.text()) if bookNum <= 39: if item.isEnabled(): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) else: item.setCheckState(Qt.Unchecked) def selectNT(self): for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) bookNum = int(item.text()) if bookNum >= 40: if item.isEnabled(): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) else: item.setCheckState(Qt.Unchecked) def download(self): self.downloadButton.setEnabled(False) self.setStatus(config.thisTranslation["message_installing"]) self.closeButton.setEnabled(False) folder = os.path.join("audio", "bibles") if not os.path.exists(folder): os.mkdir(folder) folder = os.path.join("audio", "bibles", self.selectedText) if not os.path.exists(folder): os.mkdir(folder) folder = os.path.join("audio", "bibles", self.selectedText, self.selectedDirectory) if not os.path.exists(folder): os.mkdir(folder) self.thread = QThread() self.worker = DownloadFromGitHub(self.github, self.repoData, self.dataViewModel, self.selectedText, self.selectedDirectory) self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.worker.deleteLater) self.worker.finished.connect(self.finishedDownloading) self.worker.progress.connect(self.setStatus) self.thread.start() def finishedDownloading(self, count): self.selectRendition(self.selectedRendition) self.setStatus("") self.downloadButton.setEnabled(True) self.closeButton.setEnabled(True) if count > 0: self.parent.displayMessage( config.thisTranslation["message_installed"]) def setStatus(self, message): self.status.setText(message) QApplication.processEvents() def closeDialog(self): if self.thread: if self.thread.isRunning(): self.thread.quit() self.close()
class LiveFilterDialog(QDialog): JS_HIDE = """ count = 0; searchResultCount = document.getElementById("searchResultCount"); divs = document.querySelectorAll("div"); for (var i = 0, len = divs.length; i < len; i++) {{ div = divs[i]; div.hidden = {0}; count++; }}; if (searchResultCount) {{ searchResultCount.innerHTML = count; }} """ JS_SHOW = """ wordSets = [{0}]; count = 0; searchResultCount = document.getElementById("searchResultCount"); divs = document.querySelectorAll("div"); for (var i=0, len=divs.length; i < len; i++) {{ div = divs[i]; var found = true; for (var j=0, len2=wordSets.length; j < len2; j++) {{ wordSet = wordSets[j]; var regex; if (wordSet.startsWith("'")) {{ wordSet = wordSet.replace("'", ""); wordSet = wordSet.replace("'", ""); regex = new RegExp(wordSet); }} else {{ regex = new RegExp(wordSet, "i"); }} found &= regex.test(div.innerHTML); }} if (found) {{ div.hidden = false; count++; }} }}; if (searchResultCount) {{ searchResultCount.innerHTML = count; }} """ def __init__(self, parent): super().__init__() self.parent = parent self.setWindowTitle(config.thisTranslation["liveFilter"]) self.setMinimumSize(400, 400) self.selectedFilter = None self.selectedPattern = None self.settingBibles = False self.db = LiveFilterSqlite() self.filters = None self.saveReadFormattedBibles = config.readFormattedBibles if config.readFormattedBibles: self.parent.disableBiblesInParagraphs() self.setupUI() def setupUI(self): mainLayout = QVBoxLayout() title = QLabel(config.thisTranslation["liveFilter"]) mainLayout.addWidget(title) self.filtersTable = QTableView() self.filtersTable.setEnabled(True) self.filtersTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.filtersTable.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.filtersTable) self.filtersTable.setModel(self.dataViewModel) self.dataViewModel.itemChanged.connect(self.filterSelectionChanged) self.selectionModel = self.filtersTable.selectionModel() self.selectionModel.selectionChanged.connect(self.handleSelection) mainLayout.addWidget(self.filtersTable) self.reloadFilters() buttonsLayout = QHBoxLayout() addButton = QPushButton(config.thisTranslation["add"]) addButton.clicked.connect(self.addNewFilter) buttonsLayout.addWidget(addButton) removeButton = QPushButton(config.thisTranslation["remove"]) removeButton.clicked.connect(self.removeFilter) buttonsLayout.addWidget(removeButton) editButton = QPushButton(config.thisTranslation["edit"]) editButton.clicked.connect(self.editFilter) buttonsLayout.addWidget(editButton) importButton = QPushButton(config.thisTranslation["import"]) importButton.clicked.connect(self.importFile) buttonsLayout.addWidget(importButton) buttonsLayout.addStretch() mainLayout.addLayout(buttonsLayout) buttons = QDialogButtonBox.Ok self.buttonBox = QDialogButtonBox(buttons) self.buttonBox.accepted.connect(self.accept) self.buttonBox.accepted.connect(self.close) self.buttonBox.rejected.connect(self.reject) mainLayout.addWidget(self.buttonBox) self.setLayout(mainLayout) def close(self): pass def reloadFilters(self): self.filters = self.db.getAll() self.dataViewModel.clear() rowCount = 0 for bible, description in self.filters: item = QStandardItem(bible) item.setToolTip(bible) item.setCheckable(True) self.dataViewModel.setItem(rowCount, 0, item) item = QStandardItem(description) self.dataViewModel.setItem(rowCount, 1, item) rowCount += 1 self.dataViewModel.setHorizontalHeaderLabels([ config.thisTranslation["filter2"], config.thisTranslation["pattern"] ]) self.filtersTable.resizeColumnsToContents() def handleSelection(self, selected, deselected): for item in selected: row = item.indexes()[0].row() filter = self.dataViewModel.item(row, 0) self.selectedFilter = filter.text() pattern = self.dataViewModel.item(row, 1) self.selectedPattern = pattern.text() def filterSelectionChanged(self, item): try: numChecked = 0 for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) if item.checkState() == Qt.Checked: numChecked += 1 if numChecked == 0: config.mainWindow.studyPage.runJavaScript( self.JS_HIDE.format("false")) else: sets = [] config.mainWindow.studyPage.runJavaScript( self.JS_HIDE.format("true")) for index in range(self.dataViewModel.rowCount()): item = self.dataViewModel.item(index) if item.checkState() == Qt.Checked: sets.append('"{0}"'.format(self.filters[index][1])) wordSets = ",".join(sets) js = self.JS_SHOW.format(wordSets) config.mainWindow.studyPage.runJavaScript(js) except Exception as e: print(str(e)) def addNewFilter(self): fields = [(config.thisTranslation["filter2"], ""), (config.thisTranslation["pattern"], "")] dialog = MultiLineInputDialog("New Filter", fields) if dialog.exec(): data = dialog.getInputs() self.db.insert(data[0], data[1]) self.reloadFilters() def removeFilter(self): reply = QMessageBox.question( self, "Delete", 'Delete {0} {1}'.format(self.selectedFilter, config.thisTranslation["filter2"]), QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.db.delete(self.selectedFilter) self.reloadFilters() def editFilter(self): fields = [(config.thisTranslation["filter2"], self.selectedFilter), (config.thisTranslation["pattern"], self.selectedPattern)] dialog = MultiLineInputDialog("Edit Filter", fields) if dialog.exec(): data = dialog.getInputs() self.db.delete(self.selectedFilter) self.db.insert(data[0], data[1]) self.reloadFilters() def importFile(self): options = QFileDialog.Options() filename, filtr = QFileDialog.getOpenFileName( self, config.thisTranslation["import"], config.thisTranslation["liveFilter"], "File (*.*)", "", options) if filename: try: with open(filename, errors='ignore') as f: for line in f: data = line.split(":::") filter = data[0].strip() pattern = data[1].strip() if self.db.checkFilterExists(filter): self.db.delete(filter) self.db.insert(filter, pattern) except Exception as e: print(e) self.reloadFilters()
from qtpy.QtCore import Qt, QVariant, QSortFilterProxyModel from qtpy.QtGui import QStandardItemModel, QStandardItem from qtpy.QtWidgets import QApplication, QTableView class NumberSortModel(QSortFilterProxyModel): def lessThan(self, left, right): lvalue = float(left.data()) rvalue = float(right.data()) return lvalue < rvalue if __name__ == "__main__": app = QApplication(sys.argv) model = QStandardItemModel(5, 5) random.seed() for i in range(5): for j in range(5): item = QStandardItem() item.setData(QVariant(str(random.randint(-500, 500)/10.0)), Qt.DisplayRole) model.setItem(i, j, item) proxy = NumberSortModel() proxy.setSourceModel(model) view = QTableView() view.setModel(proxy) view.setSortingEnabled(True) view.show() sys.exit(app.exec_())
class BibleCollectionDialog(QDialog): def __init__(self, parent): super().__init__() self.setWindowTitle(config.thisTranslation["bibleCollections"]) self.setMinimumSize(680, 500) self.selectedCollection = None self.settingBibles = False self.bibles = self.getBibles() self.setupUI() self.parent = parent def setupUI(self): mainLayout = QVBoxLayout() title = QLabel(config.thisTranslation["bibleCollections"]) mainLayout.addWidget(title) self.collectionsLayout = QVBoxLayout() self.collectionsList = QListWidget() self.collectionsList.setMaximumHeight(90) self.collectionsLayout.addWidget(self.collectionsList) mainLayout.addLayout(self.collectionsLayout) self.showListOfCollections() buttonsLayout = QHBoxLayout() addButton = QPushButton(config.thisTranslation["add"]) addButton.clicked.connect(self.addNewCollection) buttonsLayout.addWidget(addButton) removeButton = QPushButton(config.thisTranslation["remove"]) removeButton.clicked.connect(self.removeCollection) buttonsLayout.addWidget(removeButton) renameButton = QPushButton(config.thisTranslation["rename"]) renameButton.clicked.connect(self.renameCollection) buttonsLayout.addWidget(renameButton) buttonsLayout.addStretch() mainLayout.addLayout(buttonsLayout) self.biblesTable = QTableView() self.biblesTable.setEnabled(False) self.biblesTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.biblesTable.setSortingEnabled(True) self.dataViewModel = QStandardItemModel(self.biblesTable) self.biblesTable.setModel(self.dataViewModel) self.loadBibleSelection() self.dataViewModel.itemChanged.connect(self.bibleSelectionChanged) mainLayout.addWidget(self.biblesTable) buttonLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["close"]) button.clicked.connect(self.reloadControlPanel) button.clicked.connect(self.close) buttonLayout.addWidget(button) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) def showListOfCollections(self): self.collectionsList.clear() if len(config.bibleCollections) > 0: for collection in sorted(config.bibleCollections.keys()): showBibleSelection = QRadioButton() showBibleSelection.setChecked(False) self.collectionsList.itemClicked.connect(self.selectCollection) self.collectionsList.addItem(collection) else: self.collectionsList.addItem("[No collection defined]") def addNewCollection(self): name, ok = QInputDialog.getText(self, 'Collection', 'Collection name:') if ok and len(name) > 0 and name != "All": config.bibleCollections[name] = {} self.showListOfCollections() self.biblesTable.setEnabled(False) def removeCollection(self): config.bibleCollections.pop(self.selectedCollection, None) self.showListOfCollections() self.biblesTable.setEnabled(False) def renameCollection(self): name, ok = QInputDialog.getText(self, 'Collection', 'Collection name:', text=self.selectedCollection) if ok and len(name) > 0 and name != "All": biblesInCollection = config.bibleCollections[ self.selectedCollection] config.bibleCollections.pop(self.selectedCollection, None) self.selectedCollection = name config.bibleCollections[name] = biblesInCollection self.showListOfCollections() self.biblesTable.setEnabled(False) def getBibles(self): from db.BiblesSqlite import BiblesSqlite from db.BiblesSqlite import Bible bibles = BiblesSqlite().getBibleList() bibleInfo = [] for bible in bibles: description = Bible(bible).bibleInfo() bibleInfo.append((bible, description)) return bibleInfo def selectCollection(self, item): self.selectedCollection = item.text() self.biblesTable.setEnabled(True) self.loadBibleSelection() def bibleSelectionChanged(self, item): if not self.settingBibles: if self.selectedCollection is not None: text = item.text() biblesInCollection = config.bibleCollections[ self.selectedCollection] if len(biblesInCollection) == 0: biblesInCollection = [] if text in biblesInCollection: biblesInCollection.remove(text) else: biblesInCollection.append(text) config.bibleCollections[ self.selectedCollection] = biblesInCollection def loadBibleSelection(self): self.settingBibles = True self.dataViewModel.clear() biblesInCollection = [] if self.selectedCollection is not None: biblesInCollection = config.bibleCollections[ self.selectedCollection] rowCount = 0 for bible, description in self.bibles: item = QStandardItem(bible) item.setToolTip(bible) item.setCheckable(True) if bible in biblesInCollection: item.setCheckState(Qt.Checked) self.dataViewModel.setItem(rowCount, 0, item) item = QStandardItem(description) self.dataViewModel.setItem(rowCount, 1, item) rowCount += 1 self.dataViewModel.setHorizontalHeaderLabels([ config.thisTranslation["bible"], config.thisTranslation["description"] ]) self.biblesTable.resizeColumnsToContents() self.settingBibles = False def reloadControlPanel(self): self.parent.reloadControlPanel(False)