Skip to content

Commit

Permalink
Skip tests not implemented for GTK4
Browse files Browse the repository at this point in the history
  • Loading branch information
danyeaw committed Jan 25, 2025
1 parent 062431d commit 286a461
Show file tree
Hide file tree
Showing 37 changed files with 370 additions and 205 deletions.
6 changes: 6 additions & 0 deletions gtk/src/toga_gtk/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ def __init__(self):
# A flag that can be used to explicitly flag that a redraw is required.
self.needs_redraw = True

def get_children(self):
if GTK_VERSION < (4, 0, 0):
return self.get_children()
else:
return None

def refreshed(self):
pass

Expand Down
23 changes: 12 additions & 11 deletions gtk/src/toga_gtk/widgets/activityindicator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ..libs import Gtk
from ..libs import GTK_VERSION, Gtk
from .base import Widget


Expand All @@ -16,14 +16,15 @@ def stop(self):
self.native.stop()

def rehint(self):
# print(
# "REHINT",
# self,
# self.native.get_preferred_width(),
# self.native.get_preferred_height(),
# )
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
# print(
# "REHINT",
# self,
# self.native.get_preferred_width(),
# self.native.get_preferred_height(),
# )
width = self.native.get_preferred_width()
height = self.native.get_preferred_height()

self.interface.intrinsic.width = width[0]
self.interface.intrinsic.height = height[0]
self.interface.intrinsic.width = width[0]
self.interface.intrinsic.height = height[0]
23 changes: 12 additions & 11 deletions gtk/src/toga_gtk/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from toga.constants import Baseline, FillRule
from toga.fonts import SYSTEM_DEFAULT_FONT_SIZE
from toga_gtk.colors import native_color
from toga_gtk.libs import Gdk, Gtk, Pango, PangoCairo, cairo
from toga_gtk.libs import GTK_VERSION, Gdk, Gtk, Pango, PangoCairo, cairo

from .base import Widget

Expand All @@ -23,16 +23,17 @@ def create(self):

self.native = Gtk.DrawingArea()

self.native.connect("draw", self.gtk_draw_callback)
self.native.connect("size-allocate", self.gtk_on_size_allocate)
self.native.connect("button-press-event", self.mouse_down)
self.native.connect("button-release-event", self.mouse_up)
self.native.connect("motion-notify-event", self.mouse_move)
self.native.set_events(
Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.BUTTON_MOTION_MASK
)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native.connect("draw", self.gtk_draw_callback)
self.native.connect("size-allocate", self.gtk_on_size_allocate)
self.native.connect("button-press-event", self.mouse_down)
self.native.connect("button-release-event", self.mouse_up)
self.native.connect("motion-notify-event", self.mouse_move)
self.native.set_events(
Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.BUTTON_MOTION_MASK
)

def gtk_draw_callback(self, widget, cairo_context):
"""Creates a draw callback.
Expand Down
177 changes: 95 additions & 82 deletions gtk/src/toga_gtk/widgets/detailedlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from travertino.size import at_least

from toga_gtk.libs import Gdk, Gio, Gtk, Pango
from toga_gtk.libs import GTK_VERSION, Gdk, Gio, Gtk, Pango

from .base import Widget

Expand All @@ -18,8 +18,10 @@ def __init__(self, dl, row):
# The row is a built as a stack, so that the action buttons can be pushed onto
# the stack as required.
self.stack = Gtk.Stack()
self.stack.set_homogeneous(True)
self.add(self.stack)

if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.stack.set_homogeneous(True)
self.add(self.stack)

self.content = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

Expand All @@ -28,20 +30,21 @@ def __init__(self, dl, row):

self.text = Gtk.Label(xalign=0)

# The three line below are necessary for right to left text.
self.text.set_hexpand(True)
self.text.set_ellipsize(Pango.EllipsizeMode.END)
self.text.set_margin_end(12)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
# The three line below are necessary for right to left text.
self.text.set_hexpand(True)
self.text.set_ellipsize(Pango.EllipsizeMode.END)
self.text.set_margin_end(12)

self.content.pack_end(self.text, True, True, 5)
self.content.pack_end(self.text, True, True, 5)

# Update the content for the row.
self.update(dl, row)
# Update the content for the row.
self.update(dl, row)

self.stack.add_named(self.content, "content")
self.stack.add_named(self.content, "content")

# Make sure the widgets have been made visible.
self.show_all()
# Make sure the widgets have been made visible.
self.show_all()

def update(self, dl, row):
"""Update the contents of the rendered row, using data from `row`,
Expand Down Expand Up @@ -108,99 +111,109 @@ def create(self):

