Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tuneit
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ximper Linux
tuneit
Commits
9dfbac49
Verified
Commit
9dfbac49
authored
Jan 29, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
widgets/theme_chooser: improve style
parent
82236502
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
103 additions
and
59 deletions
+103
-59
ThemeChooserWidget.py
src/settings/setting/widgets/ThemeChooserWidget.py
+103
-59
No files found.
src/settings/setting/widgets/ThemeChooserWidget.py
View file @
9dfbac49
from
gi.repository
import
Gtk
,
Adw
,
GObject
,
Gdk
import
math
from
gi.repository
import
Gtk
,
Adw
,
Gdk
from
.BaseWidget
import
BaseWidget
from
.BaseWidget
import
BaseWidget
...
@@ -98,7 +99,7 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -98,7 +99,7 @@ class ThemeChooserWidget(BaseWidget):
# FlowBox for theme cards
# FlowBox for theme cards
self
.
flowbox
=
Gtk
.
FlowBox
(
self
.
flowbox
=
Gtk
.
FlowBox
(
homogeneous
=
True
,
homogeneous
=
True
,
selection_mode
=
Gtk
.
SelectionMode
.
SINGL
E
,
selection_mode
=
Gtk
.
SelectionMode
.
NON
E
,
min_children_per_line
=
2
,
min_children_per_line
=
2
,
max_children_per_line
=
2
,
max_children_per_line
=
2
,
row_spacing
=
12
,
row_spacing
=
12
,
...
@@ -107,14 +108,22 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -107,14 +108,22 @@ class ThemeChooserWidget(BaseWidget):
content_box
.
append
(
self
.
flowbox
)
content_box
.
append
(
self
.
flowbox
)
self
.
theme_cards
=
{}
self
.
theme_cards
=
{}
self
.
handler_id
=
self
.
flowbox
.
connect
(
"child-activated"
,
self
.
_on_theme_selected
)
self
.
border_overlays
=
{}
self
.
flowbox
.
connect
(
"child-activated"
,
self
.
_on_theme_selected
)
# Subscribe to accent color changes
style_manager
=
Adw
.
StyleManager
.
get_default
()
style_manager
.
connect
(
"notify::accent-color-rgba"
,
self
.
_on_accent_color_changed
)
self
.
_build_cards
()
self
.
_build_cards
()
self
.
_update_reset_visibility
()
self
.
_update_reset_visibility
()
return
self
.
row
return
self
.
row
def
_create_theme_card
(
self
,
label
,
value
,
preview_path
=
None
):
def
_create_theme_card
(
self
,
label
,
value
,
preview_path
=
None
):
"""Create a theme preview card."""
"""Create a theme preview card with selection border overlay."""
overlay
=
Gtk
.
Overlay
()
card
=
Gtk
.
Box
(
card
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
spacing
=
8
,
spacing
=
8
,
...
@@ -134,10 +143,6 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -134,10 +143,6 @@ class ThemeChooserWidget(BaseWidget):
# Generate color preview
# Generate color preview
preview
=
self
.
_create_color_preview
(
value
)
preview
=
self
.
_create_color_preview
(
value
)
preview_frame
=
Gtk
.
Frame
()
preview_frame
.
set_child
(
preview
)
preview_frame
.
add_css_class
(
"theme-preview-frame"
)
card_inner
=
Gtk
.
Box
(
card_inner
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
orientation
=
Gtk
.
Orientation
.
VERTICAL
,
spacing
=
6
,
spacing
=
6
,
...
@@ -146,7 +151,7 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -146,7 +151,7 @@ class ThemeChooserWidget(BaseWidget):
margin_start
=
8
,
margin_start
=
8
,
margin_end
=
8
,
margin_end
=
8
,
)
)
card_inner
.
append
(
preview
_frame
)
card_inner
.
append
(
preview
)
# Label
# Label
name_label
=
Gtk
.
Label
(
name_label
=
Gtk
.
Label
(
...
@@ -157,7 +162,36 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -157,7 +162,36 @@ class ThemeChooserWidget(BaseWidget):
card_inner
.
append
(
name_label
)
card_inner
.
append
(
name_label
)
card
.
append
(
card_inner
)
card
.
append
(
card_inner
)
return
card
overlay
.
set_child
(
card
)
# Selection border overlay
border_area
=
Gtk
.
DrawingArea
()
border_area
.
set_can_target
(
False
)
border_area
.
set_draw_func
(
self
.
_draw_selection_border
,
value
)
overlay
.
add_overlay
(
border_area
)
self
.
border_overlays
[
value
]
=
border_area
return
overlay
def
_draw_selection_border
(
self
,
area
,
cr
,
width
,
height
,
value
):
if
value
!=
self
.
setting
.
_get_backend_value
():
return
rgba
=
Adw
.
StyleManager
.
get_default
()
.
get_accent_color_rgba
()
r
,
w
=
12
,
3
cr
.
new_path
()
cr
.
arc
(
width
-
r
,
r
,
r
-
w
/
2
,
-
math
.
pi
/
2
,
0
)
cr
.
arc
(
width
-
r
,
height
-
r
,
r
-
w
/
2
,
0
,
math
.
pi
/
2
)
cr
.
arc
(
r
,
height
-
r
,
r
-
w
/
2
,
math
.
pi
/
2
,
math
.
pi
)
cr
.
arc
(
r
,
r
,
r
-
w
/
2
,
math
.
pi
,
3
*
math
.
pi
/
2
)
cr
.
close_path
()
cr
.
set_source_rgba
(
rgba
.
red
,
rgba
.
green
,
rgba
.
blue
,
1.0
)
cr
.
set_line_width
(
w
)
cr
.
stroke
()
def
_clear_flowbox
(
self
):
def
_clear_flowbox
(
self
):
while
True
:
while
True
:
...
@@ -166,6 +200,7 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -166,6 +200,7 @@ class ThemeChooserWidget(BaseWidget):
break
break
self
.
flowbox
.
remove
(
child
)
self
.
flowbox
.
remove
(
child
)
self
.
theme_cards
=
{}
self
.
theme_cards
=
{}
self
.
border_overlays
=
{}
def
_build_cards
(
self
):
def
_build_cards
(
self
):
if
not
self
.
setting
.
map
:
if
not
self
.
setting
.
map
:
...
@@ -174,7 +209,6 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -174,7 +209,6 @@ class ThemeChooserWidget(BaseWidget):
self
.
flowbox
.
append
(
placeholder
)
self
.
flowbox
.
append
(
placeholder
)
return
return
current_value
=
self
.
setting
.
_get_backend_value
()
previews
=
self
.
setting
.
previews
or
{}
previews
=
self
.
setting
.
previews
or
{}
for
label
,
value
in
self
.
setting
.
map
.
items
():
for
label
,
value
in
self
.
setting
.
map
.
items
():
...
@@ -185,10 +219,6 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -185,10 +219,6 @@ class ThemeChooserWidget(BaseWidget):
self
.
flowbox
.
append
(
flowbox_child
)
self
.
flowbox
.
append
(
flowbox_child
)
self
.
theme_cards
[
value
]
=
flowbox_child
self
.
theme_cards
[
value
]
=
flowbox_child
if
value
==
current_value
:
with
GObject
.
signal_handler_block
(
self
.
flowbox
,
self
.
handler_id
):
self
.
flowbox
.
select_child
(
flowbox_child
)
def
_create_color_preview
(
self
,
value
):
def
_create_color_preview
(
self
,
value
):
"""Create a colored preview box for the theme."""
"""Create a colored preview box for the theme."""
preview
=
Gtk
.
Box
(
preview
=
Gtk
.
Box
(
...
@@ -209,61 +239,68 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -209,61 +239,68 @@ class ThemeChooserWidget(BaseWidget):
preview
.
append
(
drawing
)
preview
.
append
(
drawing
)
return
preview
return
preview
def
_rounded_rect
(
self
,
cr
,
x
,
y
,
w
,
h
,
r
):
"""Draw a rounded rectangle path."""
cr
.
new_path
()
cr
.
arc
(
x
+
w
-
r
,
y
+
r
,
r
,
-
math
.
pi
/
2
,
0
)
cr
.
arc
(
x
+
w
-
r
,
y
+
h
-
r
,
r
,
0
,
math
.
pi
/
2
)
cr
.
arc
(
x
+
r
,
y
+
h
-
r
,
r
,
math
.
pi
/
2
,
math
.
pi
)
cr
.
arc
(
x
+
r
,
y
+
r
,
r
,
math
.
pi
,
3
*
math
.
pi
/
2
)
cr
.
close_path
()
def
_draw_theme_preview
(
self
,
area
,
cr
,
width
,
height
,
colors
):
def
_draw_theme_preview
(
self
,
area
,
cr
,
width
,
height
,
colors
):
"""Draw a simple theme preview."""
"""Draw a window mockup preview."""
bg_color
,
accent_color
=
colors
bg_color
,
headerbar_color
=
colors
bg
=
Gdk
.
RGBA
()
bg
.
parse
(
bg_color
)
hb
=
Gdk
.
RGBA
()
hb
.
parse
(
headerbar_color
)
# Parse colors
r
=
8
bg_rgba
=
Gdk
.
RGBA
()
header_h
=
24
bg_rgba
.
parse
(
bg_color
)
margin
=
4
accent_rgba
=
Gdk
.
RGBA
()
accent_rgba
.
parse
(
accent_color
)
#
Draw background
#
Window shadow
cr
.
set_source_rgba
(
bg_rgba
.
red
,
bg_rgba
.
green
,
bg_rgba
.
blue
,
1.0
)
cr
.
set_source_rgba
(
0
,
0
,
0
,
0.15
)
cr
.
rectangle
(
0
,
0
,
width
,
height
)
self
.
_rounded_rect
(
cr
,
margin
+
2
,
margin
+
2
,
width
-
margin
*
2
,
height
-
margin
*
2
,
r
)
cr
.
fill
()
cr
.
fill
()
# Draw sidebar
# Window background
sidebar_width
=
28
cr
.
set_source_rgba
(
bg
.
red
,
bg
.
green
,
bg
.
blue
,
1.0
)
cr
.
set_source_rgba
(
accent_rgba
.
red
,
accent_rgba
.
green
,
self
.
_rounded_rect
(
cr
,
margin
,
margin
,
width
-
margin
*
2
,
height
-
margin
*
2
,
r
)
accent_rgba
.
blue
,
0.5
)
cr
.
rectangle
(
0
,
0
,
sidebar_width
,
height
)
cr
.
fill
()
cr
.
fill
()
# Draw header bar simulation
# Headerbar (top rounded corners only)
cr
.
set_source_rgba
(
accent_rgba
.
red
,
accent_rgba
.
green
,
cr
.
new_path
()
accent_rgba
.
blue
,
1.0
)
cr
.
arc
(
margin
+
r
,
margin
+
r
,
r
,
math
.
pi
,
3
*
math
.
pi
/
2
)
cr
.
rectangle
(
0
,
0
,
width
,
16
)
cr
.
arc
(
width
-
margin
-
r
,
margin
+
r
,
r
,
-
math
.
pi
/
2
,
0
)
cr
.
line_to
(
width
-
margin
,
margin
+
header_h
)
cr
.
line_to
(
margin
,
margin
+
header_h
)
cr
.
close_path
()
cr
.
set_source_rgba
(
hb
.
red
,
hb
.
green
,
hb
.
blue
,
1.0
)
cr
.
fill
()
cr
.
fill
()
# Draw window controls (circles)
# Window controls
cr
.
set_source_rgba
(
bg_rgba
.
red
,
bg_rgba
.
green
,
bg_rgba
.
blue
,
0.8
)
ctrl_y
=
margin
+
header_h
/
2
for
x
in
[
width
-
12
,
width
-
24
,
width
-
36
]:
cr
.
set_source_rgba
(
bg
.
red
,
bg
.
green
,
bg
.
blue
,
0.6
)
cr
.
arc
(
x
,
8
,
4
,
0
,
2
*
3.14159
)
for
i
,
x
in
enumerate
([
width
-
margin
-
14
,
width
-
margin
-
26
,
width
-
margin
-
38
]):
cr
.
arc
(
x
,
ctrl_y
,
4
,
0
,
2
*
math
.
pi
)
cr
.
fill
()
cr
.
fill
()
# Draw sidebar items
# Content area mockup
cr
.
set_source_rgba
(
bg_rgba
.
red
,
bg_rgba
.
green
,
bg_rgba
.
blue
,
0.6
)
content_y
=
margin
+
header_h
+
10
for
y
in
[
26
,
40
,
54
,
68
]:
content_x
=
margin
+
10
cr
.
rectangle
(
6
,
y
,
sidebar_width
-
12
,
8
)
content_w
=
width
-
margin
*
2
-
20
cr
.
fill
()
# Draw content lines
cr
.
set_source_rgba
(
hb
.
red
,
hb
.
green
,
hb
.
blue
,
0.4
)
content_start
=
sidebar_width
+
8
for
i
,
y
in
enumerate
([
content_y
,
content_y
+
14
,
content_y
+
28
]):
cr
.
set_source_rgba
(
accent_rgba
.
red
,
accent_rgba
.
green
,
w
=
content_w
if
i
==
0
else
content_w
*
(
0.7
if
i
==
1
else
0.5
)
accent_rgba
.
blue
,
0.6
)
self
.
_rounded_rect
(
cr
,
content_x
,
y
,
w
,
8
,
2
)
for
y
in
[
28
,
46
,
64
]:
cr
.
rectangle
(
content_start
,
y
,
width
-
content_start
-
8
,
6
)
cr
.
fill
()
cr
.
fill
()
def
update_display
(
self
):
def
update_display
(
self
):
current_value
=
self
.
setting
.
_get_backend_value
()
self
.
_redraw_borders
()
with
GObject
.
signal_handler_block
(
self
.
flowbox
,
self
.
handler_id
):
if
current_value
in
self
.
theme_cards
:
self
.
flowbox
.
select_child
(
self
.
theme_cards
[
current_value
])
self
.
_update_reset_visibility
()
self
.
_update_reset_visibility
()
def
on_map_updated
(
self
):
def
on_map_updated
(
self
):
...
@@ -271,9 +308,19 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -271,9 +308,19 @@ class ThemeChooserWidget(BaseWidget):
self
.
_build_cards
()
self
.
_build_cards
()
self
.
_update_reset_visibility
()
self
.
_update_reset_visibility
()
def
_redraw_borders
(
self
):
"""Redraw all border overlays to update selection state."""
for
border_area
in
self
.
border_overlays
.
values
():
border_area
.
queue_draw
()
def
_on_accent_color_changed
(
self
,
style_manager
,
pspec
):
"""Redraw borders when system accent color changes."""
self
.
_redraw_borders
()
def
_on_theme_selected
(
self
,
flowbox
,
child
):
def
_on_theme_selected
(
self
,
flowbox
,
child
):
value
=
child
.
value
value
=
child
.
value
self
.
setting
.
_set_backend_value
(
value
)
self
.
setting
.
_set_backend_value
(
value
)
self
.
_redraw_borders
()
self
.
_update_reset_visibility
()
self
.
_update_reset_visibility
()
def
_on_reset_clicked
(
self
,
button
):
def
_on_reset_clicked
(
self
,
button
):
...
@@ -282,10 +329,7 @@ class ThemeChooserWidget(BaseWidget):
...
@@ -282,10 +329,7 @@ class ThemeChooserWidget(BaseWidget):
if
default_value
is
not
None
:
if
default_value
is
not
None
:
self
.
setting
.
_set_backend_value
(
default_value
)
self
.
setting
.
_set_backend_value
(
default_value
)
if
default_value
in
self
.
theme_cards
:
self
.
_redraw_borders
()
with
GObject
.
signal_handler_block
(
self
.
flowbox
,
self
.
handler_id
):
self
.
flowbox
.
select_child
(
self
.
theme_cards
[
default_value
])
self
.
_update_reset_visibility
()
self
.
_update_reset_visibility
()
def
_update_reset_visibility
(
self
):
def
_update_reset_visibility
(
self
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment