Ejemplo n.º 1
0
class AboutDialog(QDialog):  # pylint: disable=too-many-instance-attributes
    """Logic for managing about box"""
    def __init__(self, parent, app_settings):
        super().__init__(parent)
        self._log = logging.getLogger(__name__)
        self._settings = QSettings()
        self._app_settings = app_settings
        self._load_ui()
        # Flag indicating whether the user has requested the GUI settings to be reset.
        # If so, the caller should disable any further settings recording logic
        self.cleared = False

    def _load_ui(self):
        """Internal helper method that configures the UI for the dialog"""
        load_ui("about_dlg.ui", self)

        self.title_label = self.findChild(QLabel, "title_label")
        self.title_label.setText(f"Friendly Pics 2 v{__version__}")

        self.runtime_env_label = self.findChild(QLabel, "runtime_env_label")
        if is_mac_app_bundle():
            self.runtime_env_label.setText("Running as MacOS app bundle")
        elif is_pyinstaller_bundle():
            self.runtime_env_label.setText("Running as a pyinstaller binary")
        else:
            self.runtime_env_label.setText(
                "Running under conventional Python environment")

        self.gui_settings_label = self.findChild(QLabel, "gui_settings_label")
        self.gui_settings_label.setText(
            f"<b>GUI Settings:</b> {self._settings.fileName()}")

        self.gui_settings_clear_button = self.findChild(
            QPushButton, "gui_settings_clear_button")
        self.gui_settings_clear_button.clicked.connect(
            self._clear_gui_settings)

        self.app_settings_label = self.findChild(QLabel, "app_settings_label")
        self.app_settings_label.setText(
            f"<b>App Settings:</b> {self._app_settings.path}")

        # Center the about box on the parent window
        parent_geom = self.parent().geometry()
        self.move(parent_geom.center() - self.rect().center())

    @Slot()
    def _clear_gui_settings(self):
        """Callback for when user selects the clear gui settings button"""
        self._settings.clear()
        self._settings.sync()
        self.gui_settings_clear_button.setEnabled(False)
        self.cleared = True
