From 3762e7be0368484d68c4a90923672fdb0f51a5fc Mon Sep 17 00:00:00 2001 From: Patrick Zwerschke Date: Tue, 6 Dec 2022 03:41:27 +0100 Subject: [PATCH 01/16] Update test workflow for python 3.11 (#215) - added python 3.11 to test workflow - catch FileNotFoundError in module defaultpaths --- .github/workflows/pytest.yml | 10 +++++++--- DisplayCAL/RealDisplaySizeMM.py | 2 ++ DisplayCAL/defaultpaths.py | 17 +++++++++-------- DisplayCAL/lib64/python311/__init__.py | 0 README.md | 2 +- 5 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 DisplayCAL/lib64/python311/__init__.py diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index c551cd33e..a463f8077 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -15,9 +15,13 @@ jobs: - "3.8" - "3.9" - "3.10" + - "3.11" wx-version: - "4.1.1" - "4.2.0" + exclude: + - python-version: "3.11" + wx-version: "4.1.1" steps: @@ -26,14 +30,14 @@ jobs: - name: Set Environment Variables run: | echo "py_version=$(echo ${{ matrix.python-version }} | tr -d .)" >> $GITHUB_ENV - if [[ ${{ matrix.wx-version }} == "4.1.1" ]]; then echo "wx_url=wxpython.p5k.org/wxPython-4.1.1"; fi >> $GITHUB_ENV - if [[ ${{ matrix.wx-version }} == "4.2.0" ]]; then echo "wx_url=extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-20.04/wxPython-4.2.0"; fi >> $GITHUB_ENV if [ "${{ matrix.python-version }}" == "3.8" ]; then echo "add_dir_str=${{ matrix.python-version }}" >> $GITHUB_ENV elif [ "${{ matrix.python-version }}" == "3.9" ]; then echo "add_dir_str=${{ matrix.python-version }}" >> $GITHUB_ENV elif [ "${{ matrix.python-version }}" == "3.10" ]; then echo "add_dir_str=cpython-310" >> $GITHUB_ENV + elif [ "${{ matrix.python-version }}" == "3.11" ]; then + echo "add_dir_str=cpython-311" >> $GITHUB_ENV fi - name: Setup timezone @@ -71,7 +75,7 @@ jobs: - name: Install wxPython wheels ${{ matrix.wx-version }} run: | - pip install https://${{ env.wx_url }}-cp${{ env.py_version }}-cp${{ env.py_version }}-linux_x86_64.whl + pip install https://wxpython.p5k.org/wxPython-${{ matrix.wx-version }}-cp${{ env.py_version }}-cp${{ env.py_version }}-linux_x86_64.whl - name: Install Python dependencies run: | diff --git a/DisplayCAL/RealDisplaySizeMM.py b/DisplayCAL/RealDisplaySizeMM.py index 00957692c..25b730d05 100644 --- a/DisplayCAL/RealDisplaySizeMM.py +++ b/DisplayCAL/RealDisplaySizeMM.py @@ -25,6 +25,8 @@ from DisplayCAL.lib64.python39.RealDisplaySizeMM import * elif sys.version_info[:2] == (3, 10): from DisplayCAL.lib64.python310.RealDisplaySizeMM import * + elif sys.version_info[:2] == (3, 11): + from DisplayCAL.lib64.python311.RealDisplaySizeMM import * # else: # pass diff --git a/DisplayCAL/defaultpaths.py b/DisplayCAL/defaultpaths.py index cd11d6d75..59258e79d 100644 --- a/DisplayCAL/defaultpaths.py +++ b/DisplayCAL/defaultpaths.py @@ -235,9 +235,14 @@ def set_translation(obj): obj.GETTEXT_PACKAGE, locale_dir, codeset="UTF-8" ) except TypeError: - obj.translation = gettext.translation( - obj.GETTEXT_PACKAGE, locale_dir - ) + try: + obj.translation = gettext.translation( + obj.GETTEXT_PACKAGE, locale_dir + ) + except FileNotFoundError as exc: + print("XDG:", exc) + obj.translation = gettext.NullTranslations() + return False except IOError as exception: print("XDG:", exception) obj.translation = gettext.NullTranslations() @@ -261,11 +266,7 @@ def get_config_files(filename): @staticmethod def shell_unescape(s): - a = [] - for i, c in enumerate(s): - if c == "\\" and len(s) > i + 1: - continue - a.append(c) + a = [c for i, c in enumerate(s) if c != "\\" or len(s) <= i + 1] return "".join(a) @staticmethod diff --git a/DisplayCAL/lib64/python311/__init__.py b/DisplayCAL/lib64/python311/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/README.md b/README.md index 3ff3c4ec4..4119ace70 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Here is a screenshots showing the tool working with Python 3.10: ![image](https://user-images.githubusercontent.com/1786804/169152229-e06ff549-55fe-4149-8742-405446e6b01f.png) -Currently, DisplayCAL is working with Python 3.8, 3.9 and 3.10 and wxPython 4.1.1 or 4.2.0. +Currently, DisplayCAL is working with Python 3.8, 3.9, 3.10 and 3.11 and wxPython 4.1.1 or 4.2.0. Here is a list of things that is working: From 97f0c91f5855e4d21f47181ef596251eb03cb835 Mon Sep 17 00:00:00 2001 From: Patrick Zwerschke Date: Thu, 8 Dec 2022 14:12:24 +0100 Subject: [PATCH 02/16] updated restrictions for max python version to run with python 3.11 (#217) --- DisplayCAL/meta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DisplayCAL/meta.py b/DisplayCAL/meta.py index 00b9c82c9..30797cdf4 100644 --- a/DisplayCAL/meta.py +++ b/DisplayCAL/meta.py @@ -62,7 +62,7 @@ name_html = 'DisplayCAL' py_minversion = (3, 8) -py_maxversion = (3, 10) +py_maxversion = (3, 11) version = VERSION_STRING version_lin = VERSION_STRING # Linux From e7ff80139735fb38a497c7bcd5327ed9afce52b6 Mon Sep 17 00:00:00 2001 From: Patrick Zwerschke Date: Sat, 10 Dec 2022 23:03:15 +0100 Subject: [PATCH 03/16] Updated actions to use Node.js 16 (#220) --- .github/workflows/pytest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index a463f8077..887f19001 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -25,7 +25,7 @@ jobs: steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set Environment Variables run: | @@ -62,7 +62,7 @@ jobs: sudo /usr/bin/Xvfb $DISPLAY -screen 0 1280x1024x24 & - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} From a34360cefc1c4c155de376588969595628803fe6 Mon Sep 17 00:00:00 2001 From: stativ Date: Mon, 12 Dec 2022 14:17:23 +0100 Subject: [PATCH 04/16] Fix incorect bytes and string comparison when reading a .ti3 file (#221) --- DisplayCAL/worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DisplayCAL/worker.py b/DisplayCAL/worker.py index e1a7494aa..6de31cb75 100644 --- a/DisplayCAL/worker.py +++ b/DisplayCAL/worker.py @@ -13631,7 +13631,7 @@ def prepare_dispread(self, apply_calibration=True): if ext.lower() != ".ti1": ti3_lines = [line.strip() for line in ti3] ti3.close() - if "CTI3" not in ti3_lines: + if b"CTI3" not in ti3_lines: return ( Error( lang.getstr( From 5ad1ac4bb32938f0b8a6a77dc78a2e96a2990548 Mon Sep 17 00:00:00 2001 From: James Addison <55152140+jayaddison@users.noreply.github.com> Date: Sat, 7 Jan 2023 23:20:38 +0000 Subject: [PATCH 05/16] Cleanup: remove no-longer-referenced get_known_folder_path, UserDirs class (#227) Cleanup: remove no-longer-referenced defaultpaths.get_known_folder_path method, and associated UserDirs class --- DisplayCAL/defaultpaths.py | 158 ------------------------------------- DisplayCAL/setup.py | 19 ++--- DisplayCAL/worker.py | 1 - 3 files changed, 10 insertions(+), 168 deletions(-) diff --git a/DisplayCAL/defaultpaths.py b/DisplayCAL/defaultpaths.py index 59258e79d..3ac7c6822 100644 --- a/DisplayCAL/defaultpaths.py +++ b/DisplayCAL/defaultpaths.py @@ -54,57 +54,6 @@ def SHGetSpecialFolderPath(hwndOwner, nFolder, create=0): from DisplayCAL.util_os import expanduseru, expandvarsu, getenvu, waccess -def get_known_folder_path(folderid, user=True): - """Get known folder path. - - Uses GetKnownFolderPath API on Windows Vista and later, and XDG user dirs - on Linux. - - Falls back to ~/ in all other cases. - - folderid can be "Desktop", "Downloads", "Documents", "Music", "Pictures", - "Public", "Templates", or "Videos". - - user Return user folder instead of common (Windows) or default (Linux) - - """ - folder_path = os.path.join(home, folderid) - if sys.platform == "win32" and sys.getwindowsversion() >= (6,): - # Windows Vista or newer - from DisplayCAL import win_knownpaths - - try: - folder_path = win_knownpaths.get_path( - getattr(win_knownpaths.FOLDERID, folderid), - getattr(win_knownpaths.UserHandle, "current" if user else "common"), - ) - except Exception: - print("Warning: Could not get known folder %r" % folderid) - elif sys.platform not in ("darwin", "win32"): - # Linux - user_dir = folderid - folderid = ( - {"Downloads": folderid[:-1], "Public": folderid + "share"} - .get(folderid, folderid) - .upper() - ) - if folderid != "DESKTOP" or XDG.UserDirs.enabled: - user_dir = XDG.UserDirs.default_dirs.get(folderid) - if user: - user_dir = XDG.UserDirs.user_dirs.get(folderid, user_dir) - if user_dir: - folder_path = os.path.join(home, user_dir) - if ( - folderid != "DESKTOP" - and ( - not user_dir - or (not os.path.isdir(folder_path) and not XDG.UserDirs.enabled) - ) - ) or not waccess(folder_path, os.W_OK): - folder_path = home - return folder_path - - home = expanduseru("~") if sys.platform == "win32": # Always specify create=1 for SHGetSpecialFolderPath so we don't get an @@ -288,113 +237,6 @@ def process_config_file(path, fn): return False return True - class _UserDirs(object): - - GETTEXT_PACKAGE = "xdg-user-dirs" - - enabled = True - filename_encoding = "UTF-8" - default_dirs = {} - user_dirs = {} - - _initialized = False - - def __getattribute__(self, name): - if name != "init" and not object.__getattribute__(self, "_initialized"): - object.__getattribute__(self, "init")() - return object.__getattribute__(self, name) - - def load_config(self, path): - def fn(key, value): - if key == "enabled": - self.enabled = XDG.is_true(value) - elif key == "filename_encoding": - value = value.upper() - if value == "LOCALE": - current_locale = locale.getlocale() - locale.setlocale(locale.LC_ALL, "") - self.filename_encoding = locale.nl_langinfo(locale.CODESET) - locale.setlocale(locale.LC_ALL, current_locale) - else: - self.filename_encoding = value - - return XDG.process_config_file(path, fn) - - def load_all_configs(self): - for path in reversed(XDG.get_config_files("user-dirs.conf")): - self.load_config(path) - - def load_default_dirs(self): - paths = XDG.get_config_files("user-dirs.defaults") - if not paths: - print("XDG.UserDirs: No default user directories") - return False - - def fn(name, path): - self.default_dirs[name] = self.localize_path_name(path) - - return XDG.process_config_file(paths[0], fn) - - def load_user_dirs(self): - path = os.path.join(XDG.config_home, "user-dirs.dirs") - if not path or not os.path.isfile(path): - return False - - def fn(key, value): - if ( - key.startswith("XDG_") - and key.endswith("_DIR") - and value.startswith('"') - and value.endswith('"') - ): - name = key[4:-4] - if not name: - return - value = value.strip('"') - if value.startswith("$HOME"): - value = value[5:] - if value.startswith("/"): - value = value[1:] - elif value: - # Not ending after $HOME, nor followed by slash. - # Ignore - return - elif not value.startswith("/"): - return - self.user_dirs[name] = XDG.shell_unescape(value).decode( - "UTF-8", "ignore" - ) - - return XDG.process_config_file(path, fn) - - def localize_path_name(self, path): - elements = path.split(os.path.sep) - - for i, element in enumerate(elements): - elements[i] = self.translation.ugettext(element) - - return os.path.join(*elements) - - def init(self): - self._initialized = True - - XDG.set_translation(self) - - self.load_all_configs() - try: - codecs.lookup(self.filename_encoding) - except LookupError: - print( - "XDG.UserDirs: Can't convert from UTF-8 to", - self.filename_encoding, - ) - return False - - self.load_default_dirs() - self.load_user_dirs() - - UserDirs = _UserDirs() - for name in dir(XDG): attr = getattr(XDG, name) if isinstance(attr, (str, list)): diff --git a/DisplayCAL/setup.py b/DisplayCAL/setup.py index 220651e5b..b53a304fe 100644 --- a/DisplayCAL/setup.py +++ b/DisplayCAL/setup.py @@ -453,6 +453,7 @@ def setup(): prefix = "" recordfile_name = None # record installed files to this file sdist = "sdist" in sys.argv[1:] + setuptools = None skip_postinstall = "--skip-postinstall" in sys.argv[1:] use_distutils = not bdist_bbfreeze and not do_py2app use_setuptools = ( @@ -479,10 +480,10 @@ def setup(): import setuptools from setuptools import setup, Extension + setuptools = True print("using setuptools") current_findall = setuptools.findall except ImportError: - use_setuptools = False pass else: if os.path.exists("use-setuptools"): @@ -508,7 +509,7 @@ def findall( distutils.filelist.findall = findall - if not use_setuptools: + if not setuptools: from distutils.core import setup, Extension print("using distutils") @@ -944,7 +945,7 @@ def findall( ext_modules = [RealDisplaySizeMM] requires = [] - if not use_setuptools or sys.platform != "win32": + if not setuptools or sys.platform != "win32": # wxPython windows installer doesn't add egg-info entry, so # a dependency check from pkg_resources would always fail requires.append("wxPython (>= %s)" % ".".join(str(n) for n in wx_minversion)) @@ -1020,7 +1021,7 @@ def findall( "version": msiversion if "bdist_msi" in sys.argv[1:] else version, } - if use_setuptools: + if setuptools: attrs["entry_points"] = { "gui_scripts": [ "%s = %s.main:main%s" @@ -1277,7 +1278,7 @@ def copy_package_data(self, package, target_dir): attrs["options"]["py2exe"].update( {"bundle_files": 3, "compressed": 0, "optimize": 0, "skip_archive": 1} ) - if use_setuptools: + if setuptools: attrs["setup_requires"] = ["py2exe"] attrs["zipfile"] = os.path.join("lib", "library.zip") @@ -1327,10 +1328,10 @@ def copy_package_data(self, package, target_dir): # site-packages (on Mac and Windows) and when we want to make them # absolute (Linux) linux = sys.platform not in ("darwin", "win32") and ( - not cmd.root and use_setuptools + not cmd.root and setuptools ) dar_win = ( - sys.platform in ("darwin", "win32") and (cmd.root or not use_setuptools) + sys.platform in ("darwin", "win32") and (cmd.root or not setuptools) ) or bdist_win if ( not do_uninstall @@ -1379,7 +1380,7 @@ def copy_package_data(self, package, target_dir): # logic to find them paths = safe_glob(os.path.join(cmd.install_scripts, name)) if sys.platform == "win32": - if use_setuptools: + if setuptools: paths += safe_glob(os.path.join(cmd.install_scripts, f"{name}.exe")) paths += safe_glob( os.path.join(cmd.install_scripts, f"{name}-script.py") @@ -1586,7 +1587,7 @@ def copy_package_data(self, package, target_dir): manifest_in.append("include " + os.path.join("tests", "*")) manifest_in.append("recursive-include theme *") manifest_in.append("recursive-include util *.cmd *.py *.sh") - if sys.platform == "win32" and not use_setuptools: + if sys.platform == "win32" and not setuptools: # Only needed under Windows manifest_in.append("global-exclude .svn/*") manifest_in.append("global-exclude *~") diff --git a/DisplayCAL/worker.py b/DisplayCAL/worker.py index 6de31cb75..bf3844e96 100644 --- a/DisplayCAL/worker.py +++ b/DisplayCAL/worker.py @@ -141,7 +141,6 @@ ) from DisplayCAL.defaultpaths import ( cache, - get_known_folder_path, iccprofiles_home, iccprofiles_display_home, appdata, From ed4e591eab3b038b2fecc90ec4d2e3a17b2ade00 Mon Sep 17 00:00:00 2001 From: filmmakerto <26349280+filmmakerto@users.noreply.github.com> Date: Sat, 11 Mar 2023 19:26:01 +0100 Subject: [PATCH 06/16] fix eoyilmaz/displaycal-py3#231 (#240) Fixes #231 --- DisplayCAL/worker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DisplayCAL/worker.py b/DisplayCAL/worker.py index bf3844e96..e9cf27885 100644 --- a/DisplayCAL/worker.py +++ b/DisplayCAL/worker.py @@ -6583,7 +6583,7 @@ def exec_cmd( if os.path.isfile(okfilename): try: os.remove(okfilename) - except OSError, e: + except OSError: pass else: break @@ -6624,7 +6624,7 @@ def exec_cmd( waitfile.write("#!/usr/bin/env python3\n") waitfile.write(pythonscript) os.chmod(waitfilename, 0o755) - args[index] += '"%s" ./%s' % ( + args[index] += '%s ./%s' % ( strtr(safe_str(python), {'"': r"\"", "$": r"\$"}), os.path.basename(waitfilename), ) From dc16e156a355408083f07ff81b937b09c5603978 Mon Sep 17 00:00:00 2001 From: sdy623 Date: Mon, 10 Apr 2023 17:19:14 +0800 Subject: [PATCH 07/16] Add feature: Add a gamut coverage information in Profile Information page --- DisplayCAL/wxLUTViewer.py | 6 ++++ DisplayCAL/wxProfileInfo.py | 64 +++++++++++++++++++++++++++++++++++++ DisplayCAL/wxwindows.py | 15 +++++++++ 3 files changed, 85 insertions(+) diff --git a/DisplayCAL/wxLUTViewer.py b/DisplayCAL/wxLUTViewer.py index 24bf0e797..cda9e8245 100644 --- a/DisplayCAL/wxLUTViewer.py +++ b/DisplayCAL/wxLUTViewer.py @@ -40,6 +40,7 @@ BaseApp, BaseFrame, BitmapBackgroundPanelText, + BitmapBackgroundPanelTextGamut, CustomCheckBox, FileDrop, InfoDialog, @@ -828,6 +829,7 @@ def __init__(self, *args, **kwargs): self.sizer.Add(self.box_panel, flag=wx.EXPAND) self.status = BitmapBackgroundPanelText(self, name="statuspanel") + self.gamut_status = BitmapBackgroundPanelTextGamut(self, name="statuspanel") self.status.SetMaxFontSize(11) self.status.label_y = 8 self.status.textshadow = False @@ -2318,6 +2320,10 @@ def SetStatusText(self, text): self.status.Label = text self.status.Refresh() + def SetGamutStatusText(self, text): + self.gamut_status.Label = text + self.status.Refresh() + def UpdatePointLabel(self, xy): if self.client.GetEnablePointLabel(): # Show closest point (when enbled) diff --git a/DisplayCAL/wxProfileInfo.py b/DisplayCAL/wxProfileInfo.py index 39fae8793..9594daccc 100644 --- a/DisplayCAL/wxProfileInfo.py +++ b/DisplayCAL/wxProfileInfo.py @@ -5,6 +5,8 @@ import os import sys +import traceback + from DisplayCAL.config import ( defaults, fs_enc, @@ -42,6 +44,7 @@ BaseApp, BaseFrame, BitmapBackgroundPanelText, + BitmapBackgroundPanelTextGamut, CustomCheckBox, CustomGrid, CustomRowLabelRenderer, @@ -1220,6 +1223,17 @@ def __init__(self, *args, **kwargs): self.status.SetMinSize((0, h * 2 + 10)) p1.sizer.Add(self.status, flag=wx.EXPAND) + self.gamut_status = BitmapBackgroundPanelTextGamut(p1) + self.gamut_status.SetMaxFontSize(11) + self.gamut_status.label_y = 0 + self.gamut_status.textshadow = False + self.gamut_status.SetBackgroundColour(BGCOLOUR) + self.gamut_status.SetForegroundColour(FGCOLOUR) + h = self.gamut_status.GetTextExtent("Ig")[1] + self.gamut_status.SetMinSize((0, h * 2 + 10)) + p1.sizer.Add(self.gamut_status, flag=wx.EXPAND) + + # Gamut view options self.gamut_view_options = GamutViewOptions(p1) self.options_panel.AddPage(self.gamut_view_options, "") @@ -1433,6 +1447,56 @@ def LoadProfile(self, profile, reset=True): ): reset = True self.profile = profile + cinfo = [] + vinfo = [] + if "meta" in profile.tags: + for key in ("avg", "max", "rms"): + try: + dE = float( + profile.tags.meta.getvalue("ACCURACY_dE76_%s" % key) + ) + except (TypeError, ValueError): + pass + + gamuts = ( + ("srgb", "sRGB", ICCP.GAMUT_VOLUME_SRGB), + ("adobe-rgb", "Adobe RGB", ICCP.GAMUT_VOLUME_ADOBERGB), + ("dci-p3", "DCI P3", ICCP.GAMUT_VOLUME_SMPTE431_P3), + ) + for key, name, _volume in gamuts: + try: + gamut_coverage = float( + profile.tags.meta.getvalue("GAMUT_coverage(%s)" % key) + ) + except (TypeError, ValueError): + traceback.print_exc() + gamut_coverage = None + if gamut_coverage: + cinfo.append("%.1f%% %s" % (gamut_coverage * 100, name)) + try: + gamut_volume = float(profile.tags.meta.getvalue("GAMUT_volume")) + except (TypeError, ValueError): + traceback.print_exc() + gamut_volume = None + if gamut_volume: + for _key, name, volume in gamuts: + vinfo.append( + "%.1f%% %s" + % ( + gamut_volume + * ICCP.GAMUT_VOLUME_SRGB + / volume + * 100, + name, + ) + ) + if len(vinfo) == len(cinfo): + break + + if gamut_coverage and gamut_volume: + gamut_cov_text = f'{cinfo[0]} {cinfo[1]} {cinfo[2]}' + self.SetGamutStatusText(gamut_cov_text) + for channel in "rgb": trc = profile.tags.get(f"{channel}TRC", profile.tags.get("kTRC")) if isinstance(trc, ICCP.ParametricCurveType): diff --git a/DisplayCAL/wxwindows.py b/DisplayCAL/wxwindows.py index 2dcc6eb6d..e98aa778d 100644 --- a/DisplayCAL/wxwindows.py +++ b/DisplayCAL/wxwindows.py @@ -3084,6 +3084,21 @@ def _draw(self, dc): dc.SetTextForeground(color) dc.DrawText(line, int(x), int(y)) +class BitmapBackgroundPanelTextGamut(BitmapBackgroundPanelText): + + """A panel with a background bitmap and text label to display gamut""" + + def __init__(self, *args, **kwargs): + BitmapBackgroundPanel.__init__(self, *args, **kwargs) + self.title = lang.getstr("gamut.coverage") + self.caption = lang.getstr("gamut.coverage") + self.label_x = None + self.label_y = None + self.textalpha = 1.0 + self.textshadow = True + self.textshadowcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT) + self.use_gcdc = False + self._label = "" class ConfirmDialog(BaseInteractiveDialog): From ede37e2cf3050e11ededb713b97af483918b023d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Figui=C3=A8re?= Date: Tue, 23 May 2023 01:28:05 -0400 Subject: [PATCH 08/16] Fix appdata to validate for flathub (#253) - Fix appdata to validate for flathub --- misc/net.displaycal.DisplayCAL.appdata.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/net.displaycal.DisplayCAL.appdata.xml b/misc/net.displaycal.DisplayCAL.appdata.xml index 369f4ae77..c77dbc65b 100644 --- a/misc/net.displaycal.DisplayCAL.appdata.xml +++ b/misc/net.displaycal.DisplayCAL.appdata.xml @@ -26,6 +26,7 @@ Interactive display adjustment + ${URL} ${URL}issues/ ${URL}#toc From 8e1d5b7be7ba84cf2c79a7ac98fe7473ea366396 Mon Sep 17 00:00:00 2001 From: 3ll3d00d Date: Sat, 3 Jun 2023 21:42:25 +0100 Subject: [PATCH 09/16] allow untethered window to open --- DisplayCAL/wxUntetheredFrame.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DisplayCAL/wxUntetheredFrame.py b/DisplayCAL/wxUntetheredFrame.py index d38eb9171..83cb65bb7 100644 --- a/DisplayCAL/wxUntetheredFrame.py +++ b/DisplayCAL/wxUntetheredFrame.py @@ -48,7 +48,7 @@ def __init__(self, parent=None, handler=None, keyhandler=None, start_timer=True) # lang.getstr("measurement.untethered"), # style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, # name="untetheredframe") - super(UntetheredFrame, self).__init__( + BaseFrame.__init__( self, parent, wx.ID_ANY, @@ -108,7 +108,8 @@ def __init__(self, parent=None, handler=None, keyhandler=None, start_timer=True) ) self.measure_auto_cb.SetForegroundColour(FGCOLOUR) self.measure_auto_cb.Bind(wx.EVT_CHECKBOX, self.measure_auto_ctrl_handler) - sizer.Add(self.measure_auto_cb, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) + # only vertical alignment flags can be used with a horizontal sizer + sizer.Add(self.measure_auto_cb, 0, wx.ALIGN_CENTER_VERTICAL) panelsizer.Add(sizer, 0, wx.BOTTOM | wx.EXPAND, border=8) sizer = wx.BoxSizer(wx.HORIZONTAL) self.measure_btn = FlatShadedButton( From 292c940bba29f2b9f21fc03c93c8deb233af512d Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Sat, 29 Apr 2023 11:57:06 +0100 Subject: [PATCH 10/16] - Fixed `colorimeter_correction_web_check_choose()` to work properly for fractional scale. --- DisplayCAL/display_cal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DisplayCAL/display_cal.py b/DisplayCAL/display_cal.py index 34e7ffaa6..3e59d6f2e 100644 --- a/DisplayCAL/display_cal.py +++ b/DisplayCAL/display_cal.py @@ -983,7 +983,7 @@ def show_ccxx_info(event): lstr_en = lang.getstr("colorimeter_correction.web_check.info", lcode="en") if lstr != lstr_en or lang.getcode() == "en": info_txt = wx.StaticText(dlg, -1, lstr) - info_txt.Wrap(640 * scale) + info_txt.Wrap(int(640 * scale)) dlg.sizer3.Add(info_txt, 1, flag=wx.TOP | wx.ALIGN_LEFT, border=12) if len(cgats) > 1: # We got several matches From 6218880540fc829165eec488cfc94df780427ef5 Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Sat, 29 Apr 2023 11:58:43 +0100 Subject: [PATCH 11/16] - Updated string formatting on several places in `wxProfileInfo`. --- DisplayCAL/wxProfileInfo.py | 64 ++++++++++++++----------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/DisplayCAL/wxProfileInfo.py b/DisplayCAL/wxProfileInfo.py index 9594daccc..6fc7d9dfc 100644 --- a/DisplayCAL/wxProfileInfo.py +++ b/DisplayCAL/wxProfileInfo.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- - - import re import os import sys @@ -688,7 +686,9 @@ def __init__(self, *args, **kwargs): self.comparison_whitepoint_legend = wx.StaticText( self, -1, - "%s (%s)" % (lang.getstr("whitepoint"), lang.getstr("comparison_profile")), + "{} ({})".format( + lang.getstr("whitepoint"), lang.getstr("comparison_profile") + ), ) self.comparison_whitepoint_legend.SetMaxFontSize(11) self.comparison_whitepoint_legend.SetForegroundColour(FGCOLOUR) @@ -805,9 +805,7 @@ def __init__(self, *args, **kwargs): self.options_sizer.Add( self.comparison_profile_label, flag=wx.ALIGN_CENTER_VERTICAL ) - self.comparison_profiles = dict( - [(lang.getstr("calibration.file.none"), None)] - ) + self.comparison_profiles = dict([(lang.getstr("calibration.file.none"), None)]) srgb = None try: srgb = ICCP.ICCProfile(get_data_path("ref/sRGB.icm")) @@ -960,7 +958,6 @@ def comparison_profile_select_handler(self, event): self.comparison_profile_bmp.Show(index > 0) self.DrawCanvas(0, reset=False) except Exception: - import traceback traceback.print_exc() def comparison_profiles_sort(self): @@ -982,7 +979,7 @@ def draw(self, center=False): parent = self.TopLevelParent parent.client.proportional = True parent.client.DrawCanvas( - "%s %s" % (colorspace, lang.getstr("colorspace")), + f"{colorspace} {lang.getstr('colorspace')}", colorspace, whitepoint=self.whitepoint_select.GetSelection(), center=center, @@ -1233,7 +1230,6 @@ def __init__(self, *args, **kwargs): self.gamut_status.SetMinSize((0, h * 2 + 10)) p1.sizer.Add(self.gamut_status, flag=wx.EXPAND) - # Gamut view options self.gamut_view_options = GamutViewOptions(p1) self.options_panel.AddPage(self.gamut_view_options, "") @@ -1452,9 +1448,7 @@ def LoadProfile(self, profile, reset=True): if "meta" in profile.tags: for key in ("avg", "max", "rms"): try: - dE = float( - profile.tags.meta.getvalue("ACCURACY_dE76_%s" % key) - ) + dE = float(profile.tags.meta.getvalue(f"ACCURACY_dE76_{key}")) except (TypeError, ValueError): pass @@ -1466,13 +1460,13 @@ def LoadProfile(self, profile, reset=True): for key, name, _volume in gamuts: try: gamut_coverage = float( - profile.tags.meta.getvalue("GAMUT_coverage(%s)" % key) + profile.tags.meta.getvalue(f"GAMUT_coverage({key})") ) except (TypeError, ValueError): traceback.print_exc() gamut_coverage = None if gamut_coverage: - cinfo.append("%.1f%% %s" % (gamut_coverage * 100, name)) + cinfo.append(f"{gamut_coverage * 100:.1f}% {name}") try: gamut_volume = float(profile.tags.meta.getvalue("GAMUT_volume")) except (TypeError, ValueError): @@ -1481,20 +1475,13 @@ def LoadProfile(self, profile, reset=True): if gamut_volume: for _key, name, volume in gamuts: vinfo.append( - "%.1f%% %s" - % ( - gamut_volume - * ICCP.GAMUT_VOLUME_SRGB - / volume - * 100, - name, - ) + f"{gamut_volume * ICCP.GAMUT_VOLUME_SRGB / volume * 100:.1f}% {name}" ) if len(vinfo) == len(cinfo): break if gamut_coverage and gamut_volume: - gamut_cov_text = f'{cinfo[0]} {cinfo[1]} {cinfo[2]}' + gamut_cov_text = f"{cinfo[0]} {cinfo[1]} {cinfo[2]}" self.SetGamutStatusText(gamut_cov_text) for channel in "rgb": @@ -1632,13 +1619,13 @@ def LoadProfile(self, profile, reset=True): if color.groups()[0] == "Lab": color = colormath.Lab2RGB( *[float(v) for v in color.groups()[1].strip().split()], - **dict(scale=255) + **dict(scale=255), ) else: # XYZ color = colormath.XYZ2RGB( *[float(v) for v in color.groups()[1].strip().split()], - **dict(scale=255) + **dict(scale=255), ) labelbgcolor = wx.Colour(*[int(round(v)) for v in color]) rowlabelrenderer = CustomRowLabelRenderer(labelbgcolor) @@ -1693,9 +1680,9 @@ def OnMotion(self, event): if page.colorspace in ("a*b*", "u*v*") or page.colorspace.startswith( "DIN99" ): - format = "%.2f %.2f" + format_ = "%.2f %.2f" else: - format = "%.4f %.4f" + format_ = "%.4f %.4f" whitepoint_no = page.whitepoint_select.GetSelection() if whitepoint_no > 0: if page.colorspace == "a*b*": @@ -1734,7 +1721,7 @@ def OnMotion(self, event): # xy x, y = xy cct, delta = colormath.xy_CCT_delta(x, y, daylight=whitepoint_no == 1) - status = format % xy + status = format_ % xy if cct: if delta: locus = {"Blackbody": "blackbody", "Daylight": "daylight"}.get( @@ -1742,16 +1729,16 @@ def OnMotion(self, event): page.whitepoint_select.GetStringSelection(), ) status = "%s, CCT %i (%s %.2f)" % ( - format % xy, + format_ % xy, cct, lang.getstr("delta_e_to_locus", locus), delta["E"], ) else: - status = "%s, CCT %i" % (format % xy, cct) + status = "%s, CCT %i" % (format_ % xy, cct) self.SetStatusText(status) else: - self.SetStatusText(format % xy) + self.SetStatusText(format_ % xy) if isinstance(event, wx.MouseEvent): event.Skip() # Go to next handler @@ -1834,11 +1821,11 @@ def get_platform_window_size( else: name = "" if not defaultwidth: - defaultwidth = defaults["size.profile_info%s.w" % name] + defaultwidth = defaults[f"size.profile_info{name}.w"] if not defaultheight: defaultheight = defaults["size.profile_info.h"] border, titlebar = get_platform_window_decoration_size() - # return (max(max(getcfg("size.profile_info%s.w" % name), + # return (max(max(getcfg("size.profile_info{name}.w"), # defaultwidth), self.GetMinSize()[0] - border * 2), # max(getcfg("size.profile_info.h"), # defaultheight)) @@ -2017,7 +2004,8 @@ def view_3d(self, event): return desc = profile.getDescription() profile_path = os.path.join( - self.worker.tempdir, f"{make_argyll_compatible_path(desc) }{profile_ext}" + self.worker.tempdir, + f"{make_argyll_compatible_path(desc) }{profile_ext}", ) profile.write(profile_path) profile_mtime = os.stat(profile_path).st_mtime @@ -2054,10 +2042,7 @@ def view_3d(self, event): mods.append(order) if mods: filename = "{} {}".format( - filename, - "".join( - ["[{}]".format(mod.upper() for mod in mods)] - ) + filename, "".join(["[{}]".format(mod.upper() for mod in mods)]) ) if comparison_profile_path: filename += ( @@ -2066,8 +2051,7 @@ def view_3d(self, event): ) if mods: filename = "{} {}".format( - filename, - "".join(["[%s]" % mod.upper() for mod in mods]) + filename, "".join([f"[{mod.upper()}]" for mod in mods]) ) for vrmlext in (".vrml", ".vrml.gz", ".wrl", ".wrl.gz", ".wrz"): vrmlpath = filename + vrmlext From 7f6f54c7a02056c363a1b40e2f4f75ad4c099f0a Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Mon, 5 Jun 2023 17:56:23 +0100 Subject: [PATCH 12/16] - Updated Makefile to introduce new targets. --- Makefile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Makefile b/Makefile index 656133372..d72a5e943 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ NUM_CPUS = $(shell nproc || grep -c '^processor' /proc/cpuinfo) SETUP_PY_FLAGS = --use-distutils +VERSION := $(shell cat VERSION_BASE) +VERSION_FILE=$(CURDIR)/VERSION_BASE all: build FORCE @@ -8,6 +10,7 @@ build: FORCE clean: FORCE -rm -rf build + -rm -rf .pytest_cache dist: util/sdist.sh @@ -16,6 +19,13 @@ distclean: clean FORCE -rm -f INSTALLED_FILES -rm -f setuptools-*.egg -rm -f use-distutils + -rm -rf dist + +clean-all: distclean + -rm MANIFEST.in + -rm VERSION + -rm -Rf DisplayCAL.egg-info + -rm DisplayCAL/__version__.py html: ./setup.py readme @@ -31,5 +41,19 @@ requirements: requirements.txt requirements-dev.txt uninstall: ./setup.py uninstall $(SETUP_PY_FLAGS) +new-release: + git add $(VERSION_FILE) + git commit -m "Version $(VERSION)" + git push + git checkout master + git merge develop + git tag $(VERSION) + git push origin master --tags + python -m build +# twine check dist/DisplayCAL-*.whl + twine check dist/DisplayCAL-*.tar.gz +# twine upload dist/DisplayCAL-*.whl + twine upload dist/DisplayCAL-*.tar.gz + # https://www.gnu.org/software/make/manual/html_node/Force-Targets.html FORCE: From c0358281560416805aced8d2d23d79a6acda92d4 Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Mon, 5 Jun 2023 17:57:11 +0100 Subject: [PATCH 13/16] Version 3.9.11 --- VERSION_BASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION_BASE b/VERSION_BASE index 0a590336d..a9f8d1be3 100644 --- a/VERSION_BASE +++ b/VERSION_BASE @@ -1 +1 @@ -3.9.10 +3.9.11 From 39e3f5d505f5c2df3cd1b591373d5b18312957de Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Mon, 5 Jun 2023 17:58:20 +0100 Subject: [PATCH 14/16] - Fixed main branch name in Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d72a5e943..9a54ad749 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ new-release: git add $(VERSION_FILE) git commit -m "Version $(VERSION)" git push - git checkout master + git checkout main git merge develop git tag $(VERSION) git push origin master --tags From 307ea0cb2cdcafeefc22d04f24245657092310bb Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Mon, 5 Jun 2023 18:01:21 +0100 Subject: [PATCH 15/16] - Fixed main branch name in Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9a54ad749..d281481af 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ new-release: git checkout main git merge develop git tag $(VERSION) - git push origin master --tags + git push origin main --tags python -m build # twine check dist/DisplayCAL-*.whl twine check dist/DisplayCAL-*.tar.gz From 542cf52459d12397d8f83c384d628b8dca6c49ff Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Mon, 5 Jun 2023 18:07:02 +0100 Subject: [PATCH 16/16] - Fixed new-release target in Makefile to do a pull before merging the develop branch. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d281481af..72f153f03 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ new-release: git commit -m "Version $(VERSION)" git push git checkout main + git pull git merge develop git tag $(VERSION) git push origin main --tags