### Makefile Installation and Setup Targets (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Provides commands for installing the package in development mode ('make install') and setting up the complete development environment ('make dev-setup'). These are crucial first steps for contributors. ```bash make install make dev-setup ``` -------------------------------- ### Development Setup (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Sets up the development environment for the sugar-toolkit-gtk4 project using the 'make install' command. This is a convenient way to prepare your system for development. ```bash make install ``` -------------------------------- ### Makefile Utility Targets (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Lists various utility commands available via Makefile, including cleaning build artifacts ('make clean'), running examples ('make example'), testing toolkit installation ('make test-toolkit'), simulating CI pipelines ('make ci-test'), and displaying help information ('make help'). ```bash make clean make example make test-toolkit make ci-test make help ``` -------------------------------- ### Basic GTK Application Setup (Python) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Initializes and runs a basic GTK application with a specified application ID. It defines an 'on_activate' handler to create and present the main window of the activity. This function sets up the application's main loop, returning the application object. Dependencies include 'Gtk' and 'sys'. ```python def main(): """Run the basic example activity.""" app = Gtk.Application(application_id="org.sugarlabs.BasicExample") def on_activate(app): activity = BasicExampleActivity() app.add_window(activity) activity.present() app.connect("activate", on_activate) return app.run(sys.argv) if __name__ == "__main__": main() ``` -------------------------------- ### Python: Main Entry Point for Creative Studio Application Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This code snippet defines the main entry point for the Creative Studio application. It configures basic logging to DEBUG level, instantiates the CreativeStudioApplication, and then runs the application with command-line arguments. This is the standard way to start a Python application. ```python def main(): """Main entry point.""" logging.basicConfig(level=logging.DEBUG) app = CreativeStudioApplication() return app.run(sys.argv) if __name__ == "__main__": main() ``` -------------------------------- ### Run Example Activity (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Executes a sample activity from the sugar-toolkit-gtk4 project using the 'make example' command. This is useful for quickly testing the toolkit's functionality. ```bash make example ``` -------------------------------- ### Setup Keyboard Accelerators for GTK4 Window Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Configures window-level keyboard shortcuts for common actions like undo, redo, and save. It uses a GTK4 event controller to capture key presses and trigger the corresponding methods. Dependencies include Gtk and Gdk libraries. ```python def _setup_accelerators(self): """Set up application-level keyboard accelerators.""" # Create event controller for window-level shortcuts key_controller = Gtk.EventControllerKey() def on_key_pressed(controller, keyval, keycode, state): if state & Gdk.ModifierType.CONTROL_MASK: if keyval == Gdk.KEY_z or keyval == Gdk.KEY_Z: self._undo_action() return True elif keyval == Gdk.KEY_y or keyval == Gdk.KEY_Y: self._redo_action() return True elif keyval == Gdk.KEY_s or keyval == Gdk.KEY_S: self.save_creation() return True return False key_controller.connect("key-pressed", on_key_pressed) self.add_controller(key_controller) ``` -------------------------------- ### Install Activity Bundle using Python Source: https://context7.com/sugarlabs/sugar-toolkit-gtk4/llms.txt This Python function installs an activity bundle from a specified path to the user's activities directory. It uses the ActivityBundle class to perform the installation and prints the installation path and bundle details upon successful installation. Error handling is included for installation failures. ```python #!/usr/bin/env python3 import os from sugar4.bundle.activitybundle import ActivityBundle, get_bundle_instance from sugar4 import env def install_activity_bundle(bundle_path): """Install an activity bundle to user activities directory""" try: bundle = ActivityBundle(bundle_path) # Install the bundle install_path = bundle.install() print(f"Successfully installed to: {install_path}") print(f"Bundle ID: {bundle.get_bundle_id()}") print(f"Version: {bundle.get_activity_version()}") return install_path except Exception as e: print(f"Error installing bundle: {e}") return None # Example usage (within the __main__ block) # bundle_path = '/path/to/MyActivity.activity' # if os.path.exists(bundle_path): # install_path = install_activity_bundle(bundle_path) ``` -------------------------------- ### Run Example Activity with Debugging Environment Variables (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Executes a Sugar activity example by setting several environment variables that control GTK debugging, platform settings, and Sugar-specific bundle information. This is useful for running and debugging examples. ```bash GTK_DEBUG=interactive QT_QPA_PLATFORM=xcb GDK_BACKEND=x11 \ SUGAR_BUNDLE_PATH="$(pwd)/examples" \ SUGAR_BUNDLE_ID="org.sugarlabs.SugarTextEditor" \ SUGAR_BUNDLE_NAME="Sugar Text Editor" \ SUGAR_ACTIVITY_ROOT="/tmp/sugar_text_editor" \ python examples/activity_examples.py ``` -------------------------------- ### Development Workflow Examples (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Provides practical examples of using Makefile targets for common development tasks, such as setting up the environment, running tests before committing, building releases, and simulating CI pipelines locally. ```bash # Setting up for development: make dev-setup make test # Before committing changes: make dev-test # Creating a release: make dev-build make tarball make check # Testing the complete CI workflow locally: make ci-test ``` -------------------------------- ### Install sugar-toolkit-gtk4 from Source (Bash) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Installs the sugar-toolkit-gtk4 project by cloning the repository and installing it in editable mode using pip. This is useful for development and testing. ```bash git clone https://github.com/sugarlabs/sugar-toolkit-gtk4.git cd sugar-toolkit-gtk4 pip install -e . ``` -------------------------------- ### Sugar GTK4 Toolbox Example: Organized Tool Management Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python example demonstrates the Sugar GTK4 Toolbox, which provides a structured way to manage multiple toolbars. Users can switch between different sets of tools using tabs. The example includes creation of edit, view, tools, and help toolbars, each with relevant buttons and separators. It utilizes Gtk.Box for organizing content and Gtk.Label for status updates. ```python """Sugar GTK4 Toolbox Example""" import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk from sugar4.activity import SimpleActivity from sugar4.graphics.toolbox import Toolbox from sugar4.graphics import style from sugar4.graphics.icon import Icon class ToolboxExampleActivity(SimpleActivity): """Example activity demonstrating Sugar GTK4 Toolbox features.""" def __init__(self): super().__init__() self.set_title("Sugar GTK4 Toolbox Example") self._create_content() def _create_content(self): """Create the main content with toolbox.""" main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Create toolbox self._toolbox = Toolbox() self._toolbox.connect("current-toolbar-changed", self._on_toolbar_changed) # Add various toolbars self._create_edit_toolbar() self._create_view_toolbar() self._create_tools_toolbar() self._create_help_toolbar() main_box.append(self._toolbox) # Add content area content_area = self._create_content_area() main_box.append(content_area) # Status bar self._status_bar = Gtk.Label( label="Toolbox Example - Switch between toolbars using tabs" ) self._status_bar.set_margin_start(style.DEFAULT_PADDING) self._status_bar.set_margin_end(style.DEFAULT_PADDING) self._status_bar.set_margin_top(style.DEFAULT_PADDING // 2) self._status_bar.set_margin_bottom(style.DEFAULT_PADDING // 2) self._status_bar.add_css_class("dim-label") main_box.append(self._status_bar) self.set_canvas(main_box) self.set_default_size(800, 600) def _create_edit_toolbar(self): """Create edit toolbar with common editing tools.""" toolbar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) toolbar.set_margin_top(style.DEFAULT_PADDING) toolbar.set_margin_bottom(style.DEFAULT_PADDING) # Common edit buttons edit_buttons = [ ("New", "document-new"), ("Open", "document-open"), ("Save", "document-save"), ("---", None), # Separator ("Cut", "edit-cut"), ("Copy", "edit-copy"), ("Paste", "edit-paste"), ("---", None), # Separator ("Undo", "edit-undo"), ("Redo", "edit-redo"), ] for label, icon_name in edit_buttons: if label == "---": separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL) separator.set_margin_start(6) separator.set_margin_end(6) toolbar.append(separator) else: button = Gtk.Button(label=label) # icon = Icon(icon_name) # button.set_image(icon) # button.set_tooltip_text(label) button.connect("clicked", self._on_edit_button_clicked, label) toolbar.append(button) self._toolbox.add_toolbar(toolbar, "Edit") def _create_view_toolbar(self): """Create view toolbar with common view options.""" toolbar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) toolbar.set_margin_top(style.DEFAULT_PADDING) toolbar.set_margin_bottom(style.DEFAULT_PADDING) view_options = [ ("Zoom In", "view-zoom-in"), ("Zoom Out", "view-zoom-out"), ("---", None), # Separator ("Fit Window", "view-fit"), ] for label, icon_name in view_options: if label == "---": separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL) separator.set_margin_start(6) separator.set_margin_end(6) toolbar.append(separator) else: button = Gtk.Button(label=label) # icon = Icon(icon_name) # button.set_image(icon) # button.set_tooltip_text(label) button.connect("clicked", self._on_view_button_clicked, label) toolbar.append(button) self._toolbox.add_toolbar(toolbar, "View") def _create_tools_toolbar(self): """Create tools toolbar with specific tools.""" toolbar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) toolbar.set_margin_top(style.DEFAULT_PADDING) toolbar.set_margin_bottom(style.DEFAULT_PADDING) tool_buttons = [ ("Tool A", "tool-a"), ("Tool B", "tool-b"), ("Tool C", "tool-c"), ] for label, icon_name in tool_buttons: button = Gtk.Button(label=label) # icon = Icon(icon_name) # button.set_image(icon) # button.set_tooltip_text(label) button.connect("clicked", self._on_tool_button_clicked, label) toolbar.append(button) self._toolbox.add_toolbar(toolbar, "Tools") def _create_help_toolbar(self): """Create help toolbar with help actions.""" toolbar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) toolbar.set_margin_top(style.DEFAULT_PADDING) toolbar.set_margin_bottom(style.DEFAULT_PADDING) help_actions = [ ("About", "help-about"), ("Documentation", "help-contents"), ] for label, icon_name in help_actions: button = Gtk.Button(label=label) # icon = Icon(icon_name) # button.set_image(icon) # button.set_tooltip_text(label) button.connect("clicked", self._on_help_button_clicked, label) toolbar.append(button) self._toolbox.add_toolbar(toolbar, "Help") def _create_content_area(self): """Create a placeholder content area.""" content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) content_box.set_vexpand(True) label = Gtk.Label(label="Main Content Area") label.set_halign(Gtk.Align.CENTER) label.set_valign(Gtk.Align.CENTER) label.set_vexpand(True) content_box.append(label) return content_box def _on_toolbar_changed(self, toolbox, current_toolbar): """Handle changes in the current toolbar.""" self._status_bar.set_label(f"Current Toolbar: {current_toolbar.get_name()}") def _on_edit_button_clicked(self, widget, action): """Handle clicks on edit toolbar buttons.""" self._status_bar.set_label(f"Edit Action: {action}") def _on_view_button_clicked(self, widget, action): """Handle clicks on view toolbar buttons.""" self._status_bar.set_label(f"View Action: {action}") def _on_tool_button_clicked(self, widget, action): """Handle clicks on tools toolbar buttons.""" self._status_bar.set_label(f"Tool Action: {action}") def _on_help_button_clicked(self, widget, action): """Handle clicks on help toolbar buttons.""" self._status_bar.set_label(f"Help Action: {action}") def main(): """Run the Toolbox example activity.""" app = Gtk.Application(application_id="org.sugarlabs.ToolboxExample") def on_activate(app): activity = ToolboxExampleActivity() activity.set_application(app) activity.present() app.connect("activate", on_activate) return app.run(sys.argv) if __name__ == "__main__": main() ``` -------------------------------- ### Logger Setup and Configuration Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/autoapi/sugar4/logger/index.md Provides functions for setting up, configuring, and cleaning up the logging service. ```APIDOC ## sugar4.logger.TRACE ### Description Represents the trace level for logging. ### Method N/A (Constant) ### Endpoint N/A ### Parameters None ### Request Example None ### Response #### Success Response (N/A) None #### Response Example None ## sugar4.logger.get_logs_dir() ### Description Retrieves the directory where logs are stored. ### Method GET ### Endpoint /sugar4.logger/logs_dir ### Parameters None ### Request Example None ### Response #### Success Response (200) - **logs_directory** (string) - The path to the log directory. #### Response Example ```json { "logs_directory": "/var/log/sugar" } ``` ## sugar4.logger.set_level(level) ### Description Sets the logging level for the application. ### Method POST ### Endpoint /sugar4.logger/level ### Parameters #### Request Body - **level** (string) - The desired logging level (e.g., 'DEBUG', 'INFO', 'WARNING', 'ERROR'). ### Request Example ```json { "level": "INFO" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message that the level was set. #### Response Example ```json { "message": "Logging level set to INFO" } ``` ## sugar4.logger.cleanup() ### Description Cleans up the log directory by moving old logs into a numbered backup directory. Old backup directories beyond a certain limit are removed. ### Method POST ### Endpoint /sugar4.logger/cleanup ### Parameters None ### Request Example None ### Response #### Success Response (200) - **message** (string) - Confirmation message that the cleanup was performed. #### Response Example ```json { "message": "Log directory cleaned up successfully." } ``` ## sugar4.logger.start([log_filename]) ### Description Starts the logging service, optionally specifying a log filename. ### Method POST ### Endpoint /sugar4.logger/start ### Parameters #### Request Body - **log_filename** (string) - Optional. The name of the log file to use. ### Request Example ```json { "log_filename": "app.log" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message that the logging service has started. #### Response Example ```json { "message": "Logging service started." } ``` ``` -------------------------------- ### Run Sugar Toolkit GTK4 Icon Example Application Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python code sets up and runs a GTK4 application that showcases the Sugar Toolkit's icon features. It defines the main application entry point, an `on_activate` handler to create and present the main window (an instance of `IconExampleActivity`), and uses `sys.argv` for command-line arguments. The application ID is set to 'org.sugarlabs.IconExample'. ```python import sys import gi gi.require_version('Gtk', '4.0') from gi.repository import Gtk # Assuming Icon class and IconExampleActivity are defined elsewhere # from sugar.toolkit.gtk4.icon import Icon # class IconExampleActivity(Gtk.Box): # pass # Placeholder for actual activity class def main(): """Run the icon example activity.""" app = Gtk.Application(application_id="org.sugarlabs.IconExample") def on_activate(app): # activity = IconExampleActivity() # In a real scenario, IconExampleActivity would be defined and instantiated here # For this example, we'll just create a placeholder window window = Gtk.ApplicationWindow(application=app) window.set_title("Icon Example Placeholder") window.set_default_size(400, 300) app.add_window(window) window.present() app.connect("activate", on_activate) return app.run(sys.argv) if __name__ == "__main__": main() ``` -------------------------------- ### GTK4 Alert Examples in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python script showcases how to implement and display various alert dialogs using the Sugar Toolkit GTK4 library. It includes examples for simple alerts, confirmation alerts, and alerts with a timeout. The code requires GTK4 and Sugar Toolkit GTK4 dependencies. It handles user responses to the alerts. ```python import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, GLib import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) from sugar4.graphics.alert import ( Alert, ConfirmationAlert, ErrorAlert, TimeoutAlert, NotifyAlert, ) class AlertExample(Gtk.ApplicationWindow): def __init__(self, app): super().__init__(application=app, title="Alert Example") self.set_default_size(600, 400) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) vbox.set_margin_top(20) vbox.set_margin_bottom(20) vbox.set_margin_start(20) vbox.set_margin_end(20) self.set_child(vbox) self.alert_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) vbox.append(self.alert_box) btn_simple = Gtk.Button(label="Show Simple Alert") btn_simple.connect("clicked", self.on_simple_alert) vbox.append(btn_simple) btn_confirm = Gtk.Button(label="Show Confirmation Alert") btn_confirm.connect("clicked", self.on_confirmation_alert) vbox.append(btn_confirm) btn_timeout = Gtk.Button(label="Show Timeout Alert") btn_timeout.connect("clicked", self.on_timeout_alert) vbox.append(btn_timeout) def on_simple_alert(self, button): alert = Alert() alert.props.title = "Simple Alert" alert.props.msg = "This is a basic alert message." alert.add_button(1, "OK") alert.connect("response", self.on_alert_response) self.alert_box.append(alert) def on_confirmation_alert(self, button): alert = ConfirmationAlert() alert.props.title = "Confirm Action" alert.props.msg = "Are you sure you want to continue?" alert.connect("response", self.on_alert_response) self.alert_box.append(alert) def on_timeout_alert(self, button): alert = TimeoutAlert(timeout=5) alert.props.title = "Timeout Alert" alert.props.msg = "This alert will disappear in 5 seconds." alert.connect("response", self.on_alert_response) self.alert_box.append(alert) def on_alert_response(self, alert, response_id): print(f"Alert response: {response_id}") self.alert_box.remove(alert) class AlertApp(Gtk.Application): def do_activate(self): window = AlertExample(self) window.present() if __name__ == "__main__": app = AlertApp() app.run() ``` -------------------------------- ### Badge Icons in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Demonstrates how to add overlay badge icons to main icons using the Icon class. This example iterates through predefined badge and main icon pairs, setting their colors and displaying them. ```python info_label = Gtk.Label(label="Icons with badges (small overlay icons):") vbox.append(info_label) hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15) hbox.set_hexpand(True) hbox.set_halign(Gtk.Align.CENTER) badges = [ ("folder", "emblem-favorite"), ("document-new", "emblem-important"), ("network-wireless", "dialog-information"), ] for main_icon, badge_icon in badges: vbox_item = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) vbox_item.set_halign(Gtk.Align.CENTER) icon = Icon(icon_name=main_icon, pixel_size=64) icon.set_badge_name(badge_icon) icon.set_fill_color("#00AA00") icon.set_stroke_color("#004400") vbox_item.append(icon) label = Gtk.Label(label=f"{main_icon}\n+ {badge_icon}") label.set_justify(Gtk.Justification.CENTER) vbox_item.append(label) hbox.append(vbox_item) vbox.append(hbox) frame.set_child(vbox) container.append(frame) ``` -------------------------------- ### Cursor Invoker Example in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This code shows how to create a palette that appears at the cursor's position when a button is clicked. It captures motion events to update the cursor position and uses `CursorInvoker` to link the palette to the button click. ```python cursor_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) cursor_btn = Gtk.Button(label="Cursor Invoker") cursor_row.append(cursor_btn) cursor_row.append(Gtk.Label(label="← Click to show at cursor position")) demo_box.append(cursor_row) cursor_palette = Palette(label="Cursor Invoker") cursor_palette.props.secondary_text = "Shows at cursor position" cursor_invoker = CursorInvoker() cursor_invoker.attach(cursor_btn) cursor_palette.set_invoker(cursor_invoker) def update_pointer_position(motion_controller, x, y): cursor_invoker._cursor_x = int(x) cursor_invoker._cursor_y = int(y) motion_controller = Gtk.EventControllerMotion() motion_controller.connect("motion", update_pointer_position) cursor_btn.add_controller(motion_controller) def show_cursor_palette(btn): cursor_palette.popup(immediate=True) cursor_btn.connect("clicked", show_cursor_palette) ``` -------------------------------- ### Control RadioToolButton State in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/docs/source/sugar4.graphics.md Provides Python examples for getting and setting the active state of a RadioToolButton. This allows programmatic control over which button in a group is currently selected. ```python from sugar4.graphics.radiotoolbutton import RadioToolButton # Assume button is an instance of RadioToolButton # button = RadioToolButton(...) # Get the active state is_active = button.get_active() # Set the active state button.set_active(True) # Activate the button button.set_active(False) # Deactivate the button ``` -------------------------------- ### Get Activity ID Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/docs/source/sugar4.activity.md The `get_id` method provides a unique identifier for the current instance of the activity. This ID is generated randomly upon starting a new instance or read from journal metadata when resuming a saved instance. ```python def get_id(self): """Get the activity id.""" pass ``` -------------------------------- ### Animate Window Size with Animator Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/autoapi/sugar4/graphics/animator/index.md This example demonstrates how to animate the default size of a GTK window using the Animator and Animation classes. It requires the gi.repository and sugar4.graphics.animator modules. The animation starts when the window is realized and runs within a GLib main loop. ```python from gi.repository import Gtk from sugar4.graphics.animator import Animator, Animation # Construct a window to animate w = Gtk.Window() w.connect('destroy', lambda w: app.quit()) # Start the animation when the window is shown w.connect('realize', lambda self: animator.start()) w.present() # Construct a 5 second animator animator = Animator(5, widget=w) # Create an animation subclass to animate the widget class SizeAnimation(Animation): def __init__(self): # Tell the animation to give us values between 20 and # 420 during the animation Animation.__init__(self, 20, 420) def next_frame(self, frame): size = int(frame) w.set_default_size(size, size) # Add the animation to the animator animation = SizeAnimation() animator.add(animation) # The animation runs inside a GLib main loop app.run() ``` -------------------------------- ### Show Preview of Creation (Python) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Generates a preview of the current creation, saves it to a temporary PNG file, and then displays it in a dialog window. Includes error handling and updates the status label based on the outcome. Handles cases where there is no content to preview. ```python def show_preview(self): """Show a preview of the current creation.""" try: preview_data = self.get_preview() if preview_data: # Save preview to temp file preview_path = "/tmp/creative_studio_preview.png" with open(preview_path, "wb") as f: f.write(preview_data) # Show preview dialog self._show_preview_dialog(preview_path) self._status_label.set_text("Preview shown") else: self._status_label.set_text("No content to preview") except Exception as e: logging.error(f"Error showing preview: {e}") self._status_label.set_text(f"Error showing preview: {e}") ``` -------------------------------- ### Sugar GTK4 Application Structure Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python code defines the main application class for a Sugar Toolkit GTK4 application. It inherits from Gtk.Application and sets up the application ID. The `do_activate` method is responsible for creating and presenting the main window when the application starts. ```python class PaletteDemoApp(Gtk.Application): def __init__(self): super().__init__(application_id="org.sugarlabs.PaletteDemo") def do_activate(self): window = PaletteDemo(self) window.present() ``` -------------------------------- ### Handle Drag Gestures for Drawing in GTK4 Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Manages user input for drawing actions using GTK's gesture system. It captures the start, update, and end of drag events to track drawing points and finalize elements, updating the canvas accordingly. ```python def _drag_begin_cb(self, gesture, x, y): """Start a new creative action.""" self._current_stroke = [(x, y)] self.queue_draw() def _drag_update_cb(self, gesture, x, y): """Continue the current action.""" result = gesture.get_start_point() if len(result) == 3: valid, start_x, start_y = result if valid: current_x = start_x + x current_y = start_y + y if self._current_tool in ["brush", "eraser"]: # For freehand tools, add all points self._current_stroke.append((current_x, current_y)) else: # For shape tools, only keep start and current point if len(self._current_stroke) == 1: self._current_stroke.append((current_x, current_y)) else: self._current_stroke[-1] = (current_x, current_y) self.queue_draw() def _drag_end_cb(self, gesture, x, y): """Finish the current action.""" if self._current_stroke: self._save_state() element_data = { "type": self._current_tool, "points": self._current_stroke[:], "color": self._current_color, "size": self._current_brush_size, "fill": self._current_fill, "timestamp": datetime.now().isoformat(), } self._elements.append(element_data) self._current_stroke = [] # Clear redo stack self._redo_stack = [] self.queue_draw() self._notify_change() ``` -------------------------------- ### Create GTK Application Entry Point in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python code defines the main entry point for the GTK application. It initializes a Gtk.Application, connects an 'activate' signal to launch the main activity, and runs the application. Dependencies include the 'sys' module for command-line arguments and the 'gi.repository' for GTK functionality. ```python def main(): app = Gtk.Application(application_id="org.sugarlabs.HelloWorldDodge") def on_activate(app): activity = HelloWorldDodgeActivity() app.add_window(activity) activity.present() app.connect("activate", on_activate) return app.run(sys.argv) if __name__ == "__main__": main() ``` -------------------------------- ### Hello World Dodge Game Initialization in Python Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python code initializes the 'Hello World Dodge!' game activity. It sets up the GTK4 window, loads custom CSS for styling, and creates the main game layout including instructions, score display, and input fields. It also defines constants for game elements and their properties. ```python """ Hello World Dodge! - Animated Game Demo for sugar-toolkit-gtk4 - Move the "Hello World!" ball with arrow keys, WASD, or buttons. - Ball moves smoothly, bounces off walls (increasing speed), and changes color. - Avoid obstacles, reach the goal to score! - Uses: Toolbox, ToolButton, Icon, XoColor, style """ import sys import os import random import math sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) import gi gi.require_version("Gtk", "4.0") gi.require_version("Gdk", "4.0") from gi.repository import Gtk, Gdk, GLib from sugar4.activity import SimpleActivity from sugar4.graphics.toolbox import Toolbox from sugar4.graphics.toolbutton import ToolButton from sugar4.graphics.icon import Icon from sugar4.graphics.xocolor import XoColor from sugar4.graphics import style BALL_RADIUS = 28 GOAL_RADIUS = 20 OBSTACLE_RADIUS = 22 BALL_INIT_SPEED = 3.0 BALL_MAX_SPEED = 50.0 BALL_SPEED_INC = 0.7 OBSTACLE_COUNT = 3 class HelloWorldDodgeActivity(SimpleActivity): """Animated Hello World Dodge Game.""" def __init__(self): super().__init__() self.set_title("Hello World Dodge!") self._create_content() def _create_content(self): css_provider = Gtk.CssProvider() css_provider.load_from_data( b""" * { color: #000000; } .game-btn { background: #e0e0e0; border-radius: 16px; border: 2px solid #888; padding: 8px 16px; margin: 2px; transition: background 150ms, border-color 150ms; } .game-btn:hover { background: #b0e0ff; border-color: #0077cc; } .score-label { font-weight: bold; font-size: 18pt; } .header-label { font-weight: bold; font-size: 22pt; } .instructions-label { font-size: 13pt; color: #222; } .center-box { margin-left: auto; margin-right: auto; } """ ) Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), # type: ignore css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION, ) # Main vertical box main_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=style.DEFAULT_SPACING ) main_box.set_margin_top(style.DEFAULT_SPACING) main_box.set_margin_bottom(style.DEFAULT_SPACING) main_box.set_margin_start(style.DEFAULT_SPACING) main_box.set_margin_end(style.DEFAULT_SPACING) # Instructions self.instructions_label = Gtk.Label() self.instructions_label.set_wrap(True) self.instructions_label.set_justify(Gtk.Justification.CENTER) self.instructions_label.set_margin_bottom(style.DEFAULT_SPACING // 2) self.instructions_label.set_markup( "How to Play:\n" "Move the ball with arrow keys, WASD, or the on-screen buttons. " "Reach the green goal, avoid red obstacles. " "Press Reset to restart. Each wall bounce increases speed!" ) self.instructions_label.get_style_context().add_class("instructions-label") main_box.append(self.instructions_label) # Welcome and Score self.header_label = Gtk.Label() self.header_label.set_markup( "Sugar Ball Dodge!" ) self.header_label.set_margin_bottom(style.DEFAULT_SPACING // 2) self.header_label.get_style_context().add_class("header-label") main_box.append(self.header_label) self.score = 0 self.score_label = Gtk.Label(label="Score: 0") self.score_label.set_margin_bottom(style.DEFAULT_SPACING) self.score_label.get_style_context().add_class("score-label") main_box.append(self.score_label) # Ball Name ( Default to Hello World Lol) name_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8) name_label = Gtk.Label(label="Your Name:") self.name_entry = Gtk.Entry() self.name_entry.set_placeholder_text("Enter your name") self.name_entry.set_max_length(16) self.name_entry.set_width_chars(12) self.name_entry.set_text("Hello World!") self.name_entry.connect("changed", self._on_name_changed) name_box.append(name_label) name_box.append(self.name_entry) main_box.append(name_box) # Toolbar with movement buttons, pause, and reset, centered toolbox = Toolbox() ``` -------------------------------- ### Create and Run a Simple GTK4 Sugar Activity (Python) Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/README.md Demonstrates how to create a basic Sugar activity using GTK4. It defines a simple activity class that displays a 'Hello, Welcome GTK4!' label and runs it as a GTK application. ```python from sugar4.activity import SimpleActivity import gi gi.require_version('Gtk', '4.0') from gi.repository import Gtk class MyActivity(SimpleActivity): def __init__(self): super().__init__() # Your activity code here label = Gtk.Label(label="Hello, Welcome GTK4!") self.set_canvas(label) def main(): """Run the activity with proper GTK4 application lifecycle.""" app = Gtk.Application(application_id='org.sugarlabs.TestActivity') def on_activate(app): activity = MyActivity() app.add_window(activity) activity.present() app.connect('activate', on_activate) return app.run() if __name__ == '__main__': main() ``` -------------------------------- ### Python GTK4 Icon Example - Complete Feature Demo Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This Python code demonstrates the complete feature set of Sugar GTK4 icons. It includes examples for basic, colored, badge, event, and canvas icons, as well as size and alpha variations. The code requires GTK4 and Sugar toolkit dependencies and generates a GUI activity to display these icon examples. ```python """Sugar GTK4 Icon Example - Complete Feature Demo.""" import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) import gi gi.require_version("Gtk", "4.0") gi.require_version("Gdk", "4.0") from gi.repository import Gtk, Gdk from sugar4.activity import SimpleActivity from sugar4.graphics.icon import Icon, EventIcon, CanvasIcon from sugar4.graphics.xocolor import XoColor class IconExampleActivity(SimpleActivity): """Example activity demonstrating all Sugar GTK4 icon features.""" def __init__(self): super().__init__() self.set_title("Sugar GTK4 Icon Example ") self._create_content() def _create_content(self): """Create the main content showing all icon types and features.""" main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=20) main_box.set_margin_start(20) main_box.set_margin_end(20) main_box.set_margin_top(20) main_box.set_margin_bottom(20) main_box.set_hexpand(True) main_box.set_vexpand(True) # Scrolled window for all content scrolled = Gtk.ScrolledWindow() scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled.set_child(main_box) scrolled.set_hexpand(True) scrolled.set_vexpand(True) # Add CSS provider for CanvasIcon hover/active states css_provider = Gtk.CssProvider() css_data = """ .canvas-icon { background-color: transparent; border-radius: 8px; padding: 4px; transition: background-color 200ms ease; } .canvas-icon:hover { background-color: rgba(0, 0, 0, 0.15); } .canvas-icon:active { background-color: rgba(0, 0, 0, 0.25); } """ try: css_provider.load_from_string(css_data) Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION, ) except Exception as e: print(f"Warning: Could not load CSS provider: {e}") # Title title = Gtk.Label() title.set_markup("Sugar GTK4 Icon Examples - Complete") title.set_hexpand(True) main_box.append(title) # Add sections self._add_basic_icons(main_box) self._add_colored_icons(main_box) self._add_badge_icons(main_box) self._add_event_icons(main_box) self._add_canvas_icons(main_box) self._add_size_and_alpha_examples(main_box) self.set_canvas(scrolled) self.set_default_size(900, 700) def _add_basic_icons(self, container): """Add basic icon examples.""" frame = Gtk.Frame(label="Basic Icons") frame.set_hexpand(True) box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) box.set_margin_start(10) box.set_margin_end(10) box.set_margin_top(10) box.set_margin_bottom(10) box.set_hexpand(True) box.set_halign(Gtk.Align.CENTER) # System icons for icon_name in [ "document-new", "document-open", "document-save", "edit-copy", "edit-paste", ]: icon = Icon(icon_name=icon_name, pixel_size=48) box.append(icon) frame.set_child(box) container.append(frame) def _add_colored_icons(self, container): """Add colored icon examples.""" frame = Gtk.Frame(label="Colored Icons") frame.set_hexpand(True) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) vbox.set_margin_start(10) vbox.set_margin_end(10) vbox.set_margin_top(10) vbox.set_margin_bottom(10) vbox.set_hexpand(True) # XO Color examples using xotest.svg hbox1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) hbox1.set_hexpand(True) hbox1.set_halign(Gtk.Align.CENTER) label1 = Gtk.Label(label="XO Colors (xotest.svg):") label1.set_size_request(150, -1) hbox1.append(label1) xotest_svg = os.path.join( os.path.dirname(__file__), "..", "src", "sugar4", "graphics", "icons", "test.svg", ) for i in range(3): xo_color = XoColor.get_random_color() icon = Icon(file_name=xotest_svg, pixel_size=48) icon.set_xo_color(xo_color) hbox1.append(icon) vbox.append(hbox1) # Manual color examples (still using xotest.svg) hbox2 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) hbox2.set_hexpand(True) hbox2.set_halign(Gtk.Align.CENTER) ``` -------------------------------- ### CursorInvoker Class Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/autoapi/sugar4/graphics/palettewindow/index.md Represents an invoker that tracks cursor position. It inherits from the Invoker class and provides methods for attaching, detaching, getting the rectangle, and getting the top-level window. ```APIDOC ## CursorInvoker Class ### Description Invoker that tracks cursor position. ### Class Definition `class sugar4.graphics.palettewindow.CursorInvoker(parent=None)` ### Methods #### attach(parent) Attaches the invoker to a parent. #### detach() Detach from the parent. #### get_rect() Get the rectangle for this invoker - implemented by subclasses. #### get_toplevel() Get the top-level window - implemented by subclasses. ``` -------------------------------- ### Generate Preview Image using Cairo Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md Generates a preview image of the current creation using the Cairo graphics library. It handles drawing the creation elements scaled to fit the preview dimensions or displays a placeholder if the canvas is empty. The output is a PNG image byte string. ```python import cairo import logging import io # ... (within a class method) def get_preview(self): """Generate a preview image of the current creation.""" try: import cairo preview_width, preview_height = 1200, 800 surface = cairo.ImageSurface( cairo.FORMAT_ARGB32, preview_width, preview_height ) cr = cairo.Context(surface) cr.set_source_rgb(1, 1, 1) cr.paint() cr.set_source_rgb(0.8, 0.8, 0.8) cr.set_line_width(2) cr.rectangle(2, 2, preview_width - 4, preview_height - 4) cr.stroke() if hasattr(self, "_creative_canvas") and self._creative_canvas._elements: # Scale the creation to fit the preview canvas_width, canvas_height = 800, 600 scale_x = (preview_width - 20) / canvas_width scale_y = (preview_height - 20) / canvas_height scale = min(scale_x, scale_y) cr.save() cr.translate(10, 10) cr.scale(scale, scale) # Draw all elements for element in self._creative_canvas._elements: self._creative_canvas._draw_element(cr, element) cr.restore() else: # No content, show placeholder cr.set_source_rgb(0.5, 0.5, 0.5) cr.select_font_face("Sans", 0, 0) cr.set_font_size(24) text = "Creative Studio" text_extents = cr.text_extents(text) x = (preview_width - text_extents.width) / 2 y = preview_height / 2 - 10 cr.move_to(x, y) cr.show_text(text) cr.set_font_size(16) text2 = "Create something amazing!" text_extents2 = cr.text_extents(text2) x2 = (preview_width - text_extents2.width) / 2 y2 = y + 40 cr.move_to(x2, y2) cr.show_text(text2) # Convert to PNG import io preview_str = io.BytesIO() surface.write_to_png(preview_str) return preview_str.getvalue() except Exception as e: logging.error(f"Error generating preview: {e}") return None ``` -------------------------------- ### Create Palette Window Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This snippet demonstrates the creation of a palette window with custom GTK widgets, including a label, progress bar, and buttons. The window can be invoked and dismissed using OK/Cancel buttons. ```python palette_window = PaletteWindow() custom_widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) custom_widget.set_margin_start(10) custom_widget.set_margin_end(10) custom_widget.set_margin_top(10) custom_widget.set_margin_bottom(10) label = Gtk.Label(label="Custom Palette Window") label.add_css_class("heading") custom_widget.append(label) progress = Gtk.ProgressBar() progress.set_fraction(0.7) progress.set_text("Progress: 70%") progress.set_show_text(True) custom_widget.append(progress) button_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) button_box.set_halign(Gtk.Align.CENTER) ok_btn = Gtk.Button(label="OK") cancel_btn = Gtk.Button(label="Cancel") button_box.append(ok_btn) button_box.append(cancel_btn) custom_widget.append(button_box) palette_window.set_content(custom_widget) window_invoker = WidgetInvoker() window_invoker.attach(window_btn) palette_window.set_invoker(window_invoker) window_btn.connect("clicked", lambda btn: palette_window.popup(immediate=True)) ok_btn.connect("clicked", lambda btn: palette_window.popdown(immediate=True)) cancel_btn.connect( "clicked", lambda btn: palette_window.popdown(immediate=True) ) ``` -------------------------------- ### Deprecated Get MIME Type from File Name Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/autoapi/sugar4/mime/index.md A deprecated function to get the MIME type from a file name. It is recommended to use Gio.content_type_guess instead for newer versions. ```python sugar4.mime.get_from_file_name(file_name) ``` -------------------------------- ### Create Menu Palette Source: https://github.com/sugarlabs/sugar-toolkit-gtk4/blob/main/docs/examples.md This snippet shows how to create a menu palette with several menu items. Each item has a label and an icon, and connects to a feedback function. The menu palette is invoked via a button click. ```python menu_palette = Palette(label="Menu Options") menu_palette.props.secondary_text = "Right-click or use menu property for options" menu = menu_palette.menu def feedback(msg): self.menu_feedback_label.set_text(msg) item1 = PaletteMenuItem("Open File", "document-open") item1.connect("activate", lambda x: feedback("Open File clicked")) menu.append(item1) item2 = PaletteMenuItem("Save File", "document-save") item2.connect("activate", lambda x: feedback("Save File clicked")) menu.append(item2) menu.append(PaletteMenuItemSeparator()) item3 = PaletteMenuItem("Settings", "preferences-system") item3.connect("activate", lambda x: feedback("Settings clicked")) menu.append(item3) menu_invoker = WidgetInvoker() menu_invoker.attach_widget(menu_btn) menu_palette.set_invoker(menu_invoker) menu_btn.connect("clicked", lambda btn: menu_palette.popup(immediate=True)) ```