Ejemplo n.º 2
0
class Config(QObject):
    "Configuration provider for the whole program, wrapper for QSettings"

    row_height_changed = Signal(int)

    def __init__(self, log=None):
        super().__init__()
        if log:
            self.log = log.getChild('Conf')
            self.log.setLevel(30)
        else:
            self.log = logging.getLogger()
            self.log.setLevel(99)
        self.log.debug('Initializing')
        self.qsettings = QSettings()
        self.qsettings.setIniCodec('UTF-8')

        self.options = None
        self.option_spec = self.load_option_spec()
        self.options = self.load_options()
        self.full_name = "{} {}".format(QCoreApplication.applicationName(),
                                        QCoreApplication.applicationVersion())

        # options that need fast access are also defined as attributes, which
        # are updated by calling update_attributes()
        # (on paper it's 4 times faster, but I don't think it matters in my case)
        self.logger_table_font = None
        self.logger_table_font_size = None
        self.logger_row_height = None
        self.benchmark_interval = None

        self.update_attributes()

    def post_init(self):
        running_version = StrictVersion(QCoreApplication.applicationVersion())
        config_version = self.options['cutelog_version']
        if config_version == "" or config_version != running_version:
            self.save_running_version()

    def __getitem__(self, name):
        # self.log.debug('Getting "{}"'.format(name))
        value = self.options.get(name)
        if value is None:
            raise Exception('No option with name "{}"'.format(name))
        # self.log.debug('Returning "{}"'.format(value))
        return value

    def __setitem__(self, name, value):
        # self.log.debug('Setting "{}"'.format(name))
        if name not in self.options:
            raise Exception('No option with name "{}"'.format(name))
        self.options[name] = value

    def set_option(self, name, value):
        self[name] = value
        self.qsettings.beginGroup('Configuration')
        self.qsettings.setValue(name, value)
        self.qsettings.endGroup()

    @staticmethod
    def get_resource_path(name, directory='ui'):
        data_dir = resource_filename('cutelog', directory)
        path = os.path.join(data_dir, name)
        if not os.path.exists(path):
            raise FileNotFoundError('Resource file not found in this path: "{}"'.format(path))
        return path

    def get_ui_qfile(self, name):
        file = QFile(':/ui/{}'.format(name))
        if not file.exists():
            raise FileNotFoundError('ui file not found: ":/ui/{}"'.format(name))
        file.open(QFile.ReadOnly)
        return file

    @property
    def listen_address(self):
        host = self.options.get('listen_host')
        port = self.options.get('listen_port')
        if host is None or port is None:
            raise Exception('Listen host or port not in options: "{}:{}"'.format(host, port))
        return (host, port)

    def load_option_spec(self):
        option_spec = []
        for spec in OPTION_SPEC:
            option = Option(*spec)
            option_spec.append(option)
        return option_spec

    def load_options(self):
        self.log.debug('Loading options')
        options = {}
        self.qsettings.beginGroup('Configuration')
        for option in self.option_spec:
            value = self.qsettings.value(option.name, option.default)
            if option.type == bool:
                value = str(value).lower()  # needed because QSettings stores bools as strings
                value = True if value == "true" or value is True else False
            elif option.type == int and value is None:
                value = 0  # workaround for bug PYSIDE-820
            else:
                try:
                    value = option.type(value)
                except Exception:
                    self.log.warn('Could not parse value "{}" for option "{}", falling back to the '
                                  'default value "{}"'.format(value, option.name, option.default))
                    value = option.default
            options[option.name] = value
        self.qsettings.endGroup()
        return options

    def update_options(self, new_options, save=True):
        self.emit_needed_changes(new_options)
        self.options.update(new_options)
        if save:
            self.save_options()
        self.update_attributes(new_options)

    def update_attributes(self, options=None):
        "Updates fast attributes and everything else outside of self.options"
        if options is None:
            options = self.options

        self.benchmark_interval = options.get('benchmark_interval', self.benchmark_interval)
        self.logger_table_font = options.get('logger_table_font', self.logger_table_font)
        self.logger_table_font_size = options.get('logger_table_font_size', self.logger_table_font_size)
        self.logger_row_height = options.get('logger_row_height', self.logger_row_height)
        self.set_logging_level(options.get('console_logging_level', ROOT_LOG.level))

    def emit_needed_changes(self, new_options):
        new_row_height = new_options.get('logger_row_height')
        old_row_height = self.options.get('logger_row_height')
        if new_row_height != old_row_height:
            self.logger_row_height = new_row_height
            self.row_height_changed.emit(new_row_height)

    def save_options(self, sync=False):
        self.log.debug('Saving options')
        self.qsettings.beginGroup('Configuration')
        for option in self.option_spec:
            self.qsettings.setValue(option.name, self.options[option.name])
        self.qsettings.endGroup()
        if sync:  # syncing is probably not necessary here, so the default is False
            self.sync()

    def sync(self):
        self.log.debug('Syncing QSettings')
        self.qsettings.sync()

    def set_settings_value(self, name, value):
        self.qsettings.beginGroup('Configuration')
        self.qsettings.setValue(name, value)
        self.qsettings.endGroup()

    def set_logging_level(self, level):
        global ROOT_LOG
        ROOT_LOG.setLevel(level)
        self.log.setLevel(level)

    def get_levels_presets(self):
        self.qsettings.beginGroup('Levels_Presets')
        result = self.qsettings.childGroups()
        self.qsettings.endGroup()
        return result

    def save_levels_preset(self, name, levels):
        self.log.debug('Saving levels preset "{}"'.format(name))
        s = self.qsettings
        s.beginGroup('Levels_Presets')
        s.beginWriteArray(name, len(levels))
        for i, levelname in enumerate(levels):
            level = levels[levelname]
            s.setArrayIndex(i)
            dump = level.dumps()
            s.setValue('level', dump)
        s.endArray()
        s.endGroup()

    def load_levels_preset(self, name):
        from .log_levels import LogLevel
        self.log.debug('Loading levels preset "{}"'.format(name))
        s = self.qsettings
        if name not in self.get_levels_presets():
            return None
        s.beginGroup('Levels_Presets')
        size = s.beginReadArray(name)
        result = {}
        for i in range(size):
            s.setArrayIndex(i)
            new_level = LogLevel(None).loads(s.value('level'))
            result[new_level.levelname] = new_level
        s.endArray()
        s.endGroup()
        return result

    def delete_levels_preset(self, name):
        s = self.qsettings
        s.beginGroup('Levels_Presets')
        s.remove(name)
        s.endGroup()

    def get_header_presets(self):
        self.qsettings.beginGroup('Header_Presets')
        result = self.qsettings.childGroups()
        self.qsettings.endGroup()
        return result

    def save_header_preset(self, name, columns):
        self.log.debug('Saving header preset "{}"'.format(name))
        s = self.qsettings
        s.beginGroup('Header_Presets')
        s.beginWriteArray(name, len(columns))
        for i, col in enumerate(columns):
            s.setArrayIndex(i)
            # read the comment in Column.dumps() for reasoning
            if i == len(columns) - 1:
                col.width = 10
                # dump = col.dumps(width=10)
            dump = col.dumps()
            s.setValue('column', dump)
        s.endArray()
        s.endGroup()

    def load_header_preset(self, name):
        from .logger_table_header import Column
        self.log.debug('Loading header preset "{}"'.format(name))
        s = self.qsettings
        if name not in self.get_header_presets():
            return None
        s.beginGroup('Header_Presets')
        size = s.beginReadArray(name)
        result = []
        for i in range(size):
            s.setArrayIndex(i)
            new_column = Column().loads(s.value('column'))
            result.append(new_column)
        s.endArray()
        s.endGroup()
        return result

    def delete_header_preset(self, name):
        s = self.qsettings
        s.beginGroup('Header_Presets')
        s.remove(name)
        s.endGroup()

    def save_geometry(self, geometry):
        s = self.qsettings
        s.beginGroup('Geometry')
        s.setValue('Main_Window_Geometry', geometry)
        s.endGroup()
        self.sync()

    def load_geometry(self):
        s = self.qsettings
        s.beginGroup('Geometry')
        geometry = s.value('Main_Window_Geometry')
        s.endGroup()
        return geometry

    def save_running_version(self):
        version = QCoreApplication.applicationVersion()
        self.log.debug("Updating the config version to {}".format(version))
        s = self.qsettings
        s.beginGroup('Configuration')
        s.setValue('cutelog_version', version)
        self.options['cutelog_version'] = version
        s.endGroup()
        self.sync()

    def restore_defaults(self):
        self.qsettings.clear()
        self.sync()
Ejemplo n.º 3
0
 def setUp(self):
     settings = QSettings()
     settings.clear()
Ejemplo n.º 4
0
 def tearDown(self):
     settings = QSettings()
     settings.clear()
     rmtree(dirname(settings.fileName()))
Ejemplo n.º 5
0
 def clear_settings(self):
     settings = QSettings("QtGuiApplication", "%s_%s" % (self.app_name, self.__class__.__name__))
     settings.clear()