From c64a5eae9b476421d7affbb512af618e90d084aa Mon Sep 17 00:00:00 2001 From: tzutalin Date: Tue, 8 Aug 2017 05:10:34 +0800 Subject: [PATCH] Refactor settings class --- .gitignore | 1 + Makefile | 3 ++ labelImg.py | 101 ++++++++--------------------------------- libs/settings.py | 32 +++++++++++++ tests/test_settings.py | 25 ++++++++++ 5 files changed, 80 insertions(+), 82 deletions(-) create mode 100644 libs/settings.py create mode 100644 tests/test_settings.py diff --git a/.gitignore b/.gitignore index 278fd72d..63633bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ cscope* .ycm_extra_conf.py .subvimrc .vscode +*.pkl diff --git a/Makefile b/Makefile index d5ee0935..7488c40e 100644 --- a/Makefile +++ b/Makefile @@ -23,4 +23,7 @@ qt4py3: qt5py3: pyrcc5 -o resources.py resources.qrc +clean: + rm -f .settings.pkl resources.pyc + .PHONY: test diff --git a/labelImg.py b/labelImg.py index 6303a319..f9c1158f 100755 --- a/labelImg.py +++ b/labelImg.py @@ -28,6 +28,7 @@ import resources # Add internal libs from libs.constants import * from libs.lib import struct, newAction, newIcon, addActions, fmtShortcut +from libs.settings import Settings from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR from libs.canvas import Canvas from libs.zoomWidget import ZoomWidget @@ -397,40 +398,10 @@ class MainWindow(QMainWindow, WindowMixin): # Load predefined classes to the list self.loadPredefinedClasses(defaultPrefdefClassFile) - # XXX: Could be completely declarative. - # Restore application settings. - if have_qstring(): - types = { - SETTING_FILENAME: QString, - SETTING_RECENT_FILES: QStringList, - SETTING_WIN_SIZE: QSize, - SETTING_WIN_POSE: QPoint, - SETTING_WIN_GEOMETRY: QByteArray, - SETTING_LINE_COLOR: QColor, - SETTING_FILL_COLOR: QColor, - SETTING_ADVANCE_MODE: bool, - # Docks and toolbars: - SETTING_WIN_STATE: QByteArray, - SETTING_SAVE_DIR: QString, - SETTING_LAST_OPEN_DIR: QString, - } - else: - types = { - SETTING_FILENAME: str, - SETTING_RECENT_FILES: list, - SETTING_WIN_SIZE: QSize, - SETTING_WIN_POSE: QPoint, - SETTING_WIN_GEOMETRY: QByteArray, - SETTING_LINE_COLOR: QColor, - SETTING_FILL_COLOR: QColor, - SETTING_ADVANCE_MODE: bool, - # Docks and toolbars: - SETTING_WIN_STATE: QByteArray, - SETTING_SAVE_DIR: str, - SETTING_LAST_OPEN_DIR: str, - } - self.settings = settings = Settings(types) + self.settings = Settings() + self.settings.load() + settings = self.settings ## Fix the compatible issue for qt4 and qt5. Convert the QStringList to python list if settings.get(SETTING_RECENT_FILES): @@ -1005,30 +976,31 @@ class MainWindow(QMainWindow, WindowMixin): def closeEvent(self, event): if not self.mayContinue(): event.ignore() - s = self.settings + settings = self.settings # If it loads images from dir, don't load it at the begining if self.dirname is None: - s[SETTING_FILENAME] = self.filePath if self.filePath else '' + settings[SETTING_FILENAME] = self.filePath if self.filePath else '' else: - s[SETTING_FILENAME] = '' + settings[SETTING_FILENAME] = '' - s[SETTING_WIN_SIZE] = self.size() - s[SETTING_WIN_POSE] = self.pos() - s[SETTING_WIN_STATE] = self.saveState() - s[SETTING_LINE_COLOR] = self.lineColor - s[SETTING_FILL_COLOR] = self.fillColor - s[SETTING_RECENT_FILES] = self.recentFiles - s[SETTING_ADVANCE_MODE] = not self._beginner + settings[SETTING_WIN_SIZE] = self.size() + settings[SETTING_WIN_POSE] = self.pos() + settings[SETTING_WIN_STATE] = self.saveState() + settings[SETTING_LINE_COLOR] = self.lineColor + settings[SETTING_FILL_COLOR] = self.fillColor + settings[SETTING_RECENT_FILES] = self.recentFiles + settings[SETTING_ADVANCE_MODE] = not self._beginner if self.defaultSaveDir is not None and len(self.defaultSaveDir) > 1: - s[SETTING_SAVE_DIR] = ustr(self.defaultSaveDir) + settings[SETTING_SAVE_DIR] = ustr(self.defaultSaveDir) else: - s[SETTING_SAVE_DIR] = "" + settings[SETTING_SAVE_DIR] = "" if self.lastOpenDir is not None and len(self.lastOpenDir) > 1: - s[SETTING_LAST_OPEN_DIR] = self.lastOpenDir + settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir else: - s[SETTING_LAST_OPEN_DIR] = "" + settings[SETTING_LAST_OPEN_DIR] = "" + settings.save() ## User Dialogs ## def loadRecent(self, filename): @@ -1314,41 +1286,6 @@ class MainWindow(QMainWindow, WindowMixin): self.canvas.verified = tVocParseReader.verified -class Settings(object): - """Convenience dict-like wrapper around QSettings.""" - - def __init__(self, types=None): - self.data = QSettings() - self.types = defaultdict(lambda: QVariant, types if types else {}) - - def __setitem__(self, key, value): - t = self.types[key] - self.data.setValue(key, - t(value) if not isinstance(value, t) else value) - - def __getitem__(self, key): - return self._cast(key, self.data.value(key)) - - def get(self, key, default=None): - return self._cast(key, self.data.value(key, default)) - - def _cast(self, key, value): - # XXX: Very nasty way of converting types to QVariant methods :P - t = self.types.get(key) - if t is not None and t != QVariant: - if t is str: - return ustr(value) - else: - try: - method = getattr(QVariant, re.sub( - '^Q', 'to', t.__name__, count=1)) - return method(value) - except AttributeError as e: - # print(e) - return value - return value - - def inverted(color): return QColor(*[255 - v for v in color.getRgb()]) diff --git a/libs/settings.py b/libs/settings.py new file mode 100644 index 00000000..3efe5d53 --- /dev/null +++ b/libs/settings.py @@ -0,0 +1,32 @@ +import pickle +import os + +class Settings(object): + def __init__(self): + self.data = {} + self.path = '.settings.pkl' + + def __setitem__(self, key, value): + self.data[key] = value + + def __getitem__(self, key): + return self.data[key] + + def get(self, key, default=None): + if key in self.data: + return self.data[key] + return default + + def save(self): + with open(self.path, 'wb') as f: + pickle.dump(self.data, f, pickle.HIGHEST_PROTOCOL) + return True + return False + + def load(self): + if os.path.exists(self.path): + with open(self.path, 'rb') as f: + self.data = pickle.load(f) + return True + return False + diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 00000000..a89ab435 --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +from unittest import TestCase +import time +import sys +import os +__author__ = 'TzuTaLin' + +dir_name = os.path.abspath(os.path.dirname(__file__)) +libs_path = os.path.join(dir_name, '..', 'libs') +sys.path.insert(0, libs_path) +from settings import Settings + +class TestSettings(TestCase): + + def test_basic(self): + wSetting = Settings() + wSetting['test0'] = 'hello' + wSetting['test1'] = 10 + wSetting['test2'] = [0, 2, 3] + self.assertEqual(wSetting.get('test3', 3), 3) + self.assertEqual(wSetting.save(), True) + + +if __name__ == '__main__': + unittest.main()