5757)
5858DEFAULT_LISTS_DIR = os .path .join (xdg_config_home , "opensnitch" , "list_subscriptions" )
5959PLUGIN_DIR = os .path .abspath (os .path .dirname (__file__ ))
60+ RES_DIR = os .path .join (PLUGIN_DIR , "res" )
6061LIST_SUBSCRIPTIONS_DIALOG_UI_PATH = os .path .join (
61- PLUGIN_DIR , "list_subscriptions_dialog.ui"
62+ RES_DIR , "list_subscriptions_dialog.ui"
6263)
63- SUBSCRIPTION_DIALOG_UI_PATH = os .path .join (PLUGIN_DIR , "subscription_dialog.ui" )
64- BULK_EDIT_DIALOG_UI_PATH = os .path .join (PLUGIN_DIR , "bulk_edit_dialog.ui" )
64+ SUBSCRIPTION_DIALOG_UI_PATH = os .path .join (RES_DIR , "subscription_dialog.ui" )
65+ BULK_EDIT_DIALOG_UI_PATH = os .path .join (RES_DIR , "bulk_edit_dialog.ui" )
6566
6667SubscriptionDialogUI = uic .loadUiType (SUBSCRIPTION_DIALOG_UI_PATH )[0 ] # type: ignore
6768BulkEditDialogUI = uic .loadUiType (BULK_EDIT_DIALOG_UI_PATH )[0 ] # type: ignore
9495logger = logging .getLogger (__name__ )
9596
9697
98+ class KeepForegroundOnSelectionDelegate (QtWidgets .QStyledItemDelegate ):
99+ def initStyleOption (self , option , index ):
100+ super ().initStyleOption (option , index )
101+ if option is None or index is None :
102+ return
103+ foreground = index .data (QtCore .Qt .ItemDataRole .ForegroundRole )
104+ if foreground is None :
105+ return
106+ brush = foreground if isinstance (foreground , QtGui .QBrush ) else QtGui .QBrush (foreground )
107+ option .palette .setBrush (
108+ QtGui .QPalette .ColorRole .Text ,
109+ brush ,
110+ )
111+ option .palette .setBrush (
112+ QtGui .QPalette .ColorRole .HighlightedText ,
113+ brush ,
114+ )
115+
116+
97117class SubscriptionDialog (QtWidgets .QDialog , SubscriptionDialogUI ):
98118 _url_test_finished = QtCore .pyqtSignal (bool , str )
99119
@@ -809,7 +829,7 @@ def _build_ui(self):
809829 self .table .setColumnCount (19 )
810830 self .table .setHorizontalHeaderLabels (
811831 [
812- QC . translate ( "stats" , "Enabled" ) ,
832+ "☑" ,
813833 QC .translate ("stats" , "Name" ),
814834 QC .translate ("stats" , "URL" ),
815835 QC .translate ("stats" , "Filename" ),
@@ -855,9 +875,32 @@ def _build_ui(self):
855875 self .table .setSelectionMode (
856876 QtWidgets .QAbstractItemView .SelectionMode .ExtendedSelection
857877 )
878+ state_delegate = KeepForegroundOnSelectionDelegate (self .table )
879+ for col in (
880+ COL_STATE ,
881+ COL_LAST_CHECKED ,
882+ COL_LAST_UPDATED ,
883+ ):
884+ self .table .setItemDelegateForColumn (col , state_delegate )
858885 header = self .table .horizontalHeader ()
859886 if header is not None :
860887 header .setStretchLastSection (True )
888+ header .setSectionResizeMode (
889+ COL_ENABLED , QtWidgets .QHeaderView .ResizeMode .Fixed
890+ )
891+ style = self .table .style ()
892+ if style is not None :
893+ indicator_w = style .pixelMetric (
894+ QtWidgets .QStyle .PixelMetric .PM_IndicatorWidth ,
895+ None ,
896+ self .table ,
897+ )
898+ indicator_h = style .pixelMetric (
899+ QtWidgets .QStyle .PixelMetric .PM_IndicatorHeight ,
900+ None ,
901+ self .table ,
902+ )
903+ self .table .setColumnWidth (COL_ENABLED , max (indicator_w , indicator_h ) + 12 )
861904 header .setSectionResizeMode (
862905 COL_URL , QtWidgets .QHeaderView .ResizeMode .Stretch
863906 )
@@ -1261,22 +1304,23 @@ def refresh_states(self):
12611304 last_updated = str (meta .get ("last_updated" , "" )) if meta else ""
12621305 fail_count = str (meta .get ("fail_count" , 0 )) if meta else "0"
12631306 last_error = str (meta .get ("last_error" , "" )) if meta else ""
1307+ fg_color : QtGui .QColor
12641308
12651309 if not enabled :
12661310 state = "disabled"
1267- color = QtGui . QColor ( "lightgray " )
1311+ fg_color = self . _state_text_color ( "disabled " )
12681312 elif not file_exists :
12691313 # New/manual subscriptions may not be downloaded yet.
12701314 # Expose that as pending instead of an error-like missing state.
12711315 if not meta_exists or last_result in ("never" , "" , "busy" ):
12721316 state = "pending"
1273- color = QtGui . QColor ( "khaki " )
1317+ fg_color = self . _state_text_color ( "pending " )
12741318 else :
12751319 state = "missing"
1276- color = QtGui . QColor ( "tomato " )
1320+ fg_color = self . _state_text_color ( "missing " )
12771321 elif last_result in ("updated" , "not_modified" ):
12781322 state = last_result
1279- color = QtGui . QColor ( "lightgreen" )
1323+ fg_color = self . _state_text_color ( last_result )
12801324 elif last_result in (
12811325 "error" ,
12821326 "write_error" ,
@@ -1286,13 +1330,13 @@ def refresh_states(self):
12861330 "too_large" ,
12871331 ):
12881332 state = last_result
1289- color = QtGui . QColor ( "salmon" )
1333+ fg_color = self . _state_text_color ( last_result )
12901334 elif last_result == "busy" :
12911335 state = "busy"
1292- color = QtGui . QColor ( "khaki " )
1336+ fg_color = self . _state_text_color ( "busy " )
12931337 else :
12941338 state = last_result
1295- color = QtGui . QColor ( "lightyellow " )
1339+ fg_color = self . _state_text_color ( "other " )
12961340
12971341 self ._set_text_item (
12981342 row , COL_FILE , "yes" if file_exists else "no" , editable = False
@@ -1317,7 +1361,46 @@ def refresh_states(self):
13171361 ):
13181362 item = self .table .item (row , col )
13191363 if item is not None :
1320- item .setBackground (color )
1364+ item .setForeground (fg_color )
1365+
1366+ def _state_text_color (self , state : str ):
1367+ palette = self .table .palette ()
1368+ dark_theme = palette .base ().color ().lightness () < 128
1369+
1370+ if dark_theme :
1371+ colors = {
1372+ "disabled" : "#B8C0CC" ,
1373+ "pending" : "#F5D76E" ,
1374+ "busy" : "#F5D76E" ,
1375+ "missing" : "#FF8A80" ,
1376+ "updated" : "#7CE3A1" ,
1377+ "not_modified" : "#86C5FF" ,
1378+ "error" : "#FF8A80" ,
1379+ "write_error" : "#FF8A80" ,
1380+ "request_error" : "#FF8A80" ,
1381+ "unexpected_error" : "#FF8A80" ,
1382+ "bad_format" : "#FF8A80" ,
1383+ "too_large" : "#FF8A80" ,
1384+ "other" : "#F7E37A" ,
1385+ }
1386+ else :
1387+ colors = {
1388+ "disabled" : "#6B7280" ,
1389+ "pending" : "#9A6700" ,
1390+ "busy" : "#9A6700" ,
1391+ "missing" : "#C62828" ,
1392+ "updated" : "#0F8A4B" ,
1393+ "not_modified" : "#1565C0" ,
1394+ "error" : "#C62828" ,
1395+ "write_error" : "#C62828" ,
1396+ "request_error" : "#C62828" ,
1397+ "unexpected_error" : "#C62828" ,
1398+ "bad_format" : "#C62828" ,
1399+ "too_large" : "#C62828" ,
1400+ "other" : "#8D6E00" ,
1401+ }
1402+
1403+ return QtGui .QColor (colors .get (state , colors ["other" ]))
13211404
13221405 def add_subscription_row (self ):
13231406 dlg = SubscriptionDialog (
0 commit comments