# Main functional widget is a ListBox.
self.native_detailedlist = Gtk.ListBox()
self.native_detailedlist.set_selection_mode(Gtk.SelectionMode.SINGLE)
self.native_detailedlist.connect("row-selected", self.gtk_on_row_selected)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_detailedlist.set_selection_mode(Gtk.SelectionMode.SINGLE)
self.native_detailedlist.connect("row-selected", self.gtk_on_row_selected)

self.store = Gio.ListStore()
# We need to provide a function that transforms whatever is in the store into a
# `Gtk.ListBoxRow`, but the items in the store already are `Gtk.ListBoxRow`, so
# this is the identity function.
self.native_detailedlist.bind_model(self.store, lambda a: a)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
# We need to provide a function that transforms whatever is in the
# store into a `Gtk.ListBoxRow`, but the items in the store already
# are `Gtk.ListBoxRow`, so this is the identity function.
self.native_detailedlist.bind_model(self.store, lambda a: a)

# Put the ListBox into a vertically scrolling window.
# Put the ListBox into a vertically scrolling window.
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_min_content_width(self.interface._MIN_WIDTH)
scrolled_window.set_min_content_height(self.interface._MIN_HEIGHT)
scrolled_window.add(self.native_detailedlist)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_min_content_width(self.interface._MIN_WIDTH)
scrolled_window.set_min_content_height(self.interface._MIN_HEIGHT)
scrolled_window.add(self.native_detailedlist)

self.native_vadj = scrolled_window.get_vadjustment()
self.native_vadj.connect("value-changed", self.gtk_on_value_changed)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_vadj.connect("value-changed", self.gtk_on_value_changed)

# Define a revealer widget that can be used to show/hide with a crossfade.
# Define a revealer widget that can be used to show/hide with a crossfade.
self.native_revealer = Gtk.Revealer()
self.native_revealer.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE)
self.native_revealer.set_valign(Gtk.Align.END)
self.native_revealer.set_halign(Gtk.Align.CENTER)
self.native_revealer.set_margin_bottom(12)
self.native_revealer.set_reveal_child(False)

# Define a refresh button.
self.native_refresh_button = Gtk.Button.new_from_icon_name(
"view-refresh-symbolic", Gtk.IconSize.BUTTON
)
self.native_refresh_button.set_can_focus(False)
self.native_refresh_button.connect("clicked", self.gtk_on_refresh_clicked)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_revealer.set_transition_type(
Gtk.RevealerTransitionType.CROSSFADE
)
self.native_revealer.set_valign(Gtk.Align.END)
self.native_revealer.set_halign(Gtk.Align.CENTER)
self.native_revealer.set_margin_bottom(12)
self.native_revealer.set_reveal_child(False)

# Define a refresh button.
self.native_refresh_button = Gtk.Button.new_from_icon_name(
"view-refresh-symbolic", Gtk.IconSize.BUTTON
)
self.native_refresh_button.set_can_focus(False)
self.native_refresh_button.connect("clicked", self.gtk_on_refresh_clicked)

style_context = self.native_refresh_button.get_style_context()
style_context.add_class("osd")
style_context.add_class("toga-detailed-list-floating-buttons")
style_context.remove_class("button")
style_context = self.native_refresh_button.get_style_context()
style_context.add_class("osd")
style_context.add_class("toga-detailed-list-floating-buttons")
style_context.remove_class("button")

# Add the refresh button to the revealer
self.native_revealer.add(self.native_refresh_button)
# Add the refresh button to the revealer
self.native_revealer.add(self.native_refresh_button)

# The actual native widget is an overlay, made up of the scrolled window, with
# the revealer over the top.
self.native = Gtk.Overlay()
self.native.add_overlay(scrolled_window)
self.native.add_overlay(self.native_revealer)

# Set up a gesture to capture right clicks.
self.gesture = Gtk.GestureMultiPress.new(self.native_detailedlist)
self.gesture.set_button(3)
self.gesture.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
self.gesture.connect("pressed", self.gtk_on_right_click)

# Set up a box that contains action buttons. This widget can be can be re-used
# for any row when it is activated.
self.native_action_buttons = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
action_buttons_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

# TODO: Can we replace "magic words" like delete with an appropriate icon?
# self.native_primary_action_button = Gtk.Button.new_from_icon_name(
# "user-trash-symbolic", Gtk.IconSize.BUTTON
# )
action_buttons_hbox.pack_start(Gtk.Box(), True, True, 0)

if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native.add_overlay(scrolled_window)
self.native.add_overlay(self.native_revealer)
# Set up a gesture to capture right clicks.
self.gesture = Gtk.GestureMultiPress.new(self.native_detailedlist)
self.gesture.set_button(3)
self.gesture.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
self.gesture.connect("pressed", self.gtk_on_right_click)

