cinnamon: Add patches to accelerate settings
Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
This commit is contained in:
@@ -29,6 +29,12 @@ inherit meson pkgconfig gobject-introspection gtk-icon-cache gsettings gtk-doc g
|
||||
SRC_URI = " \
|
||||
git://github.com/linuxmint/cinnamon.git;branch=master;protocol=https \
|
||||
file://0001-Do-not-crash-on-systemd-reporting-Univeral-timezone.patch \
|
||||
file://okaestne-settings-performance/0001-ExtensionCore-defer-loading-of-cinnamon-version-fix-.patch \
|
||||
file://okaestne-settings-performance/0002-cs_privacy-defer-init-of-NM.Client.patch \
|
||||
file://okaestne-settings-performance/0003-cs_backgrounds-defer-import-of-imtools-module.patch \
|
||||
file://okaestne-settings-performance/0004-Spices-defer-import-of-requests-module.patch \
|
||||
file://okaestne-settings-performance/0005-cs-fix-print_timing-remove-stale-touch-function.patch \
|
||||
file://okaestne-settings-performance/0006-cs-lazy-load-python-modules-when-passed-as-arg.patch \
|
||||
"
|
||||
SRCREV = "037b17248b176c7f3dd5c9848f8c6738105c4cc2"
|
||||
PV = "5.2.7+git${SRCPV}"
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
From 03599325d88f453b464f8c500fea0e758dd6a386 Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Sun, 3 Apr 2022 15:39:36 +0200
|
||||
Subject: [PATCH 1/6] ExtensionCore: defer loading of cinnamon version & fix
|
||||
comparison
|
||||
|
||||
* saves ~15ms at import time
|
||||
* fix: comparsion was able to fail because of string comparision
|
||||
e.g `['5', '8'] > ['5', '10']` is `True`
|
||||
---
|
||||
.../cinnamon-settings/bin/ExtensionCore.py | 34 ++++++++++---------
|
||||
1 file changed, 18 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/bin/ExtensionCore.py b/files/usr/share/cinnamon/cinnamon-settings/bin/ExtensionCore.py
|
||||
index 72d124c28..e616b08e1 100644
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/bin/ExtensionCore.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/bin/ExtensionCore.py
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
+from functools import lru_cache
|
||||
import os
|
||||
import re
|
||||
import html
|
||||
@@ -30,20 +31,22 @@ ROW_SIZE = 32
|
||||
|
||||
UNSAFE_ITEMS = ['spawn_sync', 'spawn_command_line_sync', 'GTop', 'get_file_contents_utf8_sync']
|
||||
|
||||
-curr_ver = subprocess.check_output(['cinnamon', '--version']).decode("utf-8").splitlines()[0].split(' ')[1]
|
||||
-curr_ver_elements = curr_ver.split(".")
|
||||
-curr_ver_major = int(curr_ver_elements[0])
|
||||
-curr_ver_minor = int(curr_ver_elements[1])
|
||||
-
|
||||
LANGUAGE_CODE = "C"
|
||||
try:
|
||||
LANGUAGE_CODE = locale.getlocale()[0].split("_")[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
+
|
||||
+@lru_cache(maxsize=None) # fetch only once
|
||||
+def get_cinnamon_version():
|
||||
+ version_str = subprocess.check_output(['cinnamon', '--version'], encoding="utf-8").split()[1]
|
||||
+ return [int(part) for part in version_str.split(".")]
|
||||
+
|
||||
+
|
||||
def find_extension_subdir(directory):
|
||||
- largest = ['0']
|
||||
- curr_a = curr_ver.split('.')
|
||||
+ largest = [0]
|
||||
+ curr_a = get_cinnamon_version()
|
||||
|
||||
for subdir in os.listdir(directory):
|
||||
if not os.path.isdir(os.path.join(directory, subdir)):
|
||||
@@ -52,15 +55,15 @@ def find_extension_subdir(directory):
|
||||
if not re.match(r'^[1-9][0-9]*\.[0-9]+(\.[0-9]+)?$', subdir):
|
||||
continue
|
||||
|
||||
- subdir_a = subdir.split(".")
|
||||
+ subdir_a = [int(part) for part in subdir.split(".")]
|
||||
|
||||
- if subdir_a < curr_a and largest < subdir_a:
|
||||
+ if subdir_a <= curr_a and largest < subdir_a:
|
||||
largest = subdir_a
|
||||
|
||||
- if len(largest) == 1:
|
||||
+ if largest == [0]:
|
||||
return directory
|
||||
else:
|
||||
- return os.path.join(directory, ".".join(largest))
|
||||
+ return os.path.join(directory, ".".join(map(str, largest)))
|
||||
|
||||
translations = {}
|
||||
|
||||
@@ -315,11 +318,11 @@ class ManageSpicesRow(Gtk.ListBoxRow):
|
||||
try:
|
||||
# Treat "cinnamon-version" as a list of minimum required versions
|
||||
# if any version in there is lower than our Cinnamon version, then the spice is compatible.
|
||||
+ curr_ver = get_cinnamon_version()
|
||||
+
|
||||
for version in self.metadata['cinnamon-version']:
|
||||
- elements = version.split(".")
|
||||
- major = int(elements[0])
|
||||
- minor = int(elements[1])
|
||||
- if curr_ver_major > major or (curr_ver_major == major and curr_ver_minor >= minor):
|
||||
+ spice_ver = [int(part) for part in version.split(".")]
|
||||
+ if spice_ver[:2] <= curr_ver:
|
||||
# The version is OK, check that we can find the right .js file in the appropriate subdir
|
||||
path = os.path.join(self.metadata['path'], self.extension_type + ".js")
|
||||
if os.path.exists(path):
|
||||
@@ -327,7 +330,6 @@ class ManageSpicesRow(Gtk.ListBoxRow):
|
||||
else:
|
||||
print ("The %s %s is not properly structured. Path not found: '%s'" % (self.uuid, self.extension_type, path))
|
||||
return False
|
||||
- return True
|
||||
print ("The %s %s is not compatible with this version of Cinnamon." % (self.uuid, self.extension_type))
|
||||
return False
|
||||
except:
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
From b20036b87aa78242e11b4e5f023b4f8586cfe1d9 Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Sun, 3 Apr 2022 17:49:43 +0200
|
||||
Subject: [PATCH 2/6] cs_privacy: defer init of NM.Client
|
||||
|
||||
saves ~10ms import time
|
||||
|
||||
also fix some imports
|
||||
---
|
||||
.../cinnamon-settings/modules/cs_privacy.py | 43 +++++++++++--------
|
||||
1 file changed, 24 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_privacy.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_privacy.py
|
||||
index a726b0776..26693b230 100755
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_privacy.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_privacy.py
|
||||
@@ -1,26 +1,16 @@
|
||||
#!/usr/bin/python3
|
||||
-
|
||||
-nm_client = None
|
||||
-try:
|
||||
- import gi
|
||||
- gi.require_version('NM', '1.0')
|
||||
- from gi.repository import NM
|
||||
- nm_client = NM.Client.new(None)
|
||||
- # call connectivity_check_get_available to make
|
||||
- # sure it's available (it's new in libnm 1.10)
|
||||
- # if it's not, we catch the exception and set
|
||||
- # the client to None
|
||||
- nm_client.connectivity_check_get_available()
|
||||
-except:
|
||||
- nm_client = None
|
||||
+import gi
|
||||
+gi.require_version('Gtk', '3.0')
|
||||
+from gi.repository import Gio, Gtk
|
||||
|
||||
from SettingsWidgets import SidePage
|
||||
-from xapp.GSettingsWidgets import *
|
||||
+from xapp.GSettingsWidgets import GSettingsSwitch, SettingsLabel, SettingsPage, SettingsRevealer, SettingsWidget, Switch
|
||||
|
||||
PRIVACY_SCHEMA = "org.cinnamon.desktop.privacy"
|
||||
GTK_RECENT_ENABLE_KEY = "remember-recent-files"
|
||||
GTK_RECENT_MAX_AGE = "recent-files-max-age"
|
||||
|
||||
+
|
||||
class Module:
|
||||
name = "privacy"
|
||||
comment = _("Cinnamon privacy settings")
|
||||
@@ -31,6 +21,19 @@ class Module:
|
||||
sidePage = SidePage(_("Privacy"), "cs-privacy", keywords, content_box, module=self)
|
||||
self.sidePage = sidePage
|
||||
self.settings = Gio.Settings(schema=PRIVACY_SCHEMA)
|
||||
+ self.nm_client = None
|
||||
+
|
||||
+ def _init_nm_client(self):
|
||||
+ try:
|
||||
+ gi.require_version('NM', '1.0')
|
||||
+ from gi.repository import NM
|
||||
+ nm_client = NM.Client.new()
|
||||
+
|
||||
+ # we need libnm >=1.10
|
||||
+ if hasattr(nm_client, 'connectivity_check_get_available'):
|
||||
+ self.nm_client = nm_client
|
||||
+ except ValueError:
|
||||
+ pass
|
||||
|
||||
def on_module_selected(self):
|
||||
if not self.loaded:
|
||||
@@ -77,14 +80,16 @@ class Module:
|
||||
else:
|
||||
self.indefinite_switch.content_widget.set_active(False)
|
||||
self.revealer.set_reveal_child(True)
|
||||
- if start_age == 0: # Shouldn't happen, unless someone manually sets the value
|
||||
+ if start_age == 0: # Shouldn't happen, unless someone manually sets the value
|
||||
self.settings.set_int(GTK_RECENT_MAX_AGE, 30)
|
||||
self.bind_spinner()
|
||||
|
||||
- if nm_client is not None and nm_client.connectivity_check_get_available():
|
||||
+ self._init_nm_client()
|
||||
+
|
||||
+ if self.nm_client is not None and self.nm_client.connectivity_check_get_available():
|
||||
section = page.add_section(_("Internet connectivity"))
|
||||
connectivity_switch = Switch(_("Check connectivity"))
|
||||
- connectivity_switch.content_widget.set_active(nm_client.connectivity_check_get_enabled())
|
||||
+ connectivity_switch.content_widget.set_active(self.nm_client.connectivity_check_get_enabled())
|
||||
connectivity_switch.content_widget.connect("notify::active", self.on_connectivity_toggled)
|
||||
section.add_row(connectivity_switch)
|
||||
section.add_note(_("Check that network connections can reach the Internet. This makes it possible to detect captive portals, but also generates periodic network traffic."))
|
||||
@@ -117,4 +122,4 @@ class Module:
|
||||
|
||||
def on_connectivity_toggled(self, widget, gparam):
|
||||
active = widget.get_active()
|
||||
- nm_client.connectivity_check_set_enabled(active)
|
||||
+ self.nm_client.connectivity_check_set_enabled(active)
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From b7f582e2500959e89c56837675cfe454892846ce Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Sun, 3 Apr 2022 23:59:22 +0200
|
||||
Subject: [PATCH 3/6] cs_backgrounds: defer import of imtools module
|
||||
|
||||
saves ~55ms import time
|
||||
---
|
||||
.../share/cinnamon/cinnamon-settings/modules/cs_backgrounds.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_backgrounds.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_backgrounds.py
|
||||
index c462177b7..5d772191b 100755
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_backgrounds.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_backgrounds.py
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
-import imtools
|
||||
import gettext
|
||||
import _thread as thread
|
||||
import subprocess
|
||||
@@ -623,6 +622,8 @@ class PixCache(object):
|
||||
img = img.convert("RGB")
|
||||
if size:
|
||||
img.thumbnail((size, size), Image.ANTIALIAS)
|
||||
+
|
||||
+ import imtools
|
||||
img = imtools.round_image(img, {}, False, None, 3, 255)
|
||||
img = imtools.drop_shadow(img, 4, 4, background_color=(255, 255, 255, 0),
|
||||
shadow_color=0x444444, border=8, shadow_blur=3,
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
From 1358b9df2b18fb7ecb5077cdf54b427cf47e26ac Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Mon, 4 Apr 2022 00:55:26 +0200
|
||||
Subject: [PATCH 4/6] Spices: defer import of requests module
|
||||
|
||||
saves ~25ms import time
|
||||
---
|
||||
files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py b/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py
|
||||
index f345243f3..348d9488d 100644
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/bin/Spices.py
|
||||
@@ -12,9 +12,7 @@ try:
|
||||
import threading
|
||||
from PIL import Image
|
||||
import datetime
|
||||
- import proxygsettings
|
||||
import time
|
||||
- import requests
|
||||
except Exception as detail:
|
||||
print(detail)
|
||||
sys.exit(1)
|
||||
@@ -382,6 +380,9 @@ class Spice_Harvester(GObject.Object):
|
||||
#Like the one in urllib. Unlike urllib.retrieve url_retrieve
|
||||
#can be interrupted. KeyboardInterrupt exception is raised when
|
||||
#interrupted.
|
||||
+ import proxygsettings
|
||||
+ import requests
|
||||
+
|
||||
count = 0
|
||||
blockSize = 1024 * 8
|
||||
proxy_info = proxygsettings.get_proxy_settings()
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0aa0e62dd49e74253d132c7bd9a900af03bbc421 Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Sat, 9 Apr 2022 18:50:32 +0200
|
||||
Subject: [PATCH 5/6] cs: fix print_timing; remove stale touch function
|
||||
|
||||
---
|
||||
.../cinnamon/cinnamon-settings/cinnamon-settings.py | 11 +++--------
|
||||
1 file changed, 3 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py b/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
index 65d4a3028..7dee496e0 100755
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
@@ -152,20 +152,15 @@ ARG_REWRITE = {
|
||||
|
||||
def print_timing(func):
|
||||
# decorate functions with @print_timing to output how long they take to run.
|
||||
- def wrapper(*arg):
|
||||
+ def wrapper(*args, **kwargs):
|
||||
t1 = time.time()
|
||||
- res = func(*arg)
|
||||
+ res = func(*args, **kwargs)
|
||||
t2 = time.time()
|
||||
- print('%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0))
|
||||
+ print('%s took %0.3f ms' % (func.__name__, (t2-t1)*1000.0))
|
||||
return res
|
||||
return wrapper
|
||||
|
||||
|
||||
-def touch(fname, times=None):
|
||||
- with open(fname, 'a'):
|
||||
- os.utime(fname, times)
|
||||
-
|
||||
-
|
||||
class MainWindow(Gio.Application):
|
||||
# Change pages
|
||||
def side_view_nav(self, side_view, path, cat):
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
From 7215d33cfb9a4fecc4dcf94ce4fd3d757d1bcf30 Mon Sep 17 00:00:00 2001
|
||||
From: okaestne <git@oliver-kaestner.de>
|
||||
Date: Sat, 9 Apr 2022 22:52:05 +0200
|
||||
Subject: [PATCH 6/6] cs: lazy load python modules, when passed as arg
|
||||
|
||||
---
|
||||
.../cinnamon-settings/cinnamon-settings.py | 358 ++++++++++--------
|
||||
1 file changed, 204 insertions(+), 154 deletions(-)
|
||||
|
||||
diff --git a/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py b/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
index 7dee496e0..41746c16f 100755
|
||||
--- a/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
+++ b/files/usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
|
||||
@@ -1,56 +1,47 @@
|
||||
#!/usr/bin/python3
|
||||
-
|
||||
-import getopt
|
||||
-import sys
|
||||
-
|
||||
from bin import util
|
||||
util.strip_syspath_locals()
|
||||
|
||||
-import os
|
||||
-import glob
|
||||
+from functools import cmp_to_key
|
||||
+import getopt
|
||||
import gettext
|
||||
+import glob
|
||||
+import locale
|
||||
+import os
|
||||
+from setproctitle import setproctitle
|
||||
+import sys
|
||||
import time
|
||||
import traceback
|
||||
-import locale
|
||||
-import urllib.request as urllib
|
||||
-from functools import cmp_to_key
|
||||
+import typing
|
||||
import unicodedata
|
||||
-import config
|
||||
-from setproctitle import setproctitle
|
||||
+import urllib.request as urllib
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('XApp', '1.0')
|
||||
from gi.repository import Gio, Gtk, Pango, Gdk, XApp
|
||||
|
||||
-sys.path.append(config.currentPath + "/modules")
|
||||
-sys.path.append(config.currentPath + "/bin")
|
||||
-import capi
|
||||
-import proxygsettings
|
||||
-import SettingsWidgets
|
||||
+import config
|
||||
+sys.path.append(os.path.join(config.currentPath, "bin"))
|
||||
+sys.path.append(os.path.join(config.currentPath, "modules"))
|
||||
+from bin import capi
|
||||
+from bin import proxygsettings
|
||||
+from bin import SettingsWidgets
|
||||
|
||||
# i18n
|
||||
gettext.install("cinnamon", "/usr/share/locale", names=["ngettext"])
|
||||
|
||||
-# Standard setting pages... this can be expanded to include applet dirs maybe?
|
||||
-mod_files = glob.glob(config.currentPath + "/modules/*.py")
|
||||
-mod_files.sort()
|
||||
-if len(mod_files) == 0:
|
||||
- print("No settings modules found!!")
|
||||
- sys.exit(1)
|
||||
-
|
||||
-mod_files = [x.split('/')[-1].split('.')[0] for x in mod_files]
|
||||
-
|
||||
-for mod_file in mod_files:
|
||||
- if mod_file[0:3] != "cs_":
|
||||
- raise Exception("Settings modules must have a prefix of 'cs_' !!")
|
||||
-
|
||||
-modules = map(__import__, mod_files)
|
||||
-
|
||||
# i18n for menu item
|
||||
menuName = _("System Settings")
|
||||
menuComment = _("Control Center")
|
||||
|
||||
+
|
||||
+class SidePageData(typing.NamedTuple):
|
||||
+ sp: SettingsWidgets.SidePage
|
||||
+ name: str
|
||||
+ cat: str
|
||||
+
|
||||
+
|
||||
WIN_WIDTH = 800
|
||||
WIN_HEIGHT = 600
|
||||
WIN_H_PADDING = 20
|
||||
@@ -169,7 +160,9 @@ class MainWindow(Gio.Application):
|
||||
self.deselect(cat)
|
||||
filtered_path = side_view.get_model().convert_path_to_child_path(selected_items[0])
|
||||
if filtered_path is not None:
|
||||
- self.go_to_sidepage(cat, filtered_path, user_action=True)
|
||||
+ iterator = self.store_by_cat[cat].get_iter(filtered_path)
|
||||
+ sidePage = self.store_by_cat[cat].get_value(iterator, 2)
|
||||
+ self.go_to_sidepage(sidePage, user_action=True)
|
||||
|
||||
def _on_sidepage_hide_stack(self):
|
||||
self.stack_switcher.set_opacity(0)
|
||||
@@ -177,57 +170,56 @@ class MainWindow(Gio.Application):
|
||||
def _on_sidepage_show_stack(self):
|
||||
self.stack_switcher.set_opacity(1)
|
||||
|
||||
- def go_to_sidepage(self, cat, path, user_action=True):
|
||||
- iterator = self.store[cat].get_iter(path)
|
||||
- sidePage = self.store[cat].get_value(iterator, 2)
|
||||
- if not sidePage.is_standalone:
|
||||
- if not user_action:
|
||||
- self.window.set_title(sidePage.name)
|
||||
- self.window.set_icon_name(sidePage.icon)
|
||||
- sidePage.build()
|
||||
- if sidePage.stack:
|
||||
- self.stack_switcher.set_stack(sidePage.stack)
|
||||
- l = sidePage.stack.get_children()
|
||||
- if len(l) > 0:
|
||||
- if self.tab in range(len(l)):
|
||||
- sidePage.stack.set_visible_child(l[self.tab])
|
||||
- visible_child = sidePage.stack.get_visible_child()
|
||||
- if self.tab == 1 \
|
||||
- and hasattr(visible_child, 'sort_combo') \
|
||||
- and self.sort in range(5):
|
||||
- visible_child.sort_combo.set_active(self.sort)
|
||||
- visible_child.sort_changed()
|
||||
- else:
|
||||
- sidePage.stack.set_visible_child(l[0])
|
||||
- if sidePage.stack.get_visible():
|
||||
- self.stack_switcher.set_opacity(1)
|
||||
- else:
|
||||
- self.stack_switcher.set_opacity(0)
|
||||
- if hasattr(sidePage, "connect_proxy"):
|
||||
- sidePage.connect_proxy("hide_stack", self._on_sidepage_hide_stack)
|
||||
- sidePage.connect_proxy("show_stack", self._on_sidepage_show_stack)
|
||||
+ def go_to_sidepage(self, sidePage: SettingsWidgets.SidePage, user_action=True):
|
||||
+ sidePage.build()
|
||||
+
|
||||
+ if sidePage.is_standalone:
|
||||
+ return # we're done
|
||||
+
|
||||
+ if not user_action:
|
||||
+ self.window.set_title(sidePage.name)
|
||||
+ self.window.set_icon_name(sidePage.icon)
|
||||
+
|
||||
+ if sidePage.stack:
|
||||
+ self.stack_switcher.set_stack(sidePage.stack)
|
||||
+ l = sidePage.stack.get_children()
|
||||
+ if len(l) > 0:
|
||||
+ if self.tab in range(len(l)):
|
||||
+ sidePage.stack.set_visible_child(l[self.tab])
|
||||
+ visible_child = sidePage.stack.get_visible_child()
|
||||
+ if self.tab == 1 \
|
||||
+ and hasattr(visible_child, 'sort_combo') \
|
||||
+ and self.sort in range(5):
|
||||
+ visible_child.sort_combo.set_active(self.sort)
|
||||
+ visible_child.sort_changed()
|
||||
+ else:
|
||||
+ sidePage.stack.set_visible_child(l[0])
|
||||
+ if sidePage.stack.get_visible():
|
||||
+ self.stack_switcher.set_opacity(1)
|
||||
else:
|
||||
self.stack_switcher.set_opacity(0)
|
||||
+ if hasattr(sidePage, "connect_proxy"):
|
||||
+ sidePage.connect_proxy("hide_stack", self._on_sidepage_hide_stack)
|
||||
+ sidePage.connect_proxy("show_stack", self._on_sidepage_show_stack)
|
||||
else:
|
||||
self.stack_switcher.set_opacity(0)
|
||||
+ else:
|
||||
+ self.stack_switcher.set_opacity(0)
|
||||
|
||||
- if user_action:
|
||||
- self.main_stack.set_visible_child_name("content_box_page")
|
||||
- self.header_stack.set_visible_child_name("content_box")
|
||||
-
|
||||
- else:
|
||||
- self.main_stack.set_visible_child_full("content_box_page", Gtk.StackTransitionType.NONE)
|
||||
- self.header_stack.set_visible_child_full("content_box", Gtk.StackTransitionType.NONE)
|
||||
-
|
||||
- self.current_sidepage = sidePage
|
||||
- width = 0
|
||||
- for widget in self.top_bar:
|
||||
- m, n = widget.get_preferred_width()
|
||||
- width += n
|
||||
- self.top_bar.set_size_request(width + 20, -1)
|
||||
- self.maybe_resize(sidePage)
|
||||
+ if user_action:
|
||||
+ self.main_stack.set_visible_child_name("content_box_page")
|
||||
+ self.header_stack.set_visible_child_name("content_box")
|
||||
else:
|
||||
- sidePage.build()
|
||||
+ self.main_stack.set_visible_child_full("content_box_page", Gtk.StackTransitionType.NONE)
|
||||
+ self.header_stack.set_visible_child_full("content_box", Gtk.StackTransitionType.NONE)
|
||||
+
|
||||
+ self.current_sidepage = sidePage
|
||||
+ width = 0
|
||||
+ for widget in self.top_bar:
|
||||
+ m, n = widget.get_preferred_width()
|
||||
+ width += n
|
||||
+ self.top_bar.set_size_request(width + 20, -1)
|
||||
+ self.maybe_resize(sidePage)
|
||||
|
||||
def maybe_resize(self, sidePage):
|
||||
m, n = self.content_box.get_preferred_size()
|
||||
@@ -260,7 +252,7 @@ class MainWindow(Gio.Application):
|
||||
flags=Gio.ApplicationFlags.NON_UNIQUE | Gio.ApplicationFlags.HANDLES_OPEN)
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.set_translation_domain('cinnamon') # let it translate!
|
||||
- self.builder.add_from_file(config.currentPath + "/cinnamon-settings.ui")
|
||||
+ self.builder.add_from_file(os.path.join(config.currentPath, "cinnamon-settings.ui"))
|
||||
self.window = XApp.GtkWindow(window_position=Gtk.WindowPosition.CENTER,
|
||||
default_width=800, default_height=600)
|
||||
|
||||
@@ -298,8 +290,7 @@ class MainWindow(Gio.Application):
|
||||
self.window.connect("destroy", self._quit)
|
||||
|
||||
self.builder.connect_signals(self)
|
||||
- self.unsortedSidePages = []
|
||||
- self.sidePages = []
|
||||
+ self.sidePages: typing.List[SidePageData] = []
|
||||
self.settings = Gio.Settings.new("org.cinnamon")
|
||||
self.current_cat_widget = None
|
||||
|
||||
@@ -308,58 +299,61 @@ class MainWindow(Gio.Application):
|
||||
self.content_box.c_manager = self.c_manager
|
||||
self.bar_heights = 0
|
||||
|
||||
- for module in modules:
|
||||
- try:
|
||||
- mod = module.Module(self.content_box)
|
||||
- if self.loadCheck(mod) and self.setParentRefs(mod):
|
||||
- self.unsortedSidePages.append((mod.sidePage, mod.name, mod.category))
|
||||
- except:
|
||||
- print("Failed to load module %s" % module)
|
||||
- traceback.print_exc()
|
||||
+ self.tab = 0 # open 'manage' tab by default
|
||||
+ self.sort = 1 # sorted by 'score' by default
|
||||
|
||||
- for item in CONTROL_CENTER_MODULES:
|
||||
- ccmodule = SettingsWidgets.CCModule(item[0], item[1], item[2], item[3], item[4], self.content_box)
|
||||
- if ccmodule.process(self.c_manager):
|
||||
- self.unsortedSidePages.append((ccmodule.sidePage, ccmodule.name, ccmodule.category))
|
||||
+ self.store_by_cat: typing.Dict[str, Gtk.ListStore] = {}
|
||||
+ self.storeFilter = {}
|
||||
|
||||
- for item in STANDALONE_MODULES:
|
||||
- samodule = SettingsWidgets.SAModule(item[0], item[1], item[2], item[3], item[4], self.content_box)
|
||||
- if samodule.process():
|
||||
- self.unsortedSidePages.append((samodule.sidePage, samodule.name, samodule.category))
|
||||
+ # load CCC and standalone modules, but not python modules yet
|
||||
+ self.load_ccc_modules()
|
||||
+ self.load_standalone_modules()
|
||||
|
||||
- # sort the modules alphabetically according to the current locale
|
||||
+ # if a certain sidepage is given via arguments, try to load only it
|
||||
+ if len(sys.argv) > 1:
|
||||
+ if self.load_sidepage_as_standalone():
|
||||
+ return
|
||||
+
|
||||
+ self.init_settings_overview()
|
||||
+
|
||||
+ def init_settings_overview(self):
|
||||
+ """Load the system settings overview (default)
|
||||
+
|
||||
+ This requires to initialize all settings modules.
|
||||
+ """
|
||||
+ # 1. load all python modules
|
||||
+ self.load_python_modules()
|
||||
+
|
||||
+ # 2. sort the modules alphabetically according to the current locale
|
||||
localeStrKey = cmp_to_key(locale.strcoll)
|
||||
# Apply locale key to the field name of each side page.
|
||||
sidePagesKey = lambda m: localeStrKey(m[0].name)
|
||||
- self.sidePages = sorted(self.unsortedSidePages, key=sidePagesKey)
|
||||
+ self.sidePages = sorted(self.sidePages, key=sidePagesKey)
|
||||
|
||||
- # create the backing stores for the side nav-view.
|
||||
- sidePagesIters = {}
|
||||
- self.store = {}
|
||||
- self.storeFilter = {}
|
||||
+ # 3. create the backing stores for the side nav-view.
|
||||
for sidepage in self.sidePages:
|
||||
sp, sp_id, sp_cat = sidepage
|
||||
- if sp_cat not in self.store: # Label Icon sidePage Category
|
||||
- self.store[sidepage[2]] = Gtk.ListStore(str, str, object, str)
|
||||
+ if sidepage.cat not in self.store_by_cat:
|
||||
+ self.store_by_cat[sidepage.cat] = Gtk.ListStore(str, str, object, str) # Label, Icon, sidePage, Category
|
||||
for category in CATEGORIES:
|
||||
- if category["id"] == sp_cat:
|
||||
+ if category["id"] == sidepage.cat:
|
||||
category["show"] = True
|
||||
|
||||
# Don't allow item names (and their translations) to be more than 30 chars long. It looks ugly and it creates huge gaps in the icon views
|
||||
name = sp.name
|
||||
if len(name) > 30:
|
||||
name = "%s..." % name[:30]
|
||||
- sidePagesIters[sp_id] = (self.store[sp_cat].append([name, sp.icon, sp, sp_cat]), sp_cat)
|
||||
+ self.store_by_cat[sp_cat].append([name, sp.icon, sp, sp_cat])
|
||||
|
||||
self.min_label_length = 0
|
||||
self.min_pix_length = 0
|
||||
|
||||
- for key in self.store:
|
||||
- char, pix = self.get_label_min_width(self.store[key])
|
||||
+ for cat in self.store_by_cat:
|
||||
+ char, pix = self.get_label_min_width(self.store_by_cat[cat])
|
||||
self.min_label_length = max(char, self.min_label_length)
|
||||
self.min_pix_length = max(pix, self.min_pix_length)
|
||||
- self.storeFilter[key] = self.store[key].filter_new()
|
||||
- self.storeFilter[key].set_visible_func(self.filter_visible_function)
|
||||
+ self.storeFilter[cat] = self.store_by_cat[cat].filter_new()
|
||||
+ self.storeFilter[cat].set_visible_func(self.filter_visible_function)
|
||||
|
||||
self.min_label_length += 2
|
||||
self.min_pix_length += 4
|
||||
@@ -378,38 +372,55 @@ class MainWindow(Gio.Application):
|
||||
|
||||
self.calculate_bar_heights()
|
||||
|
||||
- self.tab = 0 # open 'manage' tab by default
|
||||
- self.sort = 1 # sorted by 'score' by default
|
||||
+ self.search_entry.grab_focus()
|
||||
+ self.window.connect("key-press-event", self.on_keypress)
|
||||
+ self.window.connect("button-press-event", self.on_buttonpress)
|
||||
+
|
||||
+ self.window.show()
|
||||
+
|
||||
+ def load_sidepage_as_standalone(self) -> bool:
|
||||
+ """
|
||||
+ When an explicit sidepage is given as an argument,
|
||||
+ try load only this module to save much startup time.
|
||||
+
|
||||
+ Analyses arguments to know the tab to open
|
||||
+ and the sort to apply if the tab is the 'more' one.
|
||||
+
|
||||
+ Examples:
|
||||
+ ```
|
||||
+ cinnamon-settings.py applets --tab=more --sort=date
|
||||
+ cinnamon-settings.py applets --tab=1 --sort=2
|
||||
+ cinnamon-settings.py applets --tab=more --sort=date
|
||||
+ cinnamon-settings.py applets --tab=1 -s 2
|
||||
+ cinnamon-settings.py applets -t 1 -s installed
|
||||
+ cinnamon-settings.py desklets -t 2
|
||||
+ ```
|
||||
+ Please note that useless or wrong arguments are ignored.
|
||||
+
|
||||
+ :return: True if sidepage was loaded successfully, False otherwise
|
||||
+ """
|
||||
+ if sys.argv == 1:
|
||||
+ return False
|
||||
|
||||
- # Select the first sidePage
|
||||
+ # (1) get the settings sidepage name and rewrite it if necessary
|
||||
+ sidepage_name = ARG_REWRITE.get(sys.argv[1], sys.argv[1])
|
||||
+ # pop the arg once we consume it so we don't pass it go Gio.application.run
|
||||
+ sys.argv.pop(1)
|
||||
+
|
||||
+ # (2) Try to load a matching python module.
|
||||
+ # Note: the requested module could also be a CCC or SA module (which are always loaded by __init__())
|
||||
+ self.load_python_modules(only_module=sidepage_name)
|
||||
+
|
||||
+ # (3) set tab to show and/or spices sorting if specified via args
|
||||
if len(sys.argv) > 1:
|
||||
- arg1 = sys.argv[1]
|
||||
- if arg1 in ARG_REWRITE.keys():
|
||||
- arg1 = ARG_REWRITE[arg1]
|
||||
- if len(sys.argv) > 1 and arg1 in sidePagesIters:
|
||||
- # Analyses arguments to know the tab to open
|
||||
- # and the sort to apply if the tab is the 'more' one.
|
||||
- # Examples:
|
||||
- # cinnamon-settings.py applets --tab=more --sort=date
|
||||
- # cinnamon-settings.py applets --tab=1 --sort=2
|
||||
- # cinnamon-settings.py applets --tab=more --sort=date
|
||||
- # cinnamon-settings.py applets --tab=1 -s 2
|
||||
- # cinnamon-settings.py applets -t 1 -s installed
|
||||
- # cinnamon-settings.py desklets -t 2
|
||||
- # Please note that useless or wrong arguments are ignored.
|
||||
opts = []
|
||||
sorts_literal = {"name":0, "score":1, "date":2, "installed":3, "update":4}
|
||||
- tabs_literal = {"default":0}
|
||||
- if arg1 in TABS.keys():
|
||||
- tabs_literal = TABS[arg1]
|
||||
+ tabs_literal = TABS.get(sidepage_name, {"default": 0})
|
||||
|
||||
try:
|
||||
- if len(sys.argv) > 2:
|
||||
- opts = getopt.getopt(sys.argv[2:], "t:s:", ["tab=", "sort="])[0]
|
||||
+ opts = getopt.getopt(sys.argv[1:], "t:s:", ["tab=", "sort="])[0]
|
||||
except getopt.GetoptError:
|
||||
- pass
|
||||
- # pop the arg once we consume it so we don't pass it go Gio.application.run
|
||||
- sys.argv.pop(1)
|
||||
+ pass # ignore unknown args
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ("-t", "--tab"):
|
||||
@@ -426,30 +437,69 @@ class MainWindow(Gio.Application):
|
||||
sys.argv.remove(opt)
|
||||
sys.argv.remove(arg)
|
||||
|
||||
- # If we're launching a module directly, set the WM class so GWL
|
||||
- # can consider it as a standalone app and give it its own
|
||||
- # group.
|
||||
- wm_class = "cinnamon-settings %s" % arg1
|
||||
- self.window.set_wmclass(wm_class, wm_class)
|
||||
- self.button_back.hide()
|
||||
- (iter, cat) = sidePagesIters[arg1]
|
||||
- path = self.store[cat].get_path(iter)
|
||||
- if path:
|
||||
- self.go_to_sidepage(cat, path, user_action=False)
|
||||
- self.window.show()
|
||||
- if arg1 in ("mintlocale", "blueberry", "system-config-printer", "mintlocale-im", "nvidia-settings"):
|
||||
+ # (4) set the WM class so GWL can consider it as a standalone app and give it its own group.
|
||||
+ wm_class = f"cinnamon-settings {sidepage_name}"
|
||||
+ self.window.set_wmclass(wm_class, wm_class)
|
||||
+ self.button_back.hide()
|
||||
+
|
||||
+ # (5) find and show it
|
||||
+ for sp_data in self.sidePages:
|
||||
+ if sp_data.name == sidepage_name:
|
||||
+ self.go_to_sidepage(sp_data.sp, user_action=False)
|
||||
+ if sp_data.sp.is_standalone:
|
||||
# These modules do not need to leave the System Settings window open,
|
||||
# when selected by command line argument.
|
||||
self.window.close()
|
||||
+ else:
|
||||
+ self.window.show()
|
||||
+ return True
|
||||
+ print(f"warning: settings module {sidepage_name} not found.")
|
||||
+ return False
|
||||
+
|
||||
+ def load_ccc_modules(self):
|
||||
+ """Loads all Cinnamon Control Center settings modules."""
|
||||
+ for item in CONTROL_CENTER_MODULES:
|
||||
+ ccmodule = SettingsWidgets.CCModule(item[0], item[1], item[2], item[3], item[4], self.content_box)
|
||||
+ if ccmodule.process(self.c_manager):
|
||||
+ self.sidePages.append(SidePageData(ccmodule.sidePage, ccmodule.name, ccmodule.category))
|
||||
else:
|
||||
- self.search_entry.grab_focus()
|
||||
- self.window.show()
|
||||
- else:
|
||||
- self.search_entry.grab_focus()
|
||||
- self.window.connect("key-press-event", self.on_keypress)
|
||||
- self.window.connect("button-press-event", self.on_buttonpress)
|
||||
+ print("warning: failed to process CCC module", item[1])
|
||||
+
|
||||
+ def load_standalone_modules(self):
|
||||
+ """Loads all standalone settings modules."""
|
||||
+ for item in STANDALONE_MODULES:
|
||||
+ samodule = SettingsWidgets.SAModule(item[0], item[1], item[2], item[3], item[4], self.content_box)
|
||||
+ if samodule.process():
|
||||
+ self.sidePages.append(SidePageData(samodule.sidePage, samodule.name, samodule.category))
|
||||
+ # else:
|
||||
+ # print(f"note: skipped standalone module {samodule.name} (not found in PATH).")
|
||||
+
|
||||
+ def load_python_modules(self, only_module: str = None) -> bool:
|
||||
+ """Loads all or only a given settings module(s) written in python.
|
||||
+
|
||||
+ :param only_module: (optional) module name to be loaded exclusively
|
||||
+ :return: True if successful, False otherwise
|
||||
+ """
|
||||
+ # Standard setting pages... this can be expanded to include applet dirs maybe?
|
||||
+ mod_files = glob.glob(os.path.join(config.currentPath, 'modules', 'cs_*.py'))
|
||||
+ if len(mod_files) == 0:
|
||||
+ print("warning: no python settings modules found!!", file=sys.stderr)
|
||||
+ return False
|
||||
+
|
||||
+ to_import = [os.path.splitext(os.path.basename(x))[0] for x in mod_files]
|
||||
+
|
||||
+ if only_module is not None:
|
||||
+ to_import = filter(lambda mod: only_module in mod, to_import)
|
||||
|
||||
- self.window.show()
|
||||
+ for module in map(__import__, to_import):
|
||||
+ try:
|
||||
+ mod = module.Module(self.content_box)
|
||||
+ if self.loadCheck(mod) and self.setParentRefs(mod):
|
||||
+ self.sidePages.append(SidePageData(mod.sidePage, mod.name, mod.category))
|
||||
+ except:
|
||||
+ print(f"failed to load python module {module}", file=sys.stderr)
|
||||
+ traceback.print_exc()
|
||||
+ return True
|
||||
|
||||
# If there are no arguments, do_active() is called, otherwise do_open().
|
||||
def do_activate(self):
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Patches taken at 2022-05-05 / see https://github.com/linuxmint/cinnamon/pull/10735
|
||||
|
||||
Reference in New Issue
Block a user