def readSettings(self): settings = QSettings("Boxshade", "Boxshade") settings.setFallbacksEnabled(False) pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos)
def reload_settings(): global settings if settings: del settings settings = QSettings('settings.ini', QSettings.IniFormat) settings.setFallbacksEnabled(False)
class Settings: def __init__(self): self.settings = QSettings('settings.ini', QSettings.IniFormat) self.settings.setFallbacksEnabled(False) def getMaxNum(self): return self.settings.value('max', 100, type=int) def setMaxNum(self, v): self.settings.setValue('max', v) def getMinNum(self): return self.settings.value('min', 0, type=int) def setMinNum(self, v): self.settings.setValue('min', v) def isPlusEnable(self): return self.settings.value('op_plus', True, type=bool) def setPlusEnable(self, v): self.settings.setValue('op_plus', v) def isMinusEnable(self): return self.settings.value('op_minus', True, type=bool) def setMinusEnable(self, v): self.settings.setValue('op_minus', v) def isMultiEnable(self): return self.settings.value('op_multi', False, type=bool) def setMultiEnable(self, v): self.settings.setValue('op_multi', v) def isDivideEnable(self): return self.settings.value('op_div', False, type=bool) def setDivideEnable(self, v): self.settings.setValue('op_div', v) def getQuestionNum(self): return self.settings.value('question_number', 15, type=int) def setQuestionNum(self, v): self.settings.setValue('question_number', v) def getOperatorNum(self): return self.settings.value('op_number', 1, type=int) def setOperatorNum(self, v): self.settings.setValue('op_number', v) def isSupportNegative(self): return self.settings.value('support_nagtive', False, type=bool) def setSupportNegative(self, v): self.settings.setValue('support_nagtive', v)
class UserTexts: def __init__(self): self.texts = QSettings(QSettings.IniFormat, QSettings.SystemScope, 'TypoViewer', 'user') #self.settings = QSettings('settings.ini', QSettings.IniFormat) self.texts.setFallbacksEnabled(False) # File only, not registry or or. #self.texts.setValue('xx','yyyy') def getTexts(self): return self.texts
def set_defaults( ): # To be called the first time the program is run, if there are no Preferences settings = QSettings("Boxshade", "Boxshade") settings.setFallbacksEnabled(False) if settings.contains("ASCIIchars"): return settings.setValue( "simsline", 'SIMS:F YW:Y FW:W FY:I LM:L IM:M IL:R KH:K RH:H KR:A G:S T:D EN:E DQ:N EQ:P G:V M:END' ) settings.setValue("grpsline", 'GRPS:FYW:ILVM:DE:GA:ST:NQ:RKH:END') settings.setValue("DNAsimsline", 'SIMS:A GR:G AR:C TY:T CY:R AG:Y CT:END') settings.setValue("DNAgrpsline", 'GRPS:AGR:CTY:END') settings.setValue("thrfrac", 0.7) settings.setValue("scflag", False) settings.setValue("snameflag", True) settings.setValue("RHsnumsflag", False) settings.setValue("LHsnumsflag", False) settings.setValue("defnumsflag", False) settings.setValue("simflag", True) settings.setValue("globalflag", True) settings.setValue("consflag", False) settings.setValue("outlen", 60) settings.setValue("interlines", 1) settings.setValue("symbcons", ' LU') settings.setValue("consline", 1) settings.setValue("rulerflag", False) settings.setValue("pepseqsflag", True) settings.setValue("PSfgds", [ QColor(0, 0, 0), QColor(255, 255, 255), QColor(0, 0, 0), QColor(255, 255, 255) ]) settings.setValue("PSbgds", [ QColor(255, 255, 255), QColor(0, 0, 0), QColor(180, 180, 180), QColor(0, 0, 0) ]) settings.setValue("PSFsize", 12) settings.setValue("PSLCs", [False, False, False, False]) settings.setValue("PSlandscapeflag", False) settings.setValue("ASCIIchars", ['L', '.', 'l', '*']) settings.setValue("pos", QPoint(200, 200)) settings.setValue("size", QSize(400, 400)) settings.sync() return
def make_tagger(app): # todo this will eventually end up in Tagger project_studio = ProjectStudio() cheddar = Cheddar(host="tagyourmusic.com", port=443, secure=True) player = open_media_player(project_studio) # todo this will eventually end up in Tagger.close() app.aboutToQuit.connect(cheddar.stop) app.aboutToQuit.connect(player.dispose) settings = QSettings() settings.setFallbacksEnabled(False) # To avoid getting global OS X settings that apply to all applications tagger = Tagger(settings, project_studio, player, cheddar) tagger.translate(app) return tagger
def moveSettingsToNewRoot(): """Move all settings to one application file.""" movelist = [[appinfo.name, appinfo.url, False], "metainfo", "snippets", "sessions", "sessiondata"] for moveitem in movelist: if isinstance(moveitem, string_types): moveitem = [moveitem, appinfo.name, True] o = QSettings(moveitem[1], moveitem[0]) o.setFallbacksEnabled(False) keys = o.allKeys() if len(keys) > 0: s = QSettings() if moveitem[2]: s.beginGroup(moveitem[0]) for k in keys: s.setValue(k, o.value(k)) o.clear()
def make_tagger(app): # todo this will eventually end up in Tagger project_studio = ProjectStudio() cheddar = Cheddar(host="tagyourmusic.com", port=443, secure=True) player = open_media_player(project_studio) # todo this will eventually end up in Tagger.close() app.aboutToQuit.connect(cheddar.stop) app.aboutToQuit.connect(player.dispose) settings = QSettings() settings.setFallbacksEnabled( False ) # To avoid getting global OS X settings that apply to all applications tagger = Tagger(settings, project_studio, player, cheddar) tagger.translate(app) return tagger
class settingsWindow(QMainWindow): def __init__(self, parent=None): super().__init__() self.init_ui(parent) def init_ui(self, parent): self.parent = parent # this is the master window settingsWindow = Ui_settingsWindow() settingsWindow.setupUi(self) self.settingsWindow = settingsWindow self.settings = QSettings('collBook', 'collBook') #self.settingsWindow.value_CollectionName.setPlainText(self.get('value_CollectionName')) self.settings.setFallbacksEnabled(False) # File only, no fallback to registry. # before we populate them, verify the file exists self.populateSettings() self.settingsWindow.button_SaveExit.clicked.connect(self.saveButtonClicked) self.settingsWindow.button_Cancel.clicked.connect(self.cancelButtonClicked) self.settingsWindow.toolButton_GetLogoPath.clicked.connect(self.getLogoPath) self.genDummyCatalogNumber() # be sure the settings file exists if not self.settings.value('version', False): self.saveSettings() self.setMaxZoom() # can also later do a check if the version is not up-to-date def setMaxZoom(self): try: self.parent.updatePreview() except AttributeError: pass screenSize = (self.parent.geometry()) screenX = screenSize.width() xMax = screenX * 0.6 screenY = screenSize.height() yMax = screenY * 0.75 # resulting pdfs are 96dpi skip calling getPixmap twice, Assume 96 # 96dpi / 25.4mm per inch = 3.780 dots per mm label_X = int(self.settingsWindow.value_X.value() * (3.780)) label_Y = int(self.settingsWindow.value_Y.value() * (3.780)) max_XZoom = xMax / label_X max_YZoom = yMax / label_Y max_Zoom = int(min(max_XZoom, max_YZoom) * 100) self.parent.w.value_zoomLevel.setMaximum(max_Zoom) currentZoom = int(self.parent.w.value_zoomLevel.value()) if currentZoom > max_Zoom: valueToSet = (max_Zoom) else: valueToSet = currentZoom self.parent.w.value_zoomLevel.setValue(valueToSet) self.parent.w.label_zoomLevel.setText(f'{str(valueToSet).rjust(4," ")}%') # update the label self.settings.setValue('value_zoomLevel', valueToSet) # update settings def saveButtonClicked(self): """ hides the preferences window and saves the user entries """ # check the new limitations on zoomlevel self.setMaxZoom() self.saveSettings() # force pdf_preview window to resize ui elements. self.parent.pdf_preview.initViewer(self.parent) self.parent.p.initLogoCanvas() # build the logo backdrop for labels. self.genDummyCatalogNumber() self.parent.updatePreview() self.parent.updateAutoComplete() # reset tax session's alignments since the settings have changed self.parent.tax.sessionAlignments = {} self.hide() def cancelButtonClicked(self): """ hides the preferences window and resets user entries to last known good saved values """ self.hide() self.populateSettings() def getLogoPath(self): """ opens a QFileDialog to select an image""" fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Logo Image", QtCore.QDir.homePath(), 'Image Files(*.png *.jpg *.bmp)') if fileName: # if an image was selected, store the path self.settingsWindow.value_LogoPath.setText(fileName) def has(self, key): return self.settings.contains(key) def setValue(self, key, value): return self.settings.setValue(key, value) def get(self, key, altValue = ""): result = self.settings.value(key, altValue) if result == 'true': result = True elif result == 'false': result = False return result def populateQComboBoxSettings(self, obj, value): """ sets a QComboBox based on a string value. Presumed to be a more durable method. obj is the qComboBox object, and value is a string to search for""" index = obj.findText(value) obj.setCurrentIndex(index) def convertCheckState(self, stringState): """ given a string either "true" or "false" returns the proper Qt.CheckState""" if str(stringState).lower() != 'true': return Qt.Unchecked else: return Qt.Checked def kingdomChanged(self, QString): """ called when value_Kingdom changes text. Calls populateSources, and """ self.populateSources(QString) def updateCatalogNumberPreview(self, QString): """ called when a change is made to any of the appropriate fields in catalogNumberPage. Updates the example preview catalog number """ prefix = self.settingsWindow.value_catalogNumberPrefix.text() digits = int(self.settingsWindow.value_catalogNumberDigits.value()) startingNum = str(self.settingsWindow.value_catalogNumberStartingNum.value()) startingNum = startingNum.zfill(digits) # fill in leading zeroes previewText = f'{prefix}{startingNum}' # assemble the preview string. self.settingsWindow.label_catalogNumber_Preview.setText(previewText) # set it def updateStartingCatalogNumber(self, val): """ called when value_catalogNumberdigits changes and alters the max value allowed in value_catalogNumberStartingNum. Also, called when Catalog numbers are applied, to increment the value_catalogNumberStartingNum""" sender = self.sender() # check if it is appropriate to alter the maximum digits for starting value if sender.objectName() == "value_catalogNumberDigits": maxDigits = int(val) newMax = int(''.ljust(maxDigits, '9')) self.settingsWindow.value_catalogNumberStartingNum.setMaximum(newMax) else: # otherwise just edit the starting value self.settingsWindow.value_catalogNumberStartingNum.setValue(val) self.setValue('value_catalogNumberStartingNum', val) self.updateCatalogNumberPreview def populateSources(self, QString): """ called when value_Kingdom changes text. Decides what the options should be for value_TaxAlignSource (taxanomic alignment source).""" kingdom = QString source = self.settingsWindow.value_TaxAlignSource sourceValue = source.currentText() # save initial selection source.clear() # clear existing options # conditionally build a list of those which to add. # NOTE: keeping Local options in index 0 position if kingdom == 'Plantae': toAdd = ['ITIS (local)', 'Catalog of Life (web API)', 'Taxonomic Name Resolution Service (web API)'] elif kingdom == 'Fungi': toAdd = ['MycoBank (local)', 'Catalog of Life (web API)'] source.addItems(toAdd) newIndex = source.findText(sourceValue) # look for new index of initial selection if newIndex == -1: # if it is no longer in the list newIndex = 0 # , settle for index 0 (the local option) source.setCurrentIndex(newIndex) # set the selection after the population change. def toggleTNRSSettings(self, QString): """ called when value_TaxAlignSource changes text. Decides if the groupbox_TNRS should be enabled or not""" if str(QString) == 'Taxonomic Name Resolution Service (web API)': b = True else: b = False self.settingsWindow.groupbox_TNRS.setEnabled(b) def scalingChanged(self, Qint): parent = self.settingsWindow val = f'({str(Qint)}%)'.rjust(8, ' ') parent.label_scalingValue.setText(val) def opacityChanged(self, Qint): parent = self.settingsWindow val = f'({str(Qint)}%)'.rjust(8, ' ') parent.label_opacityValue.setText(val) def genDummyCatalogNumber(self): """ generates a single dummy catalog number for label previews""" incDummy = self.get('value_inc_Barcode', False) if incDummy: catDigits = int(self.get('value_catalogNumberDigits')) catPrefix = self.get('value_catalogNumberPrefix') dummyCatNumber = f'{catPrefix}{str(0).zfill(catDigits)}' else: dummyCatNumber = False self.dummyCatNumber = dummyCatNumber def populateSettings(self): """ uses self.settings to populate the preferences widget's selections""" parent = self.settingsWindow # QComboBox value_AuthChangePolicy = self.get('value_AuthChangePolicy', 'Always ask') self.populateQComboBoxSettings( parent.value_AuthChangePolicy, value_AuthChangePolicy) value_NameChangePolicy = self.get('value_NameChangePolicy', 'Always ask') self.populateQComboBoxSettings( parent.value_NameChangePolicy, value_NameChangePolicy) value_TaxAlignSource = self.get('value_TaxAlignSource', 'ITIS (local)') self.populateQComboBoxSettings( parent.value_TaxAlignSource, value_TaxAlignSource) value_Kingdom = self.get('value_Kingdom', 'Plantae') self.populateQComboBoxSettings( parent.value_Kingdom, value_Kingdom) value_LogoAlignment = self.get('value_LogoAlignment', 'Centered') self.populateQComboBoxSettings( parent.value_LogoAlignment, value_LogoAlignment) # QLineEdit value_VerifiedBy = self.get('value_VerifiedBy') parent.value_VerifiedBy.setText(value_VerifiedBy) value_LogoPath = self.get('value_LogoPath') parent.value_LogoPath.setText(value_LogoPath) value_catalogNumberPrefix = self.get('value_catalogNumberPrefix') parent.value_catalogNumberPrefix.setText(value_catalogNumberPrefix) # QPlainTextEdit value_CollectionName = self.get('value_CollectionName') parent.value_CollectionName.setPlainText(value_CollectionName) # QCheckBox value_inc_Associated = self.convertCheckState(self.get('value_inc_Associated')) parent.value_inc_Associated.setCheckState(value_inc_Associated) value_inc_Barcode = self.convertCheckState(self.get('value_inc_Barcode')) parent.value_inc_Barcode.setCheckState(value_inc_Barcode) value_inc_CollectionName = self.convertCheckState(self.get('value_inc_CollectionName')) parent.value_inc_CollectionName.setCheckState(value_inc_CollectionName) value_inc_VerifiedBy = self.convertCheckState(self.get('value_inc_VerifiedBy')) parent.value_inc_VerifiedBy.setCheckState(value_inc_VerifiedBy) # QGroupbox (checkstate) value_inc_Logo = self.convertCheckState(self.get('value_inc_Logo')) parent.value_inc_Logo.setChecked(value_inc_Logo) value_assignCatalogNumbers = self.convertCheckState(self.get('value_assignCatalogNumbers')) parent.value_assignCatalogNumbers.setChecked(value_assignCatalogNumbers) # QSpinBox value_X = int(self.get('value_X', 140)) parent.value_X.setValue(value_X) value_Y = int(self.get('value_Y', 90)) parent.value_Y.setValue(value_Y) value_RelFont = int(self.get('value_RelFont', 12)) parent.value_RelFont.setValue(value_RelFont) value_TNRS_Threshold = int(self.get('value_TNRS_Threshold', 85)) parent.value_TNRS_Threshold.setValue(value_TNRS_Threshold) value_LogoMargin = int(self.get('value_LogoMargin', 2)) parent.value_LogoMargin.setValue(value_LogoMargin) value_catalogNumberDigits = int(self.get('value_catalogNumberDigits', 1)) parent.value_catalogNumberDigits.setValue(value_catalogNumberDigits) value_catalogNumberStartingNum = int(self.get('value_catalogNumberStartingNum', 0)) parent.value_catalogNumberStartingNum.setValue(value_catalogNumberStartingNum) value_max_Associated = int(self.get('value_max_Associated', 10)) parent.value_max_Associated.setValue(value_max_Associated) # slider value_LogoScaling = int(self.get('value_LogoScaling', 100)) parent.value_LogoScaling.setValue(value_LogoScaling) self.scalingChanged(value_LogoScaling) value_LogoOpacity = int(self.get('value_LogoOpacity', 30)) parent.value_LogoOpacity.setValue(value_LogoOpacity) self.opacityChanged(value_LogoOpacity) # note the self.parent.label here, accessing mainwindow. value_zoomLevel = int(self.get('value_zoomLevel', 100)) self.parent.w.value_zoomLevel.setValue(value_zoomLevel) # radiobutton value_DarkTheme = self.get('value_DarkTheme', False) parent.value_DarkTheme.setChecked(value_DarkTheme) value_LightTheme = self.get('value_LightTheme', True) parent.value_LightTheme.setChecked(value_LightTheme) value_associatedAlways = self.get('value_associatedAlways', True) parent.value_associatedAlways.setChecked(value_associatedAlways) value_associatedOnly = self.get('value_associatedOnly', False) parent.value_associatedOnly.setChecked(value_associatedOnly) value_associatedNever = self.get('value_associatedNever', False) parent.value_associatedNever.setChecked(value_associatedNever) # clean up self.updateCatalogNumberPreview def saveSettings(self): """ stores the preferences widget's selections to self.settings""" parent = self.settingsWindow # save the version number version = self.parent.w.version self.setValue('version', version) # save the laste date we checked the version number try: date_versionCheck = self.parent.w.date_versionCheck except AttributeError: # first run may not yet have this saved. date_versionCheck = "" self.setValue('date_versionCheck', date_versionCheck) # QComboBox value_AuthChangePolicy = parent.value_AuthChangePolicy.currentText() self.setValue('value_AuthChangePolicy', value_AuthChangePolicy) value_NameChangePolicy = parent.value_NameChangePolicy.currentText() self.setValue('value_NameChangePolicy', value_NameChangePolicy) value_TaxAlignSource = parent.value_TaxAlignSource.currentText() self.setValue('value_TaxAlignSource', value_TaxAlignSource) value_Kingdom = parent.value_Kingdom.currentText() self.setValue('value_Kingdom', value_Kingdom) value_LogoAlignment = parent.value_LogoAlignment.currentText() self.setValue('value_LogoAlignment', value_LogoAlignment) # QLineEdit value_VerifiedBy = parent.value_VerifiedBy.text() self.setValue('value_VerifiedBy', value_VerifiedBy) value_LogoPath = parent.value_LogoPath.text() self.setValue('value_LogoPath', value_LogoPath) value_catalogNumberPrefix = parent.value_catalogNumberPrefix.text() self.setValue('value_catalogNumberPrefix', value_catalogNumberPrefix) # QPlainTextEdit value_CollectionName = parent.value_CollectionName.toPlainText() self.setValue('value_CollectionName', value_CollectionName) # QCheckBox value_inc_Associated = parent.value_inc_Associated.isChecked() self.setValue('value_inc_Associated', value_inc_Associated) value_inc_Barcode = parent.value_inc_Barcode.isChecked() self.setValue('value_inc_Barcode', value_inc_Barcode) value_inc_CollectionName = parent.value_inc_CollectionName.isChecked() self.setValue('value_inc_CollectionName', value_inc_CollectionName) value_inc_VerifiedBy = parent.value_inc_VerifiedBy.isChecked() self.setValue('value_inc_VerifiedBy', value_inc_VerifiedBy) # QGroupbox value_inc_Logo = parent.value_inc_Logo.isChecked() self.setValue('value_inc_Logo', value_inc_Logo) value_assignCatalogNumbers = parent.value_assignCatalogNumbers.isChecked() self.setValue('value_assignCatalogNumbers', value_assignCatalogNumbers) # QSpinBox value_X = parent.value_X.value() self.setValue('value_X', value_X) value_Y = parent.value_Y.value() self.setValue('value_Y', value_Y) value_RelFont = parent.value_RelFont.value() self.setValue('value_RelFont', value_RelFont) value_TNRS_Threshold = parent.value_TNRS_Threshold.value() self.setValue('value_TNRS_Threshold', value_TNRS_Threshold) value_LogoMargin = parent.value_LogoMargin.value() self.setValue('value_LogoMargin', value_LogoMargin) value_catalogNumberDigits = parent.value_catalogNumberDigits.value() self.setValue('value_catalogNumberDigits', value_catalogNumberDigits) value_catalogNumberStartingNum = parent.value_catalogNumberStartingNum.value() self.setValue('value_catalogNumberStartingNum', value_catalogNumberStartingNum) value_max_Associated = parent.value_max_Associated.value() self.setValue('value_max_Associated', value_max_Associated) # slider value_LogoScaling = parent.value_LogoScaling.value() self.setValue('value_LogoScaling', value_LogoScaling) value_LogoOpacity = parent.value_LogoOpacity.value() self.setValue('value_LogoOpacity', value_LogoOpacity) value_zoomLevel = self.parent.w.value_zoomLevel.value() self.setValue('value_zoomLevel', value_zoomLevel) # radiobutton value_DarkTheme = parent.value_DarkTheme.isChecked() self.setValue('value_DarkTheme', value_DarkTheme) value_LightTheme = parent.value_LightTheme.isChecked() self.setValue('value_LightTheme', value_LightTheme) value_associatedAlways = parent.value_associatedAlways.isChecked() self.setValue('value_associatedAlways', value_associatedAlways) value_associatedOnly = parent.value_associatedOnly.isChecked() self.setValue('value_associatedOnly', value_associatedOnly) value_associatedNever = parent.value_associatedNever.isChecked() self.setValue('value_associatedNever', value_associatedNever)
class Dashboard(QMainWindow): def __init__(self): super().__init__() self.ui = loadUi( os.path.dirname(os.path.realpath(__file__)) + "/gui.ui", self) self.logger = Logger() self.settings = QSettings(self.logger.config['gui_cache_address'], QSettings.IniFormat) # self.settings = QSettings('settings.ini', QSettings.IniFormat) self.settings.setFallbacksEnabled( False) # File only, no fallback to registry or. # First get the report type data self.data = Data() # get the defaults self.data = self.logger.load_existing_data(self.data) # pprint.pprint(self.data.__dict__) self.initialize_gui() # if gui cache exists it will be loaded and overwrite the defaults self.logger.gui_restore(self.ui, self.settings) # self.data = self.logger.update_data(self.ui) def initialize_gui(self): self.frame() self.timer = TimerWidget(self) #todo neaten this up by making args to TodoWidget and Errandwidget match todo_groupboxes = [ self.todo_groupBox, self.todo_groupBox_2, self.todo_groupBox_3 ] errand_groupboxes = [ self.daily_errands_groupBox, self.weekly_errands_groupBox, self.monthly_errands_groupBox ] timescale_data = [self.data.daily, self.data.weekly, self.data.monthly] scales = ['daily', 'weekly', 'monthly'] self.errandwidgets, self.todowidgets = [], [] for todo_groupbox, errand_groupbox, timescale_data, scale in zip( todo_groupboxes, errand_groupboxes, timescale_data, scales): self.todowidgets.append(TodoWidget(todo_groupbox, timescale_data)) self.errandwidgets.append(ErrandWidget(self, scale)) self.toolbarWidget() self.reports = ReportWidget(self) self.calendar = OneDayCalWidget(self) def frame(self): self.conc_mode = False title = 'Dashboard' self.setWindowTitle(title) self.left = 0 self.top = 0 self.width = 1730 #1360 self.height = 930 #825 self.setGeometry(self.left, self.top, self.width, self.height) def toolbarWidget(self): self.actionSave_2.triggered.connect(self.save) self.actionLoad_2.triggered.connect(self.load) self.actionClose.triggered.connect(self.close) self.action_concentration.triggered.connect(self.concentration_mode) self.saveshortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.saveshortcut.activated.connect(self.save) self.loadshortcut = QShortcut(QKeySequence("Ctrl+O"), self) self.loadshortcut.activated.connect(self.load) self.closeshortcut = QShortcut(QKeySequence("Ctrl+D"), self) self.closeshortcut.activated.connect(self.close) self.concshortcut = QShortcut(QKeySequence("Ctrl+M"), self) self.concshortcut.activated.connect(self.concentration_mode) def concentration_mode(self): self.conc_mode = True print('Entering distraction free mode') frame_geometry = self.tabWidget.geometry() self.tabWidget.setGeometry(frame_geometry.left() - 14, frame_geometry.top() - 70, self.tabWidget.geometry().width(), self.tabWidget.geometry().height()) width = 605 height = 200 self.setGeometry(self.left, self.top, width, height) self.action_concentration.setText('Enter full display mode') self.action_concentration.triggered.disconnect() self.action_concentration.triggered.connect(self.full_mode) self.concshortcut.activated.disconnect() self.concshortcut.activated.connect(self.full_mode) def full_mode(self): self.conc_mode = False print('Entering full display free mode') frame_geometry = self.tabWidget.geometry() self.tabWidget.setGeometry(frame_geometry.left() + 14, frame_geometry.top() + 70, self.tabWidget.geometry().width(), self.tabWidget.geometry().height()) self.setGeometry(self.left, self.top, self.width, self.height) self.action_concentration.setText('Enter concentration mode') self.action_concentration.triggered.disconnect() self.action_concentration.triggered.connect(self.concentration_mode) self.concshortcut.activated.disconnect() self.concshortcut.activated.connect(self.concentration_mode) def closeEvent(self, event): self.logger.gui_save(self.ui, self.settings) self.logger.data_save(self.data) event.accept() def save(self): self.logger.gui_save(self.ui, self.settings) self.logger.data_save(self.data) def load(self): self.logger.data_load()
def __init__(self, ): basePath = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), os.pardir)) settings = QSettings('settings.ini', QSettings.IniFormat) settings.setFallbacksEnabled(False) self.skinName = settings.value("skin", "modern_chalk") self.eventName = settings.value("event", "openningWallstreat") self.logPath = basePath + "/photobooth-datas/local_datas/logs" if not os.path.exists(self.logPath): os.makedirs(self.logPath) self.logPath = os.path.normpath(self.logPath) self.logFile = self.logPath + '/photobooth.log' self.logFile = os.path.normpath(self.logFile) self.logger = logger(self.logFile) self.logger.addInfo("STARTING RESSOURCE MANAGER") self.printDuration = 60 self.numberOfPrint = 0 self.maxNumberOfPrint = 36 self.applicationPath = basePath + "/photobooth" self.applicationPath = os.path.normpath(self.applicationPath) self.skinPath = self.applicationPath + "/resources/skins/" + self.skinName self.skinPath = os.path.normpath(self.skinPath) self.pagesPath = self.skinPath self.pagesPath = os.path.normpath(self.pagesPath) self.layoutPath = self.applicationPath + "/resources/events/" + self.eventName self.layoutPath = os.path.normpath(self.layoutPath) self.thumbLocalPath = basePath + "/photobooth-datas/local_datas/thumbs" if not os.path.exists(self.thumbLocalPath): os.makedirs(self.thumbLocalPath) self.thumbLocalPath = os.path.normpath(self.thumbLocalPath) self.applicationLocalDataPath = basePath + "/photobooth-datas/local_datas" if not os.path.exists(self.applicationLocalDataPath): os.makedirs(self.applicationLocalDataPath) self.applicationLocalDataPath = os.path.normpath(self.applicationLocalDataPath) self.captureLocalPath = self.applicationLocalDataPath + "/" + self.eventName + "/captures" if not os.path.exists(self.captureLocalPath): os.makedirs(self.captureLocalPath) self.captureLocalPath = os.path.normpath(self.captureLocalPath) self.applicationUSBDataPath = basePath + "/photobooth-datas/usb_datas" if not os.path.exists(self.applicationUSBDataPath): os.makedirs(self.applicationUSBDataPath) self.applicationUSBDataPath = os.path.normpath(self.applicationUSBDataPath) self.assembliesPath = self.applicationUSBDataPath + "/" + self.eventName + "/assemblies" if not os.path.exists(self.assembliesPath): os.makedirs(self.assembliesPath) self.assembliesPath = os.path.normpath(self.assembliesPath) self.captureUSBPath = self.applicationUSBDataPath + "/" + self.eventName + "/captures" if not os.path.exists(self.captureUSBPath): os.makedirs(self.captureUSBPath) self.captureUSBPath = os.path.normpath(self.captureUSBPath) self.skinLayoutDatas = [[], [], [], []] #self.skinGeneratorThemes = [] # self.skinGeneratorLayoutDatas = [[], [], [], []] self.nbImageMax = 0 self.homePageDisplayFilename=""
path = Path(get_setting(dir_)) if not path.exists(): path.mkdir(parents=True) # assemble dict of {key: [type, section], ...} since we have nested dicts in # DEFAULTS double list comprehension feels sooo backwards to write # eg {"cache_dir": [<class "str">, "Locations"], ...} TYPES = { k: [type(v), section] for section, d in DEFAULTS.items() for k, v in d.items() } SETTINGS = QSettings("Circleguard", "Circleguard") # see third bullet here https://doc.qt.io/qt-5/qsettings.html#platform-limitations, # we don't want the global keys on macos when calling allkeys SETTINGS.setFallbacksEnabled(False) # add setting if missing (occurs between updates if we add a new default # setting) for d in DEFAULTS.values(): for key, value in d.items(): if not SETTINGS.contains(key): set_setting(key, value) CFG_PATH = get_setting("config_location") + "/circleguard.cfg" def initialize_settings(): # create folders if they don't exist initialize_dirs()
def start(): app = QSingleApplication(sys.argv) if platform.system().lower() == "windows": multiprocessing.freeze_support() # windows必须调用这个,不然会出错 # 异常调试 import cgitb sys.excepthook = cgitb.Hook(1, None, 5, sys.stderr, 'text') ##为了存路径到系统 QApplication.setApplicationName("PhyloSuite_settings") QApplication.setOrganizationName("PhyloSuite") QSettings.setDefaultFormat(QSettings.IniFormat) path_settings = QSettings() path_settings.setValue("thisPath", thisPath) os.chdir(thisPath) with open(thisPath + os.sep + 'style.qss', encoding="utf-8", errors='ignore') as f: qss_file = f.read() dialog = QDialog() dialog.setStyleSheet(qss_file) # 异常处理 def handle_exception(exc_type, exc_value, exc_traceback): rgx = re.compile(r'PermissionError.+?[\'\"](.+\.csv)[\'\"]') if issubclass(exc_type, KeyboardInterrupt): return sys.__excepthook__(exc_type, exc_value, exc_traceback) exception = str("".join(traceback.format_exception( exc_type, exc_value, exc_traceback))) print(exception) if rgx.search(exception): #忽略csv未关闭的报错 return msg = QMessageBox(dialog) msg.setIcon(QMessageBox.Critical) msg.setText( 'The program encountered an unforeseen problem, please report the bug at <a href="https://github.com/dongzhang0725/PhyloSuite/issues">https://github.com/dongzhang0725/PhyloSuite/issues</a> ' 'or send an email with the detailed traceback to [email protected]') msg.setWindowTitle("Error") msg.setDetailedText(exception) msg.setStandardButtons(QMessageBox.Ok) msg.exec_() sys.excepthook = handle_exception # 避免重复运行程序 if app.isRunning(): QMessageBox.information( dialog, "PhyloSuite", "<p style='line-height:25px; height:25px'>App is running!</p>") sys.exit(0) # 界面运行选择 launcher_settings = QSettings( thisPath + '/settings/launcher_settings.ini', QSettings.IniFormat) launcher_settings.setFallbacksEnabled(False) not_exe_lunch = launcher_settings.value("ifLaunch", "false") workPlace = launcher_settings.value( "workPlace", [thisPath + os.sep + "myWorkPlace"]) # 删除无效的路径 workPlace_copy = deepcopy(workPlace) for num,i in enumerate(workPlace_copy): if not os.path.exists(i): workPlace.remove(i) else: ##替换带.的路径 if re.search(r"^\.", i): workPlace[num] = os.path.abspath(i) # 如果workPlace被删干净了 if not workPlace: workPlace = [thisPath + os.sep + "myWorkPlace"] # 重新保存下路径 if len(workPlace) > 15: workPlace = workPlace[:15] # 只保留15个工作区 launcher_settings.setValue( "workPlace", workPlace) if not_exe_lunch == "true": myMainWindow = MyMainWindow(workPlace) myMainWindow.show() sys.exit(app.exec_()) else: launcher = Launcher() if launcher.exec_() == QDialog.Accepted: workPlace = launcher.WorkPlace myMainWindow = MyMainWindow(workPlace) myMainWindow.show() sys.exit(app.exec_())
class main(QMainWindow): NUM_THREADS = 1 sig_abort_workers = pyqtSignal() def __init__(self, Parent=None): super(main, self).__init__(Parent) if getattr(sys, 'frozen', False): # we are running in a |PyInstaller| bundle basedir = sys._MEIPASS else: # we are running in a normal Python environment basedir = os.path.dirname(__file__) self.settings = QSettings("logviewer.ini", QSettings.IniFormat) self.settings.setFallbacksEnabled( False) # File only, not registry or or. self.syslogfile = os.path.join("/", "var", "log", "syslog") loadUi(os.path.join(basedir, "logviewer.ui"), self) self.setWindowTitle("Thread logviewer") try: self.att = attenuator(testMode=False) except Exception as e: print("qRVR:%s" % str(e)) if self.att: self.devices = self.att.getDevInfo() #UI header = self.twData.horizontalHeader() header.setStretchLastSection(True) #pyqsetResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) #header.setSectionResizeMode(2, QHeaderView.Stretch) # self.myService = None # self.pbBind.clicked.connect(self.startServer) self.pbTestPathbPhase.clicked.connect(self.testPathbPhase) self.pbTestRateCtl.clicked.connect(self.testRateCtl) # self.actionExit.triggered.connect(self.saveExit) self.pbSelectSource.clicked.connect(self.selectSource) self.pbStartThread.clicked.connect(self.start_threads) self.pbStopThread.clicked.connect(self.abort_workers) self.pbSaveData.clicked.connect(self.saveData) self.pbClearData.clicked.connect(self.clearData) self.leFilter.editingFinished.connect(self.setFilter) self.leServerIP.editingFinished.connect(self.setServerIP) # self.pbDirectBF.clicked.connect(self.startDirectBF) self.pbEVPathSignal.clicked.connect(self.startEVPathSignal) self.pbSaveEVPathSignal.clicked.connect(self.saveEVPathSignal) QThread.currentThread().setObjectName( 'main') # threads can be named, useful for log output self.__workers_done = None self.__threads = None self.__sFilter = '' self.__ServerIP = '' self.ifound = 0 self.currentPhase = 0 self.phase = [] self._Proxy = None self.loadSetting() def closeEvent(self, e): print("close event %s" % type(e)) # self.abort_workers() if self.myService: self.myService.stop_server() self.myService.join() def loadSetting(self): setting = self.settings self.syslogfile = setting.value( "sourcefile", os.path.join("/", "var", "log", "syslog")) self.__sFilter = setting.value("filter", "sumall") self.__ServerIP = setting.value("ServerIP", "127.0.0.1") self.setUI() def saveExit(self): self.saveSetting() self.close() def saveSetting(self): setting = self.settings setting.setValue("sourcefile", self.syslogfile) setting.setValue("filter", self.__sFilter) setting.setValue("ServerIP", self.__ServerIP) def setUI(self): self.leSourceFile.setText(self.syslogfile) self.leFilter.setText(self.__sFilter) self.leServerIP.setText(self.__ServerIP) @pyqtSlot() def setFilter(self): t = self.leFilter.text() self.__sFilter = t @pyqtSlot() def setServerIP(self): t = self.leServerIP.text() self.__ServerIP = t @pyqtSlot(str) def logHandle(self, msg): if msg: m = msg.strip() if self.__sFilter in m: self.ifound = self.ifound + 1 if self.ifound == self.iIgnore: #ignore this pass elif self.ifound <= self.iTotalCount: self.log.append("%s================> %s" % (self.ifound, m)) # rs = m.split("kernel: ") if len(rs) == 2: self.addData(self.ifound, rs[1]) else: self.ifound = 0 self.currentPhase = self.currentPhase + 1 # issue command to xmlrpcserver (_Proxy) if self.currentPhase < len(self.phase): print("current phase %s" % self.currentPhase) if not self._Proxy: self.connectServerProxy() if self._Proxy: print("send phase to proxy: %s" % self.phase[self.currentPhase]) self._Proxy.setPathb_phase( self.phase[self.currentPhase]) else: self.abort_workers() self.log.append( "********************FINISH**************************" ) else: self.log.append(m) def clearData(self): btnReply = QMessageBox.question(self, 'Notice', "All data will be delete, continus?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if btnReply == QMessageBox.Yes: self.twData.clearContents() self.twData.setRowCount(0) def saveData(self): filename, _filter = QFileDialog.getSaveFileName( self, 'Save File', '', 'CSV(*.csv)') print("path: %s" % filename) if filename is not "": self.log.append("#################save data###################") with open(filename, 'w') as stream: writer = csv.writer(stream, delimiter=',') for row in range(self.twData.rowCount()): rowdata = [] for column in range(self.twData.columnCount()): item = self.twData.item(row, column) if item is not None: rowdata.append("%s" % item.text()) else: rowdata.append('') self.log.append("%s = %s" % (row, rowdata)) writer.writerow(rowdata) self.log.append("rowdata: %s" % rowdata) def addData(self, idx, m): iRow = self.twData.rowCount() #print("row %s" % iRow) self.twData.setRowCount(iRow + 1) newItem = QTableWidgetItem(self.phase[self.currentPhase]) self.twData.setItem(iRow, twDataCol['phase'], newItem) # newItem = QTableWidgetItem(str(idx)) self.twData.setItem(iRow, twDataCol['idx'], newItem) # newItem = QTableWidgetItem(m) self.twData.setItem(iRow, twDataCol['data'], newItem) @pyqtSlot() def selectSource(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self, "select source", os.path.join( "/", "var", "log"), "All Files (*)", options=options) if fileName: self.leSourceFile.setText(fileName) def startRsyslog(self, act): if act: #start cmd = shlex.split("sudo service rsyslog start") else: cmd = shlex.split("sudo service rsyslog stop") rs = "" try: rs = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False) except subprocess.CalledProcessError: print('startRsyslog Exception: %s' % cmd) return rs def reInitRsyslog(self): #stop rsyslog self.startRsyslog(False) #backup /var/log/syslog bakFile = datetime.now().strftime("%Y-%m-%d_%H%M%S") os.rename(self.syslogfile, "%s_%s" % (self.syslogfile, bakFile)) #start rsyslog self.startRsyslog(True) def saveEVPathSignal(self): filename, _filter = QFileDialog.getSaveFileName( self, 'Save File', '', 'CSV(*.csv)') print("path: %s" % filename) if filename is not "": #self.log.append("#################save data###################") with open(filename, 'w') as stream: writer = csv.writer(stream, delimiter=',') #header hdata = [] for column in range(self.twSignal.columnCount()): itm = self.twSignal.horizontalHeaderItem(column) if itm is not None: hdata.append("%s" % itm.text()) writer.writerow(hdata) for row in range(self.twSignal.rowCount()): rowdata = [] for column in range(self.twSignal.columnCount()): item = self.twSignal.item(row, column) if item is not None: rowdata.append("%s" % item.text()) else: rowdata.append('') #self.log.append("%s = %s" %(row, rowdata)) writer.writerow(rowdata) #self.log.append("rowdata: %s" % rowdata) @pyqtSlot() def startEVPathSignal(self): self.pbEVPathSignal.setEnabled(False) self.pbSaveEVPathSignal.setEnabled(False) #self.addSignalResult(0,0,"123") #return att1 = self.devices[0] att2 = self.devices[1] ip = self.leIP.text() username = self.leUserName.text() password = self.lePassword.text() shell = spur.SshShell(hostname=ip, username=username, password=password, missing_host_key=spur.ssh.MissingHostKey.accept) rssi_path = self.leRSSI.text() iRow = self.twAtt.rowCount() if iRow == 2: itm1 = self.twAtt.item(0, 0) if not itm1: itm1 = QTableWidgetItem(att1) itm1.setText(str(self.att.getSerialNumber(att1))) self.twAtt.setItem(0, 0, itm1) itm2 = self.twAtt.item(1, 0) if not itm2: itm2 = QTableWidgetItem(att2) itm2.setText(str(self.att.getSerialNumber(att2))) self.twAtt.setItem(1, 0, itm2) att1Start = self.twAtt.item(0, 1) att1Stop = self.twAtt.item(0, 2) att1Step = self.twAtt.item(0, 3) #att2Start = self.twAtt.item(1,1) att2Stop = self.twAtt.item(1, 2) att2Step = self.twAtt.item(1, 3) for vAtt1 in range(int(att1Start.text()), int(att1Stop.text()), int(att1Step.text())): #set patha, self.att.setValue(att1, "Attenuation", vAtt1) att2Start = vAtt1 for vAtt2 in range(att2Start, int(att2Stop.text()), int(att2Step.text())): #set pathb self.att.setValue(att2, "Attenuation", vAtt2) #get RSSI,SNR 10 times for i in range(10): result = "" #with shell: print("cat %s" % rssi_path) result = shell.run(["cat", rssi_path]) #print("%s - %s: %s" % (vAtt1, vAtt2, result)) curRow = self.twSignal.rowCount() self.addSignalResult(curRow, 0, vAtt1) self.addSignalResult(curRow, 1, vAtt2) #RSSI1, RSSI2, SNR1, SNR2 if result.return_code == 0: rs = result.output.decode() r = rs.split(",") self.addSignalResult(curRow, 2, r[0]) self.addSignalResult(curRow, 3, r[1]) self.addSignalResult(curRow, 4, r[2]) self.addSignalResult(curRow, 5, r[3].rsplit()[0]) else: rs = result.stderr_output self.addSignalResult(curRow, 2, rs) QApplication.processEvents() time.sleep(1) #wait 1 sec QApplication.processEvents() QApplication.processEvents() self.pbEVPathSignal.setEnabled(True) self.pbSaveEVPathSignal.setEnabled(True) def addSignalResult(self, row, col, val): iRow = self.twSignal.rowCount() if iRow <= row: self.twSignal.setRowCount(row + 1) itm = self.twSignal.item(row, col) if not itm: itm = QTableWidgetItem(0) #print("addSignalResult: %s = %s" % (itm,val)) itm.setText(str(val)) self.twSignal.setItem(row, col, itm) @pyqtSlot() def startDirectBF(self): '''test direct BF''' shell = spur.SshShell(hostname="192.168.110.239", username="******", password="******") #TODO: loop test? with shell: result = shell.run( ["cat", "/proc/net/rtl88x2bu/wlan3/rate_search"]) print(result) # 1. trigger rate search result = shell.run( ["echo", "1", ">", "/proc/net/rtl88x2bu/wlan3/rate_search"]) #start ping process = shell.spawn( ["sudo", "alpha_ping", "-n 1300", "192.168.0.20"], store_pid=True) #wait finish search (2min) ''' waittime=0 while proc.is_running(): print(".") time.sleep(1) waittime=waittime+1 ''' result = process.wait_for_result() print(result.output) print("wait search finish") result = shell.run( ["cat", "/proc/net/rtl88x2bu/wlan3/rate_search"]) while "=1" in result.decode(): print(".") time.sleep(5) result = shell.run( ["cat", "/proc/net/rtl88x2bu/wlan3/rate_search"]) # 2. record rate_search_result, pathb_phase result = shell.run( ["cat", "/proc/net/rtl88x2bu/wlan3/rate_search_result"]) print("search_result: %s" % result) result = shell.run( ["cat", "/proc/net/rtl88x2bu/wlan3/pathb_phase"]) print("pathb_phase: %s" % result) # 3. start throughput test (TODO: each att?) # 4. loop 1~3 for 5 times @pyqtSlot() def start_threads(self): self.log.append('starting {} threads'.format(self.NUM_THREADS)) self.updateUIbtn(False) self.currentPhase = 0 self.phase = self.lePhase.text().split(',') self.ifound = 0 self.iIgnore = self.sbIgnore.value() self.iTotalCount = self.sbCount.value() + self.iIgnore #re-init rsyslog : clear previous result! self.reInitRsyslog() self.__workers_done = 0 self.__threads = [] for idx in range(self.NUM_THREADS): print("self.syslogfile: %s" % self.syslogfile) worker = log_viewer(idx, self.syslogfile) thread = MyThread() thread.setObjectName('thread_' + str(idx)) self.__threads.append( (thread, worker)) # need to store worker too otherwise will be gc'd worker.moveToThread(thread) # get progress messages from worker: #worker.sig_step.connect(self.on_worker_step) worker.sig_done.connect(self.on_worker_done) worker.sig_msg.connect(self.logHandle) # control worker: self.sig_abort_workers.connect(worker.abort) # get read to start worker: # self.sig_start.connect(worker.work) # needed due to PyCharm debugger bug (!); comment out next line thread.started.connect(worker.work) thread.start( ) # this will emit 'started' and start thread's event loop #issue first command if self._Proxy: self._Proxy.setRate_ctl(self.leRateCtl.text()) self._Proxy.setPathb_phase(self.phase[self.currentPhase]) def startServer(self): #xmlrpcserver if not self.myService: self.myService = myServiceServer(self.leServerIP.text(), self.sbPort.value()) self.myService.register_function(self.setPathb_phase) self.myService.register_function(self.setRate_ctl) self.myService.register_function(self.getPathb_phase) self.myService.start() self.pbBind.setEnabled(False) def connectServerProxy(self): try: print("connectServerProxy") self._Proxy = ServerProxy('http://%s:%s' % (self.__ServerIP, self.sbPort.value())) print("connectServerProxy: %s" % self._Proxy) except Exception as err: print("A fault occurred: %s" % type(err)) print(err) #print("Fault code: %d" % err.faultCode) #print("Fault string: %s" % err.faultString) if self._Proxy: self.log.append("%s" % self._Proxy.system.listMethods()) def testPathbPhase(self): if not self._Proxy: self.connectServerProxy() phase = self.cbPhase.currentText() self.log.append("set PathbPhase = %s (%s)" % (phase, type(phase))) self._Proxy.setPathb_phase(phase) rs = self._Proxy.getPathb_phase() self.log.append("getPathb_phase = %s" % rs) def testRateCtl(self): if not self._Proxy: self.connectServerProxy() rate = self.cbRateCtl.currentText() self._Proxy.setRate_ctl(rate) rs = self._Proxy.getRate_ctl() self.log.append("testRateCtl = %s" % rs) def setRate_ctl(self, rate): #echo 0x2C > /proc/net/rtl88x2bu/wlan3/rate_ctl ;cat /proc/net/rtl88x2bu/wlan3/rate_ctl path = self.leRateCtlPath.text() f = open(path, 'w') f.write('%s' % rate) f.close() def getRate_ctl(self): path = self.leRateCtlPath.text() f = open(path, 'r') r = f.readline() print("%s" % r) f.close() def setPathb_phase(self, phase): #echo 0 > /proc/net/rtl88x2bu/wlan3/pathb_phase; cat /proc/net/rtl88x2bu/wlan3/pathb_phase ;cat /proc/net/rtl88x2bu/wlan3/rate_ctl pPath = self.lePathbPhasePath.text() f = open(pPath, 'w') print("write %s with %s " % (pPath, phase)) f.write('%s' % phase) f.close() def getPathb_phase(self): #echo 0 > /proc/net/rtl88x2bu/wlan3/pathb_phase; cat /proc/net/rtl88x2bu/wlan3/pathb_phase ;cat /proc/net/rtl88x2bu/wlan3/rate_ctl #rPath = self.leRateCtlPath.text() pPath = self.lePathbPhasePath.text() #cmd = shlex.split('echo %s > %s; cat %s; cat %s' % (phase, pPath, pPath, rPath )) cmd = shlex.split('cat %s ' % (pPath)) try: rs = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False) except subprocess.CalledProcessError: print('setPathb_phase Exception: %s' % cmd) return rs def updateUIbtn(self, e): self.pbStartThread.setEnabled(e) self.pbStopThread.setEnabled(not e) self.setDisableUI(not e) @pyqtSlot(int, int) def on_worker_done(self, worker_id, errCode): print("worker_id: %s %s" % (worker_id, errCode)) #self.__workers_done += 1 #if self.__workers_done == self.NUM_THREADS: # self.log.append('No more workers active') self.updateUIbtn(True) self.log.append('worker #{} done %s'.format(worker_id, errCode)) @pyqtSlot() def abort_workers(self): self.sig_abort_workers.emit() self.log.append('Asking each worker to abort') for thread, worker in self.__threads: # note nice unpacking by Python, avoids indexing thread.quit( ) # this will quit **as soon as thread event loop unblocks** thread.wait() # <- so you need to wait for it to *actually* quit # even though threads have exited, there may still be messages on the main thread's # queue (messages that threads emitted before the abort): self.log.append('All threads exited') self.updateUIbtn(True) def setDisableUI(self, e): self.widgetFilter.setEnabled(not e) self.widgetCmd.setEnabled(not e)
def settings(name): """Returns a QSettings object referring a file in ~/.config/frescobaldi/""" s = QSettings() s.beginGroup(name) s.setFallbacksEnabled(False) return s
class SettingsWrapper(types.ModuleType): # For easier auto-complete in IDE, add each new setting to settings.pyi stub # TODO: automatic stub file generator # List of possible settings. key[0] is the type, key[1] is the default value _possible_settings = { 'WIDTH': (int, 640), 'S_FIELD_HEIGHT': (int, 40), 'RESULTS_HEIGHT': (int, 300), 'ANIMATION_DURATION': (int, 250), 'SEARCH_DELAY': (int, 150), 'PLACEHOLDER_CHANGE_TIME': (int, 2000), 'BACKGROUND_COLOR': (str, '#F6F6F6'), 'SEPARATOR_COLOR': (str, '#DFDFDF'), 'SCREEN_NUM': (int, -1 ), # -1 means show app on screen where the mouse cursor currently is 'SOUNDS_ENABLED': (bool, True), 'ANIMATIONS_ENABLED': (bool, True), 'GLOBAL_HOTKEY_ENABLED': (bool, True) } # Generate runtime settings # For example paths, which should not be stored in settings ini _base_path = Path(__file__).parent.parent.parent _res_path = _base_path / 'res' _icon_path = _res_path / 'icons' _settings_path = _base_path / 'settings.ini' _plugins_path = _base_path / 'plugins' _runtime_settings = { 'BASE_PATH': _base_path, 'RES_PATH': _res_path, 'ICON_PATH': _icon_path, 'SETTINGS_PATH': _settings_path, 'PLUGINS_PATH': _plugins_path } # TODO: Logging @staticmethod def log(*whatever): print(whatever) # Resources def icon_path(self, name) -> str: return str(self.ICON_PATH / (name + '.png')) def icon(self, name) -> QIcon: return QIcon(self.icon_path(name)) # Reset settings to default def reset_settings(self): for k, v in self._possible_settings.items(): self._qsettings.setValue(k, v[1]) self._qsettings.sync() # Sync settings def sync(self): self._qsettings.sync() def __init__(self, wrapped): self._wrapped = wrapped self._runtime = [ x for x in dir(self._runtime_settings) if not x.startswith('_') ] # QSettings setup QCoreApplication.setOrganizationName('the-lay') QCoreApplication.setOrganizationDomain('gubins.lv') QCoreApplication.setApplicationName('Highlight') QCoreApplication.setApplicationVersion('0.0.5') self._qsettings = QSettings(str(self.SETTINGS_PATH), QSettings.IniFormat) self._qsettings.setFallbacksEnabled(False) # Check if all possible settings are in ini # If not, write new ones for key, def_val in self._possible_settings.items(): if key not in self._qsettings.allKeys(): print(key, 'is not in qsettings, adding it now') self._qsettings.setValue(key, def_val[1]) # Get/set settings def __setitem__(self, key, value): if key in self._runtime: raise AttributeError('Key ' + key + ' is generated at runtime and is read-only.') if key in self._possible_settings: return self._qsettings.setValue(key, value) else: raise AttributeError('Key ' + key + ' is not one of the possible settings.') def __getitem__(self, key): # if asked for one of the runtime generated settings if key in self._runtime_settings: return self._runtime_settings[key] try: return self._qsettings.value(key, type=self._possible_settings[key][0]) except AttributeError: self.log('Can\'t find setting', key) # Make it iterable def keys(self): return list(self._runtime_settings.keys()) + self._qsettings.allKeys() # Delegate uppercase attribute requests to getter def __getattribute__(self, item: str): # if requested attr starts with uppercase, then it is one of the settings if item[0].isupper(): return self[item] return super().__getattribute__(item)
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import pyqtSlot, QPoint, QSettings, QRect, QTimer, QVariant, QPoint import time list_data = [1, 2, 3, 5] list_data_default = [0, 0, 0, 0] float_value = 321.321123 p = QPoint(1, 2) setting_file = 'isp_default_test.ini' settings = QSettings(setting_file, QSettings.IniFormat) settings.setFallbacksEnabled( False) # File only, no fallback to registry or or. a = QVariant(123) b = QVariant(231) # settings.beginGroup('isp_default_parameter_values') # settings.setValue('qp', p) # settings.setValue('status', True) # settings.setValue('int_value', 321) # settings.setValue('float_value', float_value) # settings.setValue('leve1/int_value', 567) # settings.setValue('list_value', list_data) # settings.endGroup() # settings.sync() time.sleep(1) settings.beginGroup('isp_default_parameter_values') set_bool_qp = settings.value('qp', QPoint(1, 1)) set_bool = settings.value('status', False)