diff --git a/core/engine.py b/core/engine.py index 1b748ef6..aaabeb8c 100644 --- a/core/engine.py +++ b/core/engine.py @@ -17,7 +17,11 @@ from hscommon.util import flatten, multi_replace from hscommon.trans import tr from hscommon.jobprogress import job -(WEIGHT_WORDS, MATCH_SIMILAR_WORDS, NO_FIELD_ORDER,) = range(3) +( + WEIGHT_WORDS, + MATCH_SIMILAR_WORDS, + NO_FIELD_ORDER, +) = range(3) JOB_REFRESH_RATE = 100 @@ -34,11 +38,9 @@ def getwords(s): # of their accents, etc.) are preserved as is. The arbitrary limit is # obtained from this one: ord("\u037e") GREEK QUESTION MARK s = "".join( - c for c in s - if (ord(c) <= 894 - and c in string.ascii_letters + string.digits + string.whitespace - ) - or ord(c) > 894 + c + for c in s + if (ord(c) <= 894 and c in string.ascii_letters + string.digits + string.whitespace) or ord(c) > 894 ) return [_f for _f in s.split(" ") if _f] # remove empty elements @@ -115,9 +117,7 @@ def compare_fields(first, second, flags=()): if matched_field: second.remove(matched_field) else: - results = [ - compare(field1, field2, flags) for field1, field2 in zip(first, second) - ] + results = [compare(field1, field2, flags) for field1, field2 in zip(first, second)] return min(results) if results else 0 @@ -130,9 +130,7 @@ def build_word_dict(objects, j=job.nulljob): The result will be a dict with words as keys, lists of objects as values. """ result = defaultdict(set) - for object in j.iter_with_progress( - objects, "Prepared %d/%d files", JOB_REFRESH_RATE - ): + for object in j.iter_with_progress(objects, "Prepared %d/%d files", JOB_REFRESH_RATE): for word in unpack_fields(object.words): result[word].add(object) return result @@ -167,9 +165,7 @@ def reduce_common_words(word_dict, threshold): The exception to this removal are the objects where all the words of the object are common. Because if we remove them, we will miss some duplicates! """ - uncommon_words = set( - word for word, objects in word_dict.items() if len(objects) < threshold - ) + uncommon_words = set(word for word, objects in word_dict.items() if len(objects) < threshold) for word, objects in list(word_dict.items()): if len(objects) < threshold: continue @@ -275,10 +271,7 @@ def getmatches( # This is the place where the memory usage is at its peak during the scan. # Just continue the process with an incomplete list of matches. del compared # This should give us enough room to call logging. - logging.warning( - "Memory Overflow. Matches: %d. Word dict: %d" - % (len(result), len(word_dict)) - ) + logging.warning("Memory Overflow. Matches: %d. Word dict: %d" % (len(result), len(word_dict))) return result return result @@ -408,18 +401,13 @@ class Group: You can call this after the duplicate scanning process to free a bit of memory. """ - discarded = set( - m - for m in self.matches - if not all(obj in self.unordered for obj in [m.first, m.second]) - ) + discarded = set(m for m in self.matches if not all(obj in self.unordered for obj in [m.first, m.second])) self.matches -= discarded self.candidates = defaultdict(set) return discarded def get_match_of(self, item): - """Returns the match pair between ``item`` and :attr:`ref`. - """ + """Returns the match pair between ``item`` and :attr:`ref`.""" if item is self.ref: return for m in self._get_matches_for_ref(): @@ -435,8 +423,7 @@ class Group: """ # tie_breaker(ref, dupe) --> True if dupe should be ref # Returns True if anything changed during prioritization. - master_key_func = lambda x: (-x.is_ref, key_func(x)) - new_order = sorted(self.ordered, key=master_key_func) + new_order = sorted(self.ordered, key=lambda x: (-x.is_ref, key_func(x))) changed = new_order != self.ordered self.ordered = new_order if tie_breaker is None: @@ -459,9 +446,7 @@ class Group: self.unordered.remove(item) self._percentage = None self._matches_for_ref = None - if (len(self) > 1) and any( - not getattr(item, "is_ref", False) for item in self - ): + if (len(self) > 1) and any(not getattr(item, "is_ref", False) for item in self): if discard_matches: self.matches = set(m for m in self.matches if item not in m) else: @@ -470,8 +455,7 @@ class Group: pass def switch_ref(self, with_dupe): - """Make the :attr:`ref` dupe of the group switch position with ``with_dupe``. - """ + """Make the :attr:`ref` dupe of the group switch position with ``with_dupe``.""" if self.ref.is_ref: return False try: @@ -490,9 +474,7 @@ class Group: if self._percentage is None: if self.dupes: matches = self._get_matches_for_ref() - self._percentage = sum(match.percentage for match in matches) // len( - matches - ) + self._percentage = sum(match.percentage for match in matches) // len(matches) else: self._percentage = 0 return self._percentage @@ -547,12 +529,8 @@ def get_groups(matches): orphan_matches = [] for group in groups: orphan_matches += { - m - for m in group.discard_matches() - if not any(obj in matched_files for obj in [m.first, m.second]) + m for m in group.discard_matches() if not any(obj in matched_files for obj in [m.first, m.second]) } if groups and orphan_matches: - groups += get_groups( - orphan_matches - ) # no job, as it isn't supposed to take a long time + groups += get_groups(orphan_matches) # no job, as it isn't supposed to take a long time return groups diff --git a/core/results.py b/core/results.py index 14c27880..377a7313 100644 --- a/core/results.py +++ b/core/results.py @@ -106,9 +106,7 @@ class Results(Markable): self.groups, ) if self.__filtered_dupes: - self.__dupes = [ - dupe for dupe in self.__dupes if dupe in self.__filtered_dupes - ] + self.__dupes = [dupe for dupe in self.__dupes if dupe in self.__filtered_dupes] sd = self.__dupes_sort_descriptor if sd: self.sort_dupes(sd[0], sd[1], sd[2]) @@ -127,18 +125,10 @@ class Results(Markable): total_count = self.__total_count total_size = self.__total_size else: - mark_count = len( - [dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)] - ) - marked_size = sum( - dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe) - ) - total_count = len( - [dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)] - ) - total_size = sum( - dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe) - ) + mark_count = len([dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)]) + marked_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe)) + total_count = len([dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)]) + total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe)) if self.mark_inverted: marked_size = self.__total_size - marked_size result = tr("%d / %d (%s / %s) duplicates marked.") % ( @@ -201,11 +191,7 @@ class Results(Markable): self.__filters.append(filter_str) if self.__filtered_dupes is None: self.__filtered_dupes = flatten(g[:] for g in self.groups) - self.__filtered_dupes = set( - dupe - for dupe in self.__filtered_dupes - if filter_re.search(str(dupe.path)) - ) + self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(str(dupe.path))) filtered_groups = set() for dupe in self.__filtered_dupes: filtered_groups.add(self.get_group_of_duplicate(dupe)) @@ -217,8 +203,7 @@ class Results(Markable): self.__dupes = None def get_group_of_duplicate(self, dupe): - """Returns :class:`~core.engine.Group` in which ``dupe`` belongs. - """ + """Returns :class:`~core.engine.Group` in which ``dupe`` belongs.""" try: return self.__group_of_duplicate[dupe] except (TypeError, KeyError): @@ -284,8 +269,7 @@ class Results(Markable): self.is_modified = False def make_ref(self, dupe): - """Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group. - """ + """Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group.""" g = self.get_group_of_duplicate(dupe) r = g.ref if not g.switch_ref(dupe): @@ -412,10 +396,10 @@ class Results(Markable): """ if not self.__dupes: self.__get_dupe_list() - keyfunc = lambda d: self.app._get_dupe_sort_key( - d, lambda: self.get_group_of_duplicate(d), key, delta + self.__dupes.sort( + key=lambda d: self.app._get_dupe_sort_key(d, lambda: self.get_group_of_duplicate(d), key, delta), + reverse=not asc, ) - self.__dupes.sort(key=keyfunc, reverse=not asc) self.__dupes_sort_descriptor = (key, asc, delta) def sort_groups(self, key, asc=True): @@ -426,8 +410,7 @@ class Results(Markable): :param str key: key attribute name to sort with. :param bool asc: If false, sorting is reversed. """ - keyfunc = lambda g: self.app._get_group_sort_key(g, key) - self.groups.sort(key=keyfunc, reverse=not asc) + self.groups.sort(key=lambda g: self.app._get_group_sort_key(g, key), reverse=not asc) self.__groups_sort_descriptor = (key, asc) # ---Properties diff --git a/core/tests/engine_test.py b/core/tests/engine_test.py index 9b652044..068fa5ee 100644 --- a/core/tests/engine_test.py +++ b/core/tests/engine_test.py @@ -177,9 +177,7 @@ class TestCaseWordCompareWithFields: def test_simple(self): eq_( 67, - compare_fields( - [["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]] - ), + compare_fields([["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]), ) def test_empty(self): @@ -265,9 +263,7 @@ class TestCasebuild_word_dict: j = job.Job(1, do_progress) self.log = [] s = "foo bar" - build_word_dict( - [NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j - ) + build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j) # We don't have intermediate log because iter_with_progress is called with every > 1 eq_(0, self.log[0]) eq_(100, self.log[1]) @@ -297,10 +293,7 @@ class TestCasereduce_common_words: def test_dont_remove_objects_with_only_common_words(self): d = { - "common": set( - [NamedObject("common uncommon", True) for i in range(50)] - + [NamedObject("common", True)] - ), + "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]), "uncommon": set([NamedObject("common uncommon", True)]), } reduce_common_words(d, 50) @@ -309,10 +302,7 @@ class TestCasereduce_common_words: def test_values_still_are_set_instances(self): d = { - "common": set( - [NamedObject("common uncommon", True) for i in range(50)] - + [NamedObject("common", True)] - ), + "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]), "uncommon": set([NamedObject("common uncommon", True)]), } reduce_common_words(d, 50) @@ -352,12 +342,8 @@ class TestCasereduce_common_words: # would not stay in 'bar' because 'foo' is not a common word anymore. only_common = NamedObject("foo bar", True) d = { - "foo": set( - [NamedObject("foo bar baz", True) for i in range(49)] + [only_common] - ), - "bar": set( - [NamedObject("foo bar baz", True) for i in range(49)] + [only_common] - ), + "foo": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]), + "bar": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]), "baz": set([NamedObject("foo bar baz", True) for i in range(49)]), } reduce_common_words(d, 50) @@ -386,9 +372,7 @@ class TestCaseget_match: assert object() not in m def test_word_weight(self): - m = get_match( - NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,) - ) + m = get_match(NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,)) eq_(m.percentage, int((6.0 / 13.0) * 100)) @@ -554,8 +538,12 @@ class TestCaseGetMatchesByContents: def test_big_file_partial_hashes(self): smallsize = 1 bigsize = 100 * 1024 * 1024 # 100MB - f = [no("bigfoo", size=bigsize), no("bigbar", size=bigsize), - no("smallfoo", size=smallsize), no("smallbar", size=smallsize)] + f = [ + no("bigfoo", size=bigsize), + no("bigbar", size=bigsize), + no("smallfoo", size=smallsize), + no("smallbar", size=smallsize), + ] f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar" f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar" f[2].md5 = f[2].md5partial = "bleh" @@ -749,8 +737,7 @@ class TestCaseGroup: # if the ref has the same key as one or more of the dupe, run the tie_breaker func among them g = get_test_group() o1, o2, o3 = g.ordered - tie_breaker = lambda ref, dupe: dupe is o3 - g.prioritize(lambda x: 0, tie_breaker) + g.prioritize(lambda x: 0, lambda ref, dupe: dupe is o3) assert g.ref is o3 def test_prioritize_with_tie_breaker_runs_on_all_dupes(self): @@ -761,8 +748,7 @@ class TestCaseGroup: o1.foo = 1 o2.foo = 2 o3.foo = 3 - tie_breaker = lambda ref, dupe: dupe.foo > ref.foo - g.prioritize(lambda x: 0, tie_breaker) + g.prioritize(lambda x: 0, lambda ref, dupe: dupe.foo > ref.foo) assert g.ref is o3 def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self): @@ -775,9 +761,7 @@ class TestCaseGroup: o1.bar = 1 o2.bar = 2 o3.bar = 3 - key_func = lambda x: -x.foo - tie_breaker = lambda ref, dupe: dupe.bar > ref.bar - g.prioritize(key_func, tie_breaker) + g.prioritize(lambda x: -x.foo, lambda ref, dupe: dupe.bar > ref.bar) assert g.ref is o2 def test_prioritize_with_ref_dupe(self): @@ -909,9 +893,7 @@ class TestCaseget_groups: m1 = Match(A, B, 90) # This is the strongest "A" match m2 = Match(A, C, 80) # Because C doesn't match with B, it won't be in the group m3 = Match(A, D, 80) # Same thing for D - m4 = Match( - C, D, 70 - ) # However, because C and D match, they should have their own group. + m4 = Match(C, D, 70) # However, because C and D match, they should have their own group. groups = get_groups([m1, m2, m3, m4]) eq_(len(groups), 2) g1, g2 = groups diff --git a/hscommon/build.py b/hscommon/build.py index f7994636..7e25e497 100644 --- a/hscommon/build.py +++ b/hscommon/build.py @@ -30,8 +30,7 @@ from .util import ensure_folder, delete_files_with_pattern def print_and_do(cmd): - """Prints ``cmd`` and executes it in the shell. - """ + """Prints ``cmd`` and executes it in the shell.""" print(cmd) p = Popen(cmd, shell=True) return p.wait() @@ -91,16 +90,14 @@ def copy_all(pattern, dst): def ensure_empty_folder(path): - """Make sure that the path exists and that it's an empty folder. - """ + """Make sure that the path exists and that it's an empty folder.""" if op.exists(path): shutil.rmtree(path) os.mkdir(path) def filereplace(filename, outfilename=None, **kwargs): - """Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`. - """ + """Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`.""" if outfilename is None: outfilename = filename fp = open(filename, "rt", encoding="utf-8") @@ -152,9 +149,7 @@ def package_cocoa_app_in_dmg(app_path, destfolder, args): # a valid signature. if args.sign_identity: sign_identity = "Developer ID Application: {}".format(args.sign_identity) - result = print_and_do( - 'codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path) - ) + result = print_and_do('codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path)) if result != 0: print("ERROR: Signing failed. Aborting packaging.") return @@ -182,10 +177,7 @@ def build_dmg(app_path, destfolder): ) print("Building %s" % dmgname) # UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less. - print_and_do( - 'hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"' - % (op.join(destfolder, dmgname), dmgpath) - ) + print_and_do('hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"' % (op.join(destfolder, dmgname), dmgpath)) print("Build Complete") @@ -207,8 +199,7 @@ sysconfig.get_config_h_filename = lambda: op.join(op.dirname(__file__), 'pyconfi def add_to_pythonpath(path): - """Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``. - """ + """Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``.""" abspath = op.abspath(path) pythonpath = os.environ.get("PYTHONPATH", "") pathsep = ";" if ISWINDOWS else ":" @@ -231,9 +222,7 @@ def copy_packages(packages_names, dest, create_links=False, extra_ignores=None): create_links = False if not extra_ignores: extra_ignores = [] - ignore = shutil.ignore_patterns( - ".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores - ) + ignore = shutil.ignore_patterns(".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores) for package_name in packages_names: if op.exists(package_name): source_path = package_name @@ -444,11 +433,10 @@ class OSXFrameworkStructure: def create_symlinks(self): # Only call this after create() and copy_executable() - rel = lambda path: op.relpath(path, self.dest) os.symlink("A", op.join(self.dest, "Versions", "Current")) - os.symlink(rel(self.executablepath), op.join(self.dest, self.executablename)) - os.symlink(rel(self.headers), op.join(self.dest, "Headers")) - os.symlink(rel(self.resources), op.join(self.dest, "Resources")) + os.symlink(op.relpath(self.executablepath, self.dest), op.join(self.dest, self.executablename)) + os.symlink(op.relpath(self.headers, self.dest), op.join(self.dest, "Headers")) + os.symlink(op.relpath(self.resources, self.dest), op.join(self.dest, "Resources")) def copy_executable(self, executable): copy(executable, self.executablepath) @@ -481,9 +469,7 @@ def copy_embeddable_python_dylib(dst): def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): sysprefix = sys.prefix # could be a virtualenv basesysprefix = sys.base_prefix # seems to be path to non-virtual sys - real_lib_prefix = sysconfig.get_config_var( - "LIBDEST" - ) # leaving this in case it is neede + real_lib_prefix = sysconfig.get_config_var("LIBDEST") # leaving this in case it is neede def is_stdlib_path(path): # A module path is only a stdlib path if it's in either sys.prefix or @@ -493,11 +479,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): return False if "site-package" in path: return False - if not ( - path.startswith(sysprefix) - or path.startswith(basesysprefix) - or path.startswith(real_lib_prefix) - ): + if not (path.startswith(sysprefix) or path.startswith(basesysprefix) or path.startswith(real_lib_prefix)): return False return True @@ -511,9 +493,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): relpath = op.relpath(p, real_lib_prefix) elif p.startswith(sysprefix): relpath = op.relpath(p, sysprefix) - assert relpath.startswith( - "lib/python3." - ) # we want to get rid of that lib/python3.x part + assert relpath.startswith("lib/python3.") # we want to get rid of that lib/python3.x part relpath = relpath[len("lib/python3.X/") :] elif p.startswith(basesysprefix): relpath = op.relpath(p, basesysprefix) @@ -521,9 +501,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): relpath = relpath[len("lib/python3.X/") :] else: raise AssertionError() - if relpath.startswith( - "lib-dynload" - ): # We copy .so files in lib-dynload directly in our dest + if relpath.startswith("lib-dynload"): # We copy .so files in lib-dynload directly in our dest relpath = relpath[len("lib-dynload/") :] if relpath.startswith("encodings") or relpath.startswith("distutils"): # We force their inclusion later. @@ -562,9 +540,7 @@ def fix_qt_resource_file(path): fp.write(b"\n".join(lines)) -def build_cocoa_ext( - extname, dest, source_files, extra_frameworks=(), extra_includes=() -): +def build_cocoa_ext(extname, dest, source_files, extra_frameworks=(), extra_includes=()): extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"] for extra in extra_frameworks: extra_link_args += ["-framework", extra] diff --git a/hscommon/gui/table.py b/hscommon/gui/table.py index 3a03f5eb..975daf19 100644 --- a/hscommon/gui/table.py +++ b/hscommon/gui/table.py @@ -97,8 +97,7 @@ class Table(MutableSequence, Selectable): self._rows.pop(0) if self._footer is not None: self._rows.pop() - key = lambda row: row.sort_key_for_column(column_name) - self._rows.sort(key=key, reverse=desc) + self._rows.sort(key=lambda row: row.sort_key_for_column(column_name), reverse=desc) if self._header is not None: self._rows.insert(0, self._header) if self._footer is not None: @@ -277,8 +276,7 @@ class GUITable(Table, GUIObject): raise NotImplementedError() def _do_delete(self): - """(Virtual) Delete the selected rows. - """ + """(Virtual) Delete the selected rows.""" pass def _fill(self): diff --git a/qt/preferences_dialog.py b/qt/preferences_dialog.py index 2f816b16..3723e2f1 100644 --- a/qt/preferences_dialog.py +++ b/qt/preferences_dialog.py @@ -76,14 +76,10 @@ class PreferencesDialogBase(QDialog): super().__init__(parent, flags, **kwargs) self.app = app all_languages = get_langnames() - self.supportedLanguages = sorted( - SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang] - ) + self.supportedLanguages = sorted(SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang]) self._setupUi() - self.filterHardnessSlider.valueChanged["int"].connect( - self.filterHardnessLabel.setNum - ) + self.filterHardnessSlider.valueChanged["int"].connect(self.filterHardnessLabel.setNum) self.buttonBox.clicked.connect(self.buttonClicked) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) @@ -102,9 +98,7 @@ class PreferencesDialogBase(QDialog): sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.filterHardnessSlider.sizePolicy().hasHeightForWidth() - ) + sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) self.filterHardnessSlider.setSizePolicy(sizePolicy) self.filterHardnessSlider.setMinimum(1) self.filterHardnessSlider.setMaximum(100) @@ -140,9 +134,7 @@ class PreferencesDialogBase(QDialog): self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path")) self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox) self.customCommandLabel = QLabel(self) - self.customCommandLabel.setText( - tr("Custom Command (arguments: %d for dupe, %r for ref):") - ) + self.customCommandLabel.setText(tr("Custom Command (arguments: %d for dupe, %r for ref):")) self.widgetsVLayout.addWidget(self.customCommandLabel) self.customCommandEdit = QLineEdit(self) self.widgetsVLayout.addWidget(self.customCommandEdit) @@ -154,9 +146,7 @@ class PreferencesDialogBase(QDialog): self.languageComboBox = QComboBox(self) for lang in self.supportedLanguages: self.languageComboBox.addItem(get_langnames()[lang]) - layout.addLayout( - horizontalWrap([self.languageLabel, self.languageComboBox, None]) - ) + layout.addLayout(horizontalWrap([self.languageLabel, self.languageComboBox, None])) self._setupAddCheckbox( "tabs_default_pos", tr("Use default position for tab bar (requires restart)"), @@ -178,23 +168,15 @@ On MacOS, the tab bar will fill up the window's width instead." self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setMinimum(5) formlayout.addRow(tr("Font size:"), self.fontSizeSpinBox) - self._setupAddCheckbox( - "reference_bold_font", tr("Use bold font for references") - ) + self._setupAddCheckbox("reference_bold_font", tr("Use bold font for references")) formlayout.addRow(self.reference_bold_font) self.result_table_ref_foreground_color = ColorPickerButton(self) - formlayout.addRow( - tr("Reference foreground color:"), self.result_table_ref_foreground_color - ) + formlayout.addRow(tr("Reference foreground color:"), self.result_table_ref_foreground_color) self.result_table_ref_background_color = ColorPickerButton(self) - formlayout.addRow( - tr("Reference background color:"), self.result_table_ref_background_color - ) + formlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color) self.result_table_delta_foreground_color = ColorPickerButton(self) - formlayout.addRow( - tr("Delta foreground color:"), self.result_table_delta_foreground_color - ) + formlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color) formlayout.setLabelAlignment(Qt.AlignLeft) # Keep same vertical spacing as parent layout for consistency @@ -218,30 +200,20 @@ use the modifier key to drag the floating window around" else tr("The title bar can only be disabled while the window is docked") ) self.details_groupbox_layout.addWidget(self.details_dialog_titlebar_enabled) - self._setupAddCheckbox( - "details_dialog_vertical_titlebar", tr("Vertical title bar") - ) + self._setupAddCheckbox("details_dialog_vertical_titlebar", tr("Vertical title bar")) self.details_dialog_vertical_titlebar.setToolTip( - tr( - "Change the title bar from horizontal on top, to vertical on the left side" - ) + tr("Change the title bar from horizontal on top, to vertical on the left side") ) self.details_groupbox_layout.addWidget(self.details_dialog_vertical_titlebar) - self.details_dialog_vertical_titlebar.setEnabled( - self.details_dialog_titlebar_enabled.isChecked() - ) - self.details_dialog_titlebar_enabled.stateChanged.connect( - self.details_dialog_vertical_titlebar.setEnabled - ) + self.details_dialog_vertical_titlebar.setEnabled(self.details_dialog_titlebar_enabled.isChecked()) + self.details_dialog_titlebar_enabled.stateChanged.connect(self.details_dialog_vertical_titlebar.setEnabled) gridlayout = QGridLayout() formlayout = QFormLayout() self.details_table_delta_foreground_color = ColorPickerButton(self) # Padding on the right side and space between label and widget to keep it somewhat consistent across themes gridlayout.setColumnStretch(1, 1) formlayout.setHorizontalSpacing(50) - formlayout.addRow( - tr("Delta foreground color:"), self.details_table_delta_foreground_color - ) + formlayout.addRow(tr("Delta foreground color:"), self.details_table_delta_foreground_color) gridlayout.addLayout(formlayout, 0, 0) self.details_groupbox_layout.addLayout(gridlayout) details_groupbox.setLayout(self.details_groupbox_layout) @@ -276,9 +248,7 @@ use the modifier key to drag the floating window around" # self.mainVLayout.addLayout(self.widgetsVLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons( - QDialogButtonBox.Cancel - | QDialogButtonBox.Ok - | QDialogButtonBox.RestoreDefaults + QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults ) self.mainVLayout.addWidget(self.tabwidget) self.mainVLayout.addWidget(self.buttonBox) @@ -299,7 +269,10 @@ use the modifier key to drag the floating window around" def load(self, prefs=None, section=Sections.ALL): if prefs is None: prefs = self.app.prefs - setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) + + def setchecked(cb, b): + cb.setCheckState(Qt.Checked if b else Qt.Unchecked) + if section & Sections.GENERAL: self.filterHardnessSlider.setValue(prefs.filter_hardness) self.filterHardnessLabel.setNum(prefs.filter_hardness) @@ -322,18 +295,10 @@ use the modifier key to drag the floating window around" prefs.details_dialog_vertical_titlebar, ) self.fontSizeSpinBox.setValue(prefs.tableFontSize) - self.details_table_delta_foreground_color.setColor( - prefs.details_table_delta_foreground_color - ) - self.result_table_ref_foreground_color.setColor( - prefs.result_table_ref_foreground_color - ) - self.result_table_ref_background_color.setColor( - prefs.result_table_ref_background_color - ) - self.result_table_delta_foreground_color.setColor( - prefs.result_table_delta_foreground_color - ) + self.details_table_delta_foreground_color.setColor(prefs.details_table_delta_foreground_color) + self.result_table_ref_foreground_color.setColor(prefs.result_table_ref_foreground_color) + self.result_table_ref_background_color.setColor(prefs.result_table_ref_background_color) + self.result_table_delta_foreground_color.setColor(prefs.result_table_delta_foreground_color) try: langindex = self.supportedLanguages.index(self.app.prefs.language) except ValueError: @@ -344,31 +309,22 @@ use the modifier key to drag the floating window around" def save(self): prefs = self.app.prefs prefs.filter_hardness = self.filterHardnessSlider.value() - ischecked = lambda cb: cb.checkState() == Qt.Checked + + def ischecked(cb): + return cb.checkState() == Qt.Checked + prefs.mix_file_kind = ischecked(self.mixFileKindBox) prefs.use_regexp = ischecked(self.useRegexpBox) prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) prefs.debug_mode = ischecked(self.debugModeBox) prefs.reference_bold_font = ischecked(self.reference_bold_font) - prefs.details_dialog_titlebar_enabled = ischecked( - self.details_dialog_titlebar_enabled - ) - prefs.details_dialog_vertical_titlebar = ischecked( - self.details_dialog_vertical_titlebar - ) - prefs.details_table_delta_foreground_color = ( - self.details_table_delta_foreground_color.color - ) - prefs.result_table_ref_foreground_color = ( - self.result_table_ref_foreground_color.color - ) - prefs.result_table_ref_background_color = ( - self.result_table_ref_background_color.color - ) - prefs.result_table_delta_foreground_color = ( - self.result_table_delta_foreground_color.color - ) + prefs.details_dialog_titlebar_enabled = ischecked(self.details_dialog_titlebar_enabled) + prefs.details_dialog_vertical_titlebar = ischecked(self.details_dialog_vertical_titlebar) + prefs.details_table_delta_foreground_color = self.details_table_delta_foreground_color.color + prefs.result_table_ref_foreground_color = self.result_table_ref_foreground_color.color + prefs.result_table_ref_background_color = self.result_table_ref_background_color.color + prefs.result_table_delta_foreground_color = self.result_table_delta_foreground_color.color prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() prefs.custom_command = str(self.customCommandEdit.text()) prefs.tableFontSize = self.fontSizeSpinBox.value() @@ -411,9 +367,7 @@ class ColorPickerButton(QPushButton): @pyqtSlot() def onClicked(self): - color = QColorDialog.getColor( - self.color if self.color is not None else Qt.white, self.parent - ) + color = QColorDialog.getColor(self.color if self.color is not None else Qt.white, self.parent) self.setColor(color) def setColor(self, color):