From edeed3dc652fa78f555def59ff4fffa2f75e3613 Mon Sep 17 00:00:00 2001 From: dmiller Date: Thu, 17 Apr 2025 04:21:21 +0000 Subject: [PATCH] Zenmap dark mode. Fixes #2358 --- CHANGELOG | 3 +++ zenmap/zenmapCore/UmitConf.py | 33 +++++++++++++++++++++------------ zenmap/zenmapGUI/MainWindow.py | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index df5fa0a68..56b0a08eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ #Nmap Changelog ($Id$); -*-text-*- +o [Zenmap][GH#2358] Added dark mode, accessed via Help->Toggle Dark Mode or + window::dark_mode in zenmap.conf. [Daniel Miller] + o Upgraded included libraries: Lua 5.4.7, libssh2 1.11.1, libpcap 1.10.5, libpcre 10.45 diff --git a/zenmap/zenmapCore/UmitConf.py b/zenmap/zenmapCore/UmitConf.py index 876378a05..3f602e90b 100644 --- a/zenmap/zenmapCore/UmitConf.py +++ b/zenmap/zenmapCore/UmitConf.py @@ -84,6 +84,14 @@ except ImportError: def is_maemo(): return MAEMO +def boolean_sanity(attr): + if attr is True or \ + attr == "True" or \ + attr == "true" or \ + attr == "1": + return "True" + return "False" + class SearchConfig(UmitConfigParser, object): section_name = "search" @@ -109,14 +117,6 @@ class SearchConfig(UmitConfigParser, object): def _set_it(self, p_name, value): config_parser.set(self.section_name, p_name, value) - def boolean_sanity(self, attr): - if attr is True or \ - attr == "True" or \ - attr == "true" or \ - attr == "1": - return "True" - return "False" - def get_directory(self): return self._get_it("directory", "") @@ -142,16 +142,16 @@ class SearchConfig(UmitConfigParser, object): self._set_it("save_time", save_time) def get_store_results(self): - return self.boolean_sanity(self._get_it("store_results", True)) + return boolean_sanity(self._get_it("store_results", True)) def set_store_results(self, store_results): - self._set_it("store_results", self.boolean_sanity(store_results)) + self._set_it("store_results", boolean_sanity(store_results)) def get_search_db(self): - return self.boolean_sanity(self._get_it("search_db", True)) + return boolean_sanity(self._get_it("search_db", True)) def set_search_db(self, search_db): - self._set_it("search_db", self.boolean_sanity(search_db)) + self._set_it("search_db", boolean_sanity(search_db)) def get_converted_save_time(self): try: @@ -251,6 +251,7 @@ class WindowConfig(UmitConfigParser, object): default_y = 0 default_width = -1 default_height = 650 + default_dark_mode = False def __init__(self): if not config_parser.has_section(self.section_name): @@ -265,6 +266,7 @@ class WindowConfig(UmitConfigParser, object): self.y = self.default_y self.width = self.default_width self.height = self.default_height + self.dark_mode = self.default_dark_mode def _get_it(self, p_name, default): return config_parser.get(self.section_name, p_name, fallback=default) @@ -340,10 +342,17 @@ class WindowConfig(UmitConfigParser, object): def set_height(self, height): self._set_it("height", "%d" % height) + def get_dark_mode(self): + return boolean_sanity(self._get_it("dark_mode", self.default_dark_mode)) + + def set_dark_mode(self, mode): + self._set_it("dark_mode", boolean_sanity(mode)) + x = property(get_x, set_x) y = property(get_y, set_y) width = property(get_width, set_width) height = property(get_height, set_height) + dark_mode = property(get_dark_mode, set_dark_mode) class CommandProfile (Profile, object): diff --git a/zenmap/zenmapGUI/MainWindow.py b/zenmap/zenmapGUI/MainWindow.py index ca0d7f452..afefe76b6 100644 --- a/zenmap/zenmapGUI/MainWindow.py +++ b/zenmap/zenmapGUI/MainWindow.py @@ -132,6 +132,9 @@ class ScanWindow(UmitScanWindow): UmitScanWindow.__init__(self) window = WindowConfig() + settings = Gtk.Settings.get_default() + settings.set_property("gtk-application-prefer-dark-theme", + window.dark_mode) self.set_title(_(APP_DISPLAY_NAME)) self.move(window.x, window.y) @@ -303,6 +306,13 @@ class ScanWindow(UmitScanWindow): None, _('Shows the application help'), self._help_cb), + + ('Toggle Dark Mode', + None, + _('Toggle Dark Mode'), + None, + None, + self._toggle_dark), ] # See info on UIManager at: @@ -351,6 +361,7 @@ class ScanWindow(UmitScanWindow): + @@ -767,6 +778,14 @@ This scan has not been run yet. Start the scan with the "Scan" button first.')) def _help_cb(self, action): self.show_help() + def _toggle_dark(self, action): + window = WindowConfig() + window.dark_mode = not window.dark_mode + settings = Gtk.Settings.get_default() + settings.set_property("gtk-application-prefer-dark-theme", + window.dark_mode) + + def _exit_cb(self, *args): """Closes the window, prompting for confirmation if necessary. If one of the tabs couldn't be closed, the function returns True and doesn't