Skip to content

Commit 67ac97e

Browse files
committed
Port Calculate activity to GTK4
This commit fully ports the Calculate activity to GTK4 and Sugar4. - Port `shareable_activity.py` with updated DBus and Sugar4 base classes. - Rework `layout.py` to use GTK4 box packing (`append`, `set_child`) instead of deprecated containers like `Gtk.Table`. - Replace legacy styling (`modify_bg`, `modify_font`) and `Gtk.EventBox` usage with a modern `Gtk.CssProvider` to handle backgrounds, colors, and font rendering. - Ensure proper CSS specificity (`background-image: none;`) to override GTK4's native `.toggle` styles for the toolbar interface. - Refactor `toolbars.py` to gracefully render GTK4 toolbar items and correctly update text fallbacks when SVG icons are invalid. - Port `calculate.py` to use `Gtk.EventControllerKey` for keystrokes and update clipboard operations to use GTK4 async mechanisms. - Include `main.py` standalone bootstrapper for isolated GTK4 testing.
1 parent e84956d commit 67ac97e

File tree

6 files changed

+270
-200
lines changed

6 files changed

+270
-200
lines changed

calculate.py

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def create_lasteq_textbuf(self):
193193
tagsmallnarrow = buf.create_tag(font=CalcLayout.FONT_SMALL_NARROW)
194194
tagbignarrow = buf.create_tag(font=CalcLayout.FONT_BIG_NARROW)
195195
tagbigger = buf.create_tag(font=CalcLayout.FONT_BIGGER)
196-
tagjustright = buf.create_tag(justification=Gtk.Justification.RIGHT)
196+
tagjustright = buf.create_tag(justification=Gtk.Justification.LEFT)
197197
tagred = buf.create_tag(foreground='#FF0000')
198198