# Set up a box that contains action buttons. This widget can be re-used
# for any row when it is activated.
self.native_action_buttons = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
action_buttons_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

# TODO: Can we replace "magic words" like delete with an appropriate icon?
# self.native_primary_action_button = Gtk.Button.new_from_icon_name(
# "user-trash-symbolic", Gtk.IconSize.BUTTON
# )
action_buttons_hbox.pack_start(Gtk.Box(), True, True, 0)

self.native_primary_action_button = Gtk.Button.new_with_label(
self.interface._primary_action
)
self.native_primary_action_button.connect(
"clicked", self.gtk_on_primary_clicked
)
action_buttons_hbox.pack_start(
self.native_primary_action_button, False, False, 10
)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_primary_action_button.connect(
"clicked", self.gtk_on_primary_clicked
)
action_buttons_hbox.pack_start(
self.native_primary_action_button, False, False, 10
)

# TODO: Can we replace "magic words" like delete with an appropriate icon?
# self.native_secondary_action_button = Gtk.Button.new_from_icon_name(
# "user-trash-symbolic", Gtk.IconSize.BUTTON
# )
# TODO: Can we replace "magic words" like delete with an appropriate icon?
# self.native_secondary_action_button = Gtk.Button.new_from_icon_name(
# "user-trash-symbolic", Gtk.IconSize.BUTTON
# )
self.native_secondary_action_button = Gtk.Button.new_with_label(
self.interface._secondary_action
)
self.native_secondary_action_button.connect(
"clicked", self.gtk_on_secondary_clicked
)
action_buttons_hbox.pack_start(
self.native_secondary_action_button, False, False, 10
)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_secondary_action_button.connect(
"clicked", self.gtk_on_secondary_clicked
)
action_buttons_hbox.pack_start(
self.native_secondary_action_button, False, False, 10
)

action_buttons_hbox.pack_start(Gtk.Box(), True, True, 0)
action_buttons_hbox.pack_start(Gtk.Box(), True, True, 0)

self.native_action_buttons.pack_start(action_buttons_hbox, True, False, 0)
self.native_action_buttons.show_all()
self.native_action_buttons.pack_start(action_buttons_hbox, True, False, 0)
self.native_action_buttons.show_all()

def row_factory(self, item):
return DetailedListRow(self.interface, item)
Expand Down
16 changes: 10 additions & 6 deletions gtk/src/toga_gtk/widgets/imageview.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
from toga.widgets.imageview import rehint_imageview

from ..libs import GdkPixbuf, Gtk
from ..libs import GTK_VERSION, GdkPixbuf, Gtk
from .base import Widget


class ImageView(Widget):
def create(self):
self.native = Gtk.Image()
self.native.connect("size-allocate", self.gtk_size_allocate)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native.connect("size-allocate", self.gtk_size_allocate)
self._aspect_ratio = None

def set_image(self, image):
if image:
self.set_scaled_pixbuf(image._impl.native, self.native.get_allocation())
else:
self.native.set_from_pixbuf(None)
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
if image:
self.set_scaled_pixbuf(image._impl.native, self.native.get_allocation())
else:
self.native.set_from_pixbuf(None)
else: # pragma: no-cover-if-gtk3
self.native.set_from_paintable()

def gtk_size_allocate(self, widget, allocation):
# GTK doesn't have any native image resizing; so, when the Gtk.Image
Expand Down
16 changes: 9 additions & 7 deletions gtk/src/toga_gtk/widgets/multilinetextinput.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from travertino.size import at_least

from ..libs import (
GTK_VERSION,
Gtk,
get_background_color_css,
get_color_css,
Expand Down Expand Up @@ -34,15 +35,16 @@ def create(self):

self.native_textview = Gtk.TextView()
self.native_textview.set_name(f"toga-{self.interface.id}-textview")
self.native_textview.get_style_context().add_class("toga")
if GTK_VERSION < (4, 0, 0): # pragma: no-cover-if-gtk4
self.native_textview.get_style_context().add_class("toga")

self.native_textview.set_buffer(self.placeholder)
self.native_textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
self.native_textview.connect("focus-in-event", self.gtk_on_focus_in)
self.native_textview.connect("focus-out-event", self.gtk_on_focus_out)
self.native_textview.connect("key-press-event", self.gtk_on_key_press)
self.native_textview.set_buffer(self.placeholder)
self.native_textview.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
self.native_textview.connect("focus-in-event", self.gtk_on_focus_in)
self.native_textview.connect("focus-out-event", self.gtk_on_focus_out)
self.native_textview.connect("key-press-event", self.gtk_on_key_press)

self.native.add(self.native_textview)
self.native.add(self.native_textview)

def set_color(self, color):
self.apply_css(
Expand Down
Loading

0 comments on commit 286a461

Please sign in to comment.