199199
# Add label and equation
@@ -258,6 +258,7 @@ def create_history_object(self):
258258
textview text {
259259
background-color: %s;
260260
color: %s;
261+
min-height: 20px;
261262
}
262263
""" % (stroke_color, fill_color, stroke_color, fill_color)
263264

@@ -275,7 +276,7 @@ def create_history_object(self):
275276
tagsmall = buf.create_tag(font=CalcLayout.FONT_SMALL)
276277
tagsmallnarrow = buf.create_tag(font=CalcLayout.FONT_SMALL_NARROW)
277278
tagbig = buf.create_tag(font=CalcLayout.FONT_BIG,
278-
justification=Gtk.Justification.RIGHT)
279+
justification=Gtk.Justification.LEFT)
279280

280281
# Calculate brightness
281282
c = Gdk.RGBA()
@@ -297,13 +298,22 @@ def create_history_object(self):
297298
eqnstr = '%s\n' % str(self.equation)
298299
self.append_with_superscript_tags(buf, eqnstr, tagsmall)
299300

300-
resstr = self.ml.format_number(self.result)
301-
resstr = str(resstr).rstrip('0').rstrip('.') \
302-
if '.' in resstr else resstr
301+
try:
302+
resstr = self.ml.format_number(self.result)
303+
except Exception:
304+
resstr = str(self.result)
305+
306+
resstr = str(resstr)
307+
resstr = resstr.rstrip('0').rstrip('.') if '.' in resstr else resstr
308+
309+
if not resstr or resstr == "None":
310+
resstr = "0"
311+
303312
if len(resstr) > 30:
304313
restag = tagsmall
305314
else:
306315
restag = tagbig
316+
307317
self.append_with_superscript_tags(buf, resstr, restag)
308318

309319
buf.apply_tag(tagcolor, buf.get_start_iter(), buf.get_end_iter())
@@ -381,6 +391,10 @@ def __init__(self, handle):
381391

382392
self.ml = MathLib()
383393
self.parser = AstParser(self.ml)
394+
395+
angle_var = self.parser.get_var('angle_scaling')
396+
if angle_var is not None:
397+
angle_var.value = MathLib.ANGLE_RAD
384398

385399
# These will result in 'Ans <operator character>' being inserted
386400
self._chars_ans_diadic = [op[0]
@@ -400,7 +414,6 @@ def __init__(self, handle):
400414
self.ans_inserted = False
401415
self.show_vars = False
402416

403-
# Input handling for GTK4
404417
key_controller = Gtk.EventControllerKey()
405418
key_controller.connect("key-pressed", self.keypress_cb)
406419
self.add_controller(key_controller)
@@ -451,14 +464,15 @@ def equation_pressed_cb(self, eqn):
451464
def set_last_equation(self, eqn):
452465
"""Set the 'last equation' TextView."""
453466

454-
if self.last_eq_sig is not None:
455-
self.layout.last_eq.disconnect(self.last_eq_sig)
456-
self.last_eq_sig = None
467+
if self.last_eqn_controller is not None:
468+
self.layout.last_eq.remove_controller(self.last_eqn_controller)
469+
self.last_eqn_controller = None
457470

458471
if not isinstance(eqn.result, ParserError):
459-
self.last_eq_sig = self.layout.last_eq.connect(
460-
'button-press-event',
461-
lambda a1, a2, e: self.equation_pressed_cb(e), eqn)
472+
self.last_eqn_controller = Gtk.GestureClick.new()
473+
self.last_eqn_controller.set_button(0)
474+
self.last_eqn_controller.connect('pressed', lambda gesture, n_press, x, y: self.equation_pressed_cb(eqn))
475+
self.layout.last_eq.add_controller(self.last_eqn_controller)
462476

463477
self.layout.last_eq.set_buffer(eqn.create_lasteq_textbuf())
464478

@@ -514,8 +528,10 @@ def add_equation(self, eq, prepend=False, drawlasteq=False, tree=None):
514528

515529
own = (eq.owner == self.get_owner_id())
516530
w = eq.create_history_object()
517-
w.connect('button-press-event', lambda w,
518-
e: self.equation_pressed_cb(eq))
531+
click_gesture = Gtk.GestureClick.new()
532+
click_gesture.set_button(0)
533+
click_gesture.connect('pressed', lambda gesture, n_press, x, y: self.equation_pressed_cb(eq))
534+
w.add_controller(click_gesture)
519535
if drawlasteq:
520536
self.set_last_equation(eq)
521537

@@ -575,7 +591,7 @@ def process(self):
575591
self.get_owner_id(), ml=self.ml)
576592
self.set_error_equation(eqn)
577593
else:
578-
eqn = Equation(label, _n(s), _n(str(res)), self.color,
594+
eqn = Equation(label, _n(s), res, self.color,
579595
self.get_owner_id(), ml=self.ml)
580596
self.add_equation(eqn, drawlasteq=True, tree=tree)
581597
self.send_message("add_eq", value=str(eqn))
@@ -600,28 +616,40 @@ def create_var_textview(self, name, value):
600616
if name in reserved:
601617
return None
602618
w = Gtk.TextView()
603-
w.modify_base(
604-
Gtk.StateType.NORMAL, Gdk.color_parse(self.color.get_fill_color()))
605-
w.modify_bg(
606-
Gtk.StateType.NORMAL,
607-
Gdk.color_parse(self.color.get_stroke_color()))
619+
fill_color = self.color.get_fill_color()
620+
stroke_color = self.color.get_stroke_color()
621+
622+
provider = Gtk.CssProvider()
623+
css_str = """
624+
textview {
625+
background-color: %s;
626+
color: %s;
627+
}
628+
textview text {
629+
background-color: %s;
630+
color: %s;
631+
}
632+
""" % (fill_color, stroke_color, fill_color, stroke_color)
633+
provider.load_from_data(css_str.encode())
634+
w.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
635+
608636
w.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
609-
w.set_border_window_size(Gtk.TextWindowType.LEFT, 4)
610-
w.set_border_window_size(Gtk.TextWindowType.RIGHT, 4)
611-
w.set_border_window_size(Gtk.TextWindowType.TOP, 4)
612-
w.set_border_window_size(Gtk.TextWindowType.BOTTOM, 4)
637+
w.set_left_margin(4)
638+
w.set_right_margin(4)
639+
w.set_top_margin(4)
640+
w.set_bottom_margin(4)
613641
w.connect('realize', _textview_realize_cb)
614642
buf = w.get_buffer()
615643

616-
# TODO Fix for old Sugar 0.82 builds, red_float not available
617-
bright = (
618-
Gdk.color_parse(self.color.get_fill_color()).red_float +
619-
Gdk.color_parse(self.color.get_fill_color()).green_float +
620-
Gdk.color_parse(self.color.get_fill_color()).blue_float) / 3.0
621-
if bright < 0.5:
622-
col = Gdk.color_parse('white')
644+
c = Gdk.RGBA()
645+
if c.parse(fill_color):
646+
bright = (c.red + c.green + c.blue) / 3.0
647+
if bright < 0.5:
648+
col = 'white'
649+
else:
650+
col = 'black'
623651
else:
624-
col = Gdk.color_parse('black')
652+
col = 'black'
625653

626654
tag = buf.create_tag(font=CalcLayout.FONT_SMALL_NARROW,
627655
foreground=col)
@@ -842,7 +870,7 @@ def _on_paste_text_received(self, clipboard, result, user_data):
842870
if text:
843871
self.button_pressed(self.TYPE_TEXT, text)
844872
except Exception as e:
845-
_logger.error(f"Error pasting text: {e}")
873+
_logger.error("Error pasting text: %s", e)
846874

847875
def text_cut(self):
848876
self.text_copy()
@@ -993,19 +1021,3 @@ def format_insert_ans(self):
9931021
return self.ml.format_number(ans)
9941022
else:
9951023
return ''
996-
997-
998-
def main():
999-
app = Gtk.Application(application_id="org.laptop.Calculate.Test")
1000-
1001-
def activate(app):
1002-
win = Calculate(None)
1003-
win.set_application(app)
1004-
win.present()
1005-
1006-
app.connect("activate", activate)
1007-
app.run(None)
1008-
1009-
1010-
if __name__ == "__main__":
1011-
main()

0 commit comments

Comments
 (0)