mirror of
https://gitlab.gnome.org/jpu/cambalache.git
synced 2025-08-01 00:03:29 -04:00
Compare commits
2 Commits
19851963fb
...
fa89006ff2
Author | SHA1 | Date | |
---|---|---|---|
|
fa89006ff2 | ||
|
15b8ecf3d8 |
@ -1,6 +1,6 @@
|
||||
# Cambalache
|
||||
#
|
||||
# Copyright (C) 2021 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2023 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -28,10 +28,10 @@ import builtins
|
||||
|
||||
from . import config
|
||||
|
||||
gi.require_version("Gdk", "3.0")
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version("GtkSource", "4")
|
||||
gi.require_version("WebKit2", "4.1")
|
||||
gi.require_version("Gdk", "4.0")
|
||||
gi.require_version("Gtk", "4.0")
|
||||
gi.require_version("GtkSource", "5")
|
||||
gi.require_version("WebKit", "6.0")
|
||||
|
||||
# Ensure _() builtin
|
||||
if "_" not in builtins.__dict__:
|
||||
@ -54,8 +54,9 @@ resource._register()
|
||||
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_resource("/ar/xjuan/Cambalache/cambalache.css")
|
||||
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
Gtk.IconTheme.get_default().add_resource_path("/ar/xjuan/Cambalache/icons")
|
||||
display = Gdk.Display.get_default()
|
||||
Gtk.StyleContext.add_provider_for_display(display, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
Gtk.IconTheme.get_for_display(display).add_resource_path("/ar/xjuan/Cambalache/icons")
|
||||
|
||||
|
||||
def getLogger(name):
|
||||
|
@ -21,27 +21,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
@binding-set WindowBindings {
|
||||
bind "<Control>s" { "cmb-action" ("save") };
|
||||
bind "<Control>w" { "cmb-action" ("close") };
|
||||
bind "<Control>z" { "cmb-action" ("undo") };
|
||||
bind "<Control><shift>z" { "cmb-action" ("redo") };
|
||||
bind "Delete" { "cmb-action" ("delete") };
|
||||
bind "<Control>n" { "cmb-action" ("create_new") };
|
||||
bind "<Control>o" { "cmb-action" ("open") };
|
||||
bind "<Control>Insert" { "cmb-action-bool" ("add_placeholder", 0) };
|
||||
bind "<Control>Delete" { "cmb-action-bool" ("remove_placeholder", 0) };
|
||||
bind "<Control><shift>Insert" { "cmb-action-bool" ("add_placeholder", 1) };
|
||||
bind "<Control><shift>Delete" { "cmb-action-bool" ("remove_placeholder", 1) };
|
||||
}
|
||||
|
||||
CmbWindow .logo {
|
||||
background: url('resource:///ar/xjuan/Cambalache/app/images/logo-symbolic.svg') no-repeat 50% 35% / 40%
|
||||
background: url('resource:///ar/xjuan/Cambalache/app/images/logo-symbolic.svg') no-repeat 50% 35% / 40%;
|
||||
}
|
||||
|
||||
CmbWindow.dark .logo {
|
||||
color: white;
|
||||
background: -gtk-recolor(url('resource:///ar/xjuan/Cambalache/app/images/logo-symbolic.svg'), success #ffcb85, error #1a1a1a) no-repeat 50% 35% / 40%
|
||||
background: -gtk-recolor(url('resource:///ar/xjuan/Cambalache/app/images/logo-symbolic.svg'), success #ffcb85, error #1a1a1a) no-repeat 50% 35% / 40%;
|
||||
}
|
||||
|
||||
CmbWindow label.message {
|
||||
@ -56,7 +43,7 @@ CmbWindow.dark label.message {
|
||||
background-color: rgba(255, 255, 255, .6);
|
||||
}
|
||||
|
||||
popover.cmb-tutor {
|
||||
popover.cmb-tutor > * {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
@ -65,13 +52,23 @@ popover.cmb-tutor label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
popover.cmb-tutor image {
|
||||
padding-right: 1em;
|
||||
-gtk-icon-size: 48px;
|
||||
}
|
||||
|
||||
button.cmb-tutor-highlight,
|
||||
modelbutton.cmb-tutor-highlight,
|
||||
buttonbox.cmb-tutor-highlight > button,
|
||||
stackswitcher.cmb-tutor-highlight > button,
|
||||
entry.cmb-tutor-highlight,
|
||||
treeview.cmb-tutor-highlight,
|
||||
box.cmb-tutor-highlight {
|
||||
box.cmb-tutor-highlight,
|
||||
CmbView.cmb-tutor-highlight {
|
||||
box-shadow: inset 0px 0px 6px @theme_selected_bg_color;
|
||||
transition: box-shadow .75s ease;
|
||||
}
|
||||
|
||||
CmbView.cmb-tutor-highlight {
|
||||
padding: 6px;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Cambalache Application
|
||||
#
|
||||
# Copyright (C) 2021 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2024 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -43,7 +43,8 @@ class CmbApplication(Gtk.Application):
|
||||
def __add_window(self):
|
||||
window = CmbWindow(application=self)
|
||||
window.connect("open-project", self.__on_open_project)
|
||||
window.connect("delete-event", self.__on_window_delete_event)
|
||||
|
||||
window.connect("close-request", self.__on_window_close_request)
|
||||
self.add_window(window)
|
||||
return window
|
||||
|
||||
@ -91,7 +92,7 @@ class CmbApplication(Gtk.Application):
|
||||
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_resource("/ar/xjuan/Cambalache/app/cambalache.css")
|
||||
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
||||
def do_activate(self):
|
||||
if self.props.active_window is None:
|
||||
@ -103,9 +104,17 @@ class CmbApplication(Gtk.Application):
|
||||
else:
|
||||
self.open_project(filename, target_tk, uiname)
|
||||
|
||||
def __check_can_quit(self, windows):
|
||||
def __check_can_quit(self, window=None):
|
||||
windows = self.__get_windows() if window is None else [window]
|
||||
unsaved_windows = []
|
||||
projects2save = []
|
||||
windows2save = []
|
||||
|
||||
def do_quit():
|
||||
if window is None:
|
||||
self.quit()
|
||||
else:
|
||||
self.remove_window(window)
|
||||
window.destroy()
|
||||
|
||||
# Gather projects that needs saving
|
||||
for win in windows:
|
||||
@ -117,16 +126,17 @@ class CmbApplication(Gtk.Application):
|
||||
|
||||
unsaved_windows_len = len(unsaved_windows)
|
||||
if unsaved_windows_len == 0:
|
||||
return True
|
||||
do_quit()
|
||||
return
|
||||
|
||||
# Create Dialog
|
||||
text = _("Save changes before closing?")
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=windows[0],
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.QUESTION,
|
||||
text=f"<b><big>{text}</big></b>",
|
||||
use_markup=True,
|
||||
modal=True
|
||||
)
|
||||
|
||||
# Add buttons
|
||||
@ -141,36 +151,58 @@ class CmbApplication(Gtk.Application):
|
||||
|
||||
dialog.set_default_response(Gtk.ResponseType.ACCEPT)
|
||||
|
||||
if unsaved_windows_len > 1:
|
||||
if unsaved_windows_len > 1 or unsaved_windows[0].project.filename is None:
|
||||
# Add checkbox for each unsaved project
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4)
|
||||
box.add(Gtk.Label(label=_("Select which files:"), halign=Gtk.Align.START))
|
||||
box.append(Gtk.Label(label=_("Select which files:"), halign=Gtk.Align.START))
|
||||
|
||||
home = GLib.get_home_dir()
|
||||
untitled = 0
|
||||
|
||||
for win in unsaved_windows:
|
||||
path = win.project.filename.replace(GLib.get_home_dir(), "~")
|
||||
check = Gtk.CheckButton(label=path, active=True, margin_start=8, can_focus=False)
|
||||
projects2save.append((win.project, check))
|
||||
box.add(check)
|
||||
if win.project.filename is None:
|
||||
untitled += 1
|
||||
|
||||
box.show_all()
|
||||
dialog.props.message_area.add(box)
|
||||
# Find Unique name
|
||||
while os.path.exists(f"Untitled {untitled}.cmb"):
|
||||
untitled += 1
|
||||
|
||||
# Run Dialog
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
check = Gtk.CheckButton(active=True, margin_start=8, can_focus=False)
|
||||
entry = Gtk.Entry(text=f"Untitled {untitled}")
|
||||
|
||||
# Handle response
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
if unsaved_windows_len > 1:
|
||||
for project, check in projects2save:
|
||||
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=4)
|
||||
hbox.append(check)
|
||||
hbox.append(entry)
|
||||
|
||||
box.append(hbox)
|
||||
else:
|
||||
path = win.project.filename.replace(home, "~")
|
||||
check = Gtk.CheckButton(label=path, active=True, margin_start=8, can_focus=False)
|
||||
box.append(check)
|
||||
|
||||
windows2save.append((win, check, entry))
|
||||
|
||||
box.show()
|
||||
dialog.props.message_area.append(box)
|
||||
else:
|
||||
windows2save.append((unsaved_windows[0], None, None))
|
||||
|
||||
def callback(dialog, response, window):
|
||||
dialog.destroy()
|
||||
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
for win, check, entry in windows2save:
|
||||
if entry is not None:
|
||||
win.project.filename = entry.props.text
|
||||
if check is None or check.props.active:
|
||||
project.save()
|
||||
elif unsaved_windows_len:
|
||||
unsaved_windows[0].project.save()
|
||||
elif response == Gtk.ResponseType.CANCEL:
|
||||
return False
|
||||
win.save_project()
|
||||
elif response == Gtk.ResponseType.CANCEL:
|
||||
return
|
||||
|
||||
return True
|
||||
do_quit()
|
||||
|
||||
dialog.connect("response", callback, window)
|
||||
dialog.present()
|
||||
|
||||
def __get_windows(self):
|
||||
retval = []
|
||||
@ -181,8 +213,9 @@ class CmbApplication(Gtk.Application):
|
||||
|
||||
return retval
|
||||
|
||||
def __on_window_delete_event(self, window, event):
|
||||
return not self.__check_can_quit([window])
|
||||
def __on_window_close_request(self, window):
|
||||
self.__check_can_quit(window)
|
||||
return True
|
||||
|
||||
def do_window_removed(self, window):
|
||||
windows = self.__get_windows()
|
||||
@ -191,8 +224,7 @@ class CmbApplication(Gtk.Application):
|
||||
self.activate_action("quit")
|
||||
|
||||
def _on_quit_activate(self, action, data):
|
||||
if self.__check_can_quit(self.__get_windows()):
|
||||
self.quit()
|
||||
self.__check_can_quit()
|
||||
|
||||
def do_handle_local_options(self, options):
|
||||
if options.contains("version"):
|
||||
|
@ -1,86 +1,74 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.9.0 -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-name cmb_shortcuts.ui -->
|
||||
<requires lib="gtk+" version="3.0"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkShortcutsWindow" id="shortcuts">
|
||||
<property name="section-name">shortcuts</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="section-name">shortcuts</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">Project</property>
|
||||
<property name="title" translatable="1">Project</property>
|
||||
<property name="view">shortcuts</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>n</property>
|
||||
<property name="title" translatable="yes">Create new project</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Create new project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>o</property>
|
||||
<property name="title" translatable="yes">Open a project</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Open a project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>w</property>
|
||||
<property name="title" translatable="yes">Close the project</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Close the project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>s</property>
|
||||
<property name="title" translatable="yes">Save the project</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Save the project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">0</property>
|
||||
<property name="accelerator"><Control>e</property>
|
||||
<property name="title" translatable="yes">Save and Export</property>
|
||||
<property name="title" translatable="1">Save and Export</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">Workspace</property>
|
||||
<property name="title" translatable="1">Workspace</property>
|
||||
<property name="view">shortcuts</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>Insert</property>
|
||||
<property name="title" translatable="yes">Add slot/column</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Add slot/column</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>Delete</property>
|
||||
<property name="title" translatable="yes">Remove slot/column</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Remove slot/column</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control><shift>Insert</property>
|
||||
<property name="title" translatable="yes">Add row</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Add row</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control><shift>Delete</property>
|
||||
<property name="title" translatable="yes">Remove row</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="1">Remove row</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -26,6 +26,7 @@
|
||||
from gi.repository import GObject, GLib, Gdk, Gtk
|
||||
from enum import Enum
|
||||
from collections import namedtuple
|
||||
from cambalache import utils
|
||||
|
||||
|
||||
class CmbTutorState(Enum):
|
||||
@ -85,32 +86,30 @@ class CmbTutor(GObject.GObject):
|
||||
def __add(self, text, widget_name, delay, name=None, position=CmbTutorPosition.BOTTOM):
|
||||
retval = {}
|
||||
|
||||
def find_widget(w, data):
|
||||
if data.get("widget", None):
|
||||
return
|
||||
def find_by_css_name_or_buildable_id(widget, name):
|
||||
retval = None
|
||||
css_name = widget.get_name()
|
||||
|
||||
name = None
|
||||
n = w.get_name()
|
||||
# Get css name first
|
||||
if css_name and css_name != GObject.type_name(widget) and css_name == name:
|
||||
return widget
|
||||
|
||||
# Get css name first then GtkBuildable name
|
||||
if n and n != GObject.type_name(w):
|
||||
name = n
|
||||
elif isinstance(w, Gtk.Buildable):
|
||||
n = Gtk.Buildable.get_name(w)
|
||||
if n and not n.startswith("___object"):
|
||||
name = n
|
||||
# then GtkBuildable name
|
||||
if isinstance(widget, Gtk.Buildable) and Gtk.Buildable.get_buildable_id(widget) == name:
|
||||
return widget
|
||||
|
||||
# Return widget
|
||||
if name == widget_name:
|
||||
data["widget"] = w
|
||||
return
|
||||
# or ModelButton name
|
||||
if GObject.type_name(widget) == "GtkModelButton" and widget.props.text == name:
|
||||
return widget
|
||||
|
||||
if isinstance(w, Gtk.Container):
|
||||
w.forall(find_widget, data)
|
||||
for child in utils.widget_get_children(widget):
|
||||
retval = find_by_css_name_or_buildable_id(child, name)
|
||||
if retval:
|
||||
return retval
|
||||
|
||||
self.window.forall(find_widget, retval)
|
||||
return retval
|
||||
|
||||
widget = retval.get("widget", None)
|
||||
widget = find_by_css_name_or_buildable_id(self.window, widget_name)
|
||||
|
||||
if widget:
|
||||
self.script.append(ScriptNode(widget, text, delay, name, position))
|
||||
@ -140,14 +139,19 @@ class CmbTutor(GObject.GObject):
|
||||
self.notify("state")
|
||||
|
||||
def __popover_new(self, text):
|
||||
popover = Gtk.Popover(modal=False)
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
||||
popover = Gtk.Popover(autohide=False)
|
||||
popover.add_css_class("cmb-tutor")
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, hexpand=True)
|
||||
|
||||
box.add(Gtk.Image(icon_name="dialog-information-symbolic", icon_size=Gtk.IconSize.DIALOG))
|
||||
box.add(Gtk.Label(label=text, wrap=True, max_width_chars=28))
|
||||
popover.add(box)
|
||||
popover.get_style_context().add_class("cmb-tutor")
|
||||
box.show_all()
|
||||
box.append(Gtk.Image(icon_name="dialog-information-symbolic"))
|
||||
box.append(Gtk.Label(
|
||||
label=text,
|
||||
vexpand=False,
|
||||
hexpand=True,
|
||||
wrap=True,
|
||||
max_width_chars=24
|
||||
))
|
||||
popover.set_child(box)
|
||||
|
||||
return popover
|
||||
|
||||
@ -203,11 +207,11 @@ class CmbTutor(GObject.GObject):
|
||||
if parent:
|
||||
parent.popup()
|
||||
|
||||
node.widget.get_style_context().add_class("cmb-tutor-highlight")
|
||||
node.widget.add_css_class("cmb-tutor-highlight")
|
||||
|
||||
# Create popover
|
||||
self.popover = self.__popover_new(node.text)
|
||||
self.popover.set_relative_to(node.widget)
|
||||
self.popover.set_parent(node.widget)
|
||||
|
||||
if node.position == CmbTutorPosition.BOTTOM:
|
||||
self.popover.set_position(Gtk.PositionType.BOTTOM)
|
||||
|
@ -36,9 +36,9 @@ intro = [
|
||||
(_("Common actions like Undo"), "undo_button", 4),
|
||||
(_("Redo"), "redo_button", 2),
|
||||
(_("Add new UI file"), "add_button", 3),
|
||||
(_("and Save are directly accessible in the headerbar"), "save_button", 6),
|
||||
(_("and Save are directly accessible in the headerbar"), "cmb_save_button", 6),
|
||||
(_("just like Save As"), "save_as_button", 2),
|
||||
(_("and the main menu"), "menu_button", 3),
|
||||
(_("and the main menu"), "menu_button", 3, "menu_button"),
|
||||
(_("Create a project to continue"), "intro_button", 2, "add-project"),
|
||||
(_("Great!"), "intro_button", 2),
|
||||
(
|
||||
@ -66,14 +66,21 @@ intro = [
|
||||
(_("Quite easy! Isn't it?"), "intro_button", 3),
|
||||
(
|
||||
_("Once you finish, you can export all UI files to xml here"),
|
||||
"export_all",
|
||||
_("Export all"),
|
||||
5,
|
||||
"main-menu",
|
||||
CmbTutorPosition.LEFT,
|
||||
),
|
||||
(
|
||||
_("If you have any question, contact us on Matrix!"),
|
||||
_("Contact"),
|
||||
7,
|
||||
None,
|
||||
CmbTutorPosition.LEFT,
|
||||
),
|
||||
(
|
||||
_("That is all for now.\nIf you find Cambalache useful please consider donating"),
|
||||
"donate",
|
||||
_("Donate"),
|
||||
7,
|
||||
"donate",
|
||||
CmbTutorPosition.LEFT,
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# CmbWindow
|
||||
#
|
||||
# Copyright (C) 2021-2023 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2024 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -30,7 +30,7 @@ from gi.repository import GLib, GObject, Gio, Gdk, Gtk, Pango
|
||||
from .cmb_tutor import CmbTutor, CmbTutorState
|
||||
from . import cmb_tutorial
|
||||
|
||||
from cambalache import CmbProject, CmbUI, CmbCSS, CmbObject, CmbTypeChooserPopover, getLogger, config, _
|
||||
from cambalache import CmbProject, CmbUI, CmbCSS, CmbObject, CmbTypeChooserPopover, getLogger, config, utils, _
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
@ -39,15 +39,17 @@ logger = getLogger(__name__)
|
||||
class CmbWindow(Gtk.ApplicationWindow):
|
||||
__gtype_name__ = "CmbWindow"
|
||||
|
||||
__gsignals__ = {"open-project": (GObject.SignalFlags.RUN_FIRST, None, (str, str, str))}
|
||||
__gsignals__ = {
|
||||
"open-project": (GObject.SignalFlags.RUN_FIRST, None, (str, str, str)),
|
||||
"project-saved": (GObject.SignalFlags.RUN_FIRST, None, (CmbProject, ))
|
||||
}
|
||||
|
||||
open_filter = Gtk.Template.Child()
|
||||
import_filter = Gtk.Template.Child()
|
||||
|
||||
open_button_box = Gtk.Template.Child()
|
||||
import_button_box = Gtk.Template.Child()
|
||||
|
||||
headerbar = Gtk.Template.Child()
|
||||
subtitle = Gtk.Template.Child()
|
||||
recent_menu = Gtk.Template.Child()
|
||||
undo_button = Gtk.Template.Child()
|
||||
redo_button = Gtk.Template.Child()
|
||||
stack = Gtk.Template.Child()
|
||||
@ -85,62 +87,83 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
|
||||
# Tutor widgets
|
||||
intro_button = Gtk.Template.Child()
|
||||
main_menu = Gtk.Template.Child()
|
||||
export_all = Gtk.Template.Child()
|
||||
menu_button = Gtk.Template.Child()
|
||||
|
||||
# Settings
|
||||
completed_intro = GObject.Property(type=bool, default=False, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
MAXIMIZED = 1 << 2
|
||||
FULLSCREEN = 1 << 4
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__project = None
|
||||
self.__last_saved_index = None
|
||||
self.__np_location = None
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.editor_stack.set_size_request(420, -1)
|
||||
|
||||
self.actions = {}
|
||||
self.open_button_box.props.homogeneous = False
|
||||
self.import_button_box.props.homogeneous = False
|
||||
|
||||
for action in [
|
||||
"open",
|
||||
"create_new",
|
||||
"new",
|
||||
"undo",
|
||||
"redo",
|
||||
"intro",
|
||||
"save",
|
||||
"save_as",
|
||||
"add_ui",
|
||||
"about",
|
||||
"add_css",
|
||||
"copy",
|
||||
"paste",
|
||||
"cut",
|
||||
"delete",
|
||||
"add_object",
|
||||
"add_object_toplevel",
|
||||
"clear",
|
||||
"add_placeholder",
|
||||
"remove_placeholder",
|
||||
"add_placeholder_row",
|
||||
"remove_placeholder_row",
|
||||
"import",
|
||||
"export",
|
||||
"add_ui",
|
||||
"clear",
|
||||
"close",
|
||||
"debug",
|
||||
"show_workspace",
|
||||
"donate",
|
||||
"liberapay",
|
||||
"patreon",
|
||||
"contact",
|
||||
"about",
|
||||
"copy",
|
||||
"create_new",
|
||||
"cut",
|
||||
"debug",
|
||||
"delete",
|
||||
"donate",
|
||||
"export",
|
||||
"import",
|
||||
"intro",
|
||||
"liberapay",
|
||||
"new",
|
||||
"open",
|
||||
"paste",
|
||||
"patreon",
|
||||
"redo",
|
||||
"remove_placeholder",
|
||||
"remove_placeholder_row",
|
||||
"save",
|
||||
"save_as",
|
||||
"select_project_location",
|
||||
"show_workspace",
|
||||
"undo",
|
||||
"workspace_restart",
|
||||
"inspect"
|
||||
]:
|
||||
gaction = Gio.SimpleAction.new(action, None)
|
||||
gaction.connect("activate", getattr(self, f"_on_{action}_activate"))
|
||||
self.actions[action] = gaction
|
||||
self.add_action(gaction)
|
||||
|
||||
# Stateful actions
|
||||
for action, parameter_type, state in [
|
||||
("open_recent", "s", None),
|
||||
("workspace_theme", "s", "")
|
||||
]:
|
||||
if state is None:
|
||||
gaction = Gio.SimpleAction.new(action, GLib.VariantType.new(parameter_type))
|
||||
else:
|
||||
gaction = Gio.SimpleAction.new_stateful(
|
||||
action,
|
||||
GLib.VariantType.new(parameter_type),
|
||||
GLib.Variant(parameter_type, state)
|
||||
)
|
||||
gaction.connect("activate", getattr(self, f"_on_{action}_activate"))
|
||||
self.actions[action] = gaction
|
||||
self.add_action(gaction)
|
||||
|
||||
# Add global accelerators
|
||||
action_map = [
|
||||
("win.save", ["<Primary>s"]),
|
||||
@ -205,7 +228,7 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
)
|
||||
|
||||
self.tutor = None
|
||||
self.turor_waiting_for_user_action = False
|
||||
self.tutor_waiting_for_user_action = False
|
||||
|
||||
self.__clipboard_enabled = True
|
||||
self.__message_timeout_id = None
|
||||
@ -237,6 +260,14 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
|
||||
self.view.connect("notify::gtk-theme", self.__on_view_gtk_theme_notify)
|
||||
self.connect("notify::focus-widget", self.__on_focus_widget_notify)
|
||||
self.__update_recent_menu()
|
||||
|
||||
def __on_view_gtk_theme_notify(self, obj, pspec):
|
||||
print("__on_view_gtk_theme_notify", obj.props.gtk_theme)
|
||||
#self.actions["workspace_theme"].set_state(GLib.Variant("s", obj.props.gtk_theme))
|
||||
|
||||
@GObject.Property(type=CmbProject)
|
||||
def project(self):
|
||||
return self.__project
|
||||
@ -246,7 +277,6 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
if self.__project is not None:
|
||||
self.__project.disconnect_by_func(self.__on_project_filename_notify)
|
||||
self.__project.disconnect_by_func(self.__on_project_selection_changed)
|
||||
self.__project.disconnect_by_func(self.__on_project_filename_required)
|
||||
self.__project.disconnect_by_func(self.__on_project_changed)
|
||||
|
||||
self.__project = project
|
||||
@ -267,10 +297,9 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.__on_project_filename_notify(None, None)
|
||||
self.__project.connect("notify::filename", self.__on_project_filename_notify)
|
||||
self.__project.connect("selection-changed", self.__on_project_selection_changed)
|
||||
self.__project.connect("filename-required", self.__on_project_filename_required)
|
||||
self.__project.connect("changed", self.__on_project_changed)
|
||||
else:
|
||||
self.headerbar.set_subtitle(None)
|
||||
self.subtitle.props.visible = False
|
||||
|
||||
self.__update_actions()
|
||||
|
||||
@ -279,15 +308,9 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
path = self.project.filename.replace(GLib.get_home_dir(), "~")
|
||||
else:
|
||||
path = _("Untitled")
|
||||
self.headerbar.set_subtitle(path)
|
||||
|
||||
@Gtk.Template.Callback("on_about_dialog_delete_event")
|
||||
def __on_about_dialog_delete_event(self, widget, event):
|
||||
return True
|
||||
|
||||
@Gtk.Template.Callback("on_about_dialog_response")
|
||||
def __on_about_dialog_response(self, widget, response_id):
|
||||
widget.hide()
|
||||
self.subtitle.props.visible = True
|
||||
self.subtitle.props.label = path
|
||||
|
||||
@Gtk.Template.Callback("on_type_chooser_type_selected")
|
||||
def __on_type_chooser_type_selected(self, popover, info):
|
||||
@ -297,10 +320,10 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
if obj and type(obj) not in [CmbObject, CmbUI]:
|
||||
return
|
||||
|
||||
valid, state = Gtk.get_current_event_state()
|
||||
device = self.get_display().get_default_seat().get_keyboard()
|
||||
|
||||
# If alt is pressed, force adding object to selection
|
||||
if valid and bool(state & Gdk.ModifierType.MOD1_MASK):
|
||||
if device and bool(device.props.modifier_state & Gdk.ModifierType.ALT_MASK):
|
||||
if obj:
|
||||
parent_id = obj.object_id if isinstance(obj, CmbObject) else None
|
||||
self.project.add_object(obj.ui_id, info.type_id, None, parent_id)
|
||||
@ -334,12 +357,9 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
|
||||
@Gtk.Template.Callback("on_view_placeholder_activated")
|
||||
def __on_view_placeholder_activated(self, view, ui_id, object_id, layout, position, child_type):
|
||||
r = Gdk.Rectangle()
|
||||
r.x, r.y = self.view.get_pointer()
|
||||
r.width = r.height = 4
|
||||
|
||||
obj = self.project.get_object_by_id(ui_id, object_id)
|
||||
popover = CmbTypeChooserPopover(relative_to=self.view, pointing_to=r, parent_type_id=obj.type_id)
|
||||
popover = CmbTypeChooserPopover(pointing_to=utils.get_pointing_to(self.view), parent_type_id=obj.type_id)
|
||||
popover.set_parent(self.view)
|
||||
|
||||
popover.project = self.project
|
||||
|
||||
@ -349,13 +369,6 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
)
|
||||
popover.popup()
|
||||
|
||||
@Gtk.Template.Callback("on_open_recent_action_item_activated")
|
||||
def __on_open_recent_action_item_activated(self, recent):
|
||||
uri = recent.get_current_uri()
|
||||
if uri is not None:
|
||||
filename, host = GLib.filename_from_uri(uri)
|
||||
self.emit("open-project", filename, None, None)
|
||||
|
||||
@Gtk.Template.Callback("on_ui_editor_remove_ui")
|
||||
def __on_ui_editor_remove_ui(self, editor):
|
||||
self.__remove_object_with_confirmation(editor.object)
|
||||
@ -366,9 +379,10 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.__remove_object_with_confirmation(editor.object)
|
||||
return True
|
||||
|
||||
@Gtk.Template.Callback("on_window_set_focus")
|
||||
def __on_window_set_focus(self, window, widget):
|
||||
types = [Gtk.Entry, Gtk.TextView, Gtk.SpinButton]
|
||||
def __on_focus_widget_notify(self, obj, pspec):
|
||||
widget = self.props.focus_widget
|
||||
|
||||
types = [Gtk.Text, Gtk.TextView]
|
||||
focused_widget_needs = True
|
||||
|
||||
for type in types:
|
||||
@ -413,16 +427,16 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
r, g, b = (linear(c.red), linear(c.green), linear(c.blue))
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b
|
||||
|
||||
ctx = self.get_style_context()
|
||||
|
||||
# Get foreground color
|
||||
fg = ctx.get_color(Gtk.StateFlags.NORMAL)
|
||||
fg = self.get_color()
|
||||
|
||||
# If foreground luminance is closer to 1 then the background must be dark
|
||||
if luminance(fg) > 0.5:
|
||||
ctx.add_class("dark")
|
||||
self.add_css_class("dark")
|
||||
self.view._set_dark_mode(True)
|
||||
else:
|
||||
ctx.remove_class("dark")
|
||||
self.remove_css_class("dark")
|
||||
self.view._set_dark_mode(False)
|
||||
|
||||
def __np_name_to_ui(self, binding, value):
|
||||
if len(value):
|
||||
@ -549,20 +563,16 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.__update_action_undo_redo()
|
||||
self.__update_action_add_object()
|
||||
|
||||
def __file_open_dialog_new(
|
||||
self, title, action=Gtk.FileChooserAction.OPEN, filter_obj=None, select_multiple=False, accept_label=None
|
||||
):
|
||||
dialog = Gtk.FileChooserNative(
|
||||
def __file_open_dialog_new(self, title, filter_obj=None, accept_label=None):
|
||||
dialog = Gtk.FileDialog(
|
||||
modal=True,
|
||||
title=title,
|
||||
transient_for=self,
|
||||
action=action,
|
||||
filter=filter_obj,
|
||||
select_multiple=select_multiple,
|
||||
default_filter=filter_obj,
|
||||
accept_label=accept_label,
|
||||
)
|
||||
|
||||
if self.project and self.project.filename:
|
||||
dialog.set_current_folder(os.path.dirname(self.project.filename))
|
||||
dialog.set_initial_folder(Gio.File.new_for_path(os.path.dirname(self.project.filename)))
|
||||
|
||||
return dialog
|
||||
|
||||
@ -580,18 +590,21 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
def present_message_to_user(self, message, secondary_text=None, details=None):
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=self,
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.INFO,
|
||||
buttons=Gtk.ButtonsType.OK,
|
||||
text=message,
|
||||
secondary_text=secondary_text,
|
||||
modal=True
|
||||
)
|
||||
|
||||
if details:
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4)
|
||||
box = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL,
|
||||
spacing=4
|
||||
)
|
||||
|
||||
for detail in details:
|
||||
box.add(
|
||||
box.append(
|
||||
Gtk.Label(
|
||||
label=detail,
|
||||
halign=Gtk.Align.START,
|
||||
@ -602,12 +615,10 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
ellipsize=Pango.EllipsizeMode.END,
|
||||
)
|
||||
)
|
||||
dialog.props.message_area.append(box)
|
||||
|
||||
box.show_all()
|
||||
dialog.props.message_area.add(box)
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
dialog.connect("response", lambda d, r: dialog.destroy())
|
||||
dialog.present()
|
||||
|
||||
def import_file(self, filename):
|
||||
if self.project is None:
|
||||
@ -688,25 +699,41 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
)
|
||||
|
||||
def _on_open_activate(self, action, data):
|
||||
dialog = self.__file_open_dialog_new(_("Choose project to open"), filter_obj=self.open_filter)
|
||||
if dialog.run() == Gtk.ResponseType.ACCEPT:
|
||||
self.emit("open-project", dialog.get_filename(), None, None)
|
||||
def dialog_callback(dialog, res):
|
||||
try:
|
||||
file = dialog.open_finish(res)
|
||||
self.emit("open-project", file.get_path(), None, None)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
dialog.destroy()
|
||||
dialog = self.__file_open_dialog_new(_("Choose project to open"), filter_obj=self.open_filter)
|
||||
dialog.open(self, None, dialog_callback)
|
||||
|
||||
def _on_select_project_location_activate(self, action, data):
|
||||
def dialog_callback(dialog, res):
|
||||
try:
|
||||
self.__np_location = dialog.select_folder_finish(res).get_path()
|
||||
self.np_location_chooser.props.label = os.path.basename(self.__np_location)
|
||||
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
dialog = self.__file_open_dialog_new(_("Select project location"))
|
||||
dialog.select_folder(self, None, dialog_callback)
|
||||
|
||||
def _on_create_new_activate(self, action, data):
|
||||
self.__set_page("new_project")
|
||||
self.set_focus(self.np_name_entry)
|
||||
|
||||
home = GLib.get_home_dir()
|
||||
projects = os.path.join(home, "Projects")
|
||||
directory = projects if os.path.isdir(projects) else home
|
||||
if self.__np_location is None:
|
||||
home = GLib.get_home_dir()
|
||||
projects = os.path.join(home, "Projects")
|
||||
self.__np_location = projects if os.path.isdir(projects) else home
|
||||
|
||||
self.np_location_chooser.set_current_folder(directory)
|
||||
self.np_location_chooser.props.label = os.path.basename(self.__np_location)
|
||||
|
||||
def _on_new_activate(self, action, data):
|
||||
name = self.np_name_entry.props.text
|
||||
location = self.np_location_chooser.get_filename() or "."
|
||||
uiname = self.np_ui_entry.props.text
|
||||
filename = None
|
||||
uipath = None
|
||||
@ -718,7 +745,7 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
|
||||
if len(name):
|
||||
name, ext = os.path.splitext(name)
|
||||
filename = os.path.join(location, name + ".cmb")
|
||||
filename = os.path.join(self.__np_location, name + ".cmb")
|
||||
|
||||
if len(uiname) == 0:
|
||||
uiname = self.np_ui_entry.props.placeholder_text
|
||||
@ -728,7 +755,7 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.set_focus(self.np_name_entry)
|
||||
return
|
||||
|
||||
uipath = os.path.join(location, uiname)
|
||||
uipath = os.path.join(self.__np_location, uiname)
|
||||
|
||||
self.emit("open-project", filename, target_tk, uipath)
|
||||
self.__set_page("workspace" if self.project is not None else "cambalache")
|
||||
@ -743,30 +770,23 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.project.redo()
|
||||
self.__update_action_undo_redo()
|
||||
|
||||
def __on_project_filename_required(self, project):
|
||||
filename = None
|
||||
|
||||
if project.filename is None:
|
||||
dialog = self.__file_open_dialog_new(_("Choose a file to save the project"), Gtk.FileChooserAction.SAVE)
|
||||
if dialog.run() == Gtk.ResponseType.ACCEPT:
|
||||
filename = dialog.get_filename()
|
||||
dialog.destroy()
|
||||
|
||||
return filename
|
||||
|
||||
def _on_save_activate(self, action, data):
|
||||
self.__save_project()
|
||||
self.save_project()
|
||||
|
||||
def __save_dialog_callback(self, dialog, res):
|
||||
try:
|
||||
file = dialog.save_finish(res)
|
||||
self.project.filename = file.get_path()
|
||||
self.__save()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def _on_save_as_activate(self, action, data):
|
||||
if self.project is None:
|
||||
return
|
||||
|
||||
dialog = self.__file_open_dialog_new(_("Choose a new file to save the project"), Gtk.FileChooserAction.SAVE)
|
||||
if dialog.run() == Gtk.ResponseType.ACCEPT:
|
||||
self.project.filename = dialog.get_filename()
|
||||
self.__save_project()
|
||||
|
||||
dialog.destroy()
|
||||
dialog = self.__file_open_dialog_new(_("Choose a new file to save the project"))
|
||||
dialog.save(self, None, self.__save_dialog_callback)
|
||||
|
||||
def _on_add_ui_activate(self, action, data):
|
||||
if self.project is None:
|
||||
@ -785,19 +805,23 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
def __remove_object_with_confirmation(self, obj):
|
||||
dialog = Gtk.MessageDialog(
|
||||
transient_for=self,
|
||||
flags=0,
|
||||
modal=True,
|
||||
message_type=Gtk.MessageType.QUESTION,
|
||||
buttons=Gtk.ButtonsType.YES_NO,
|
||||
text=_("Do you really want to remove {name}?").format(name=obj.get_display_name()),
|
||||
)
|
||||
|
||||
if dialog.run() == Gtk.ResponseType.YES:
|
||||
if type(obj) == CmbUI:
|
||||
self.project.remove_ui(obj)
|
||||
elif type(obj) == CmbCSS:
|
||||
self.project.remove_css(obj)
|
||||
def on_dialog_response(dialog, response):
|
||||
if response == Gtk.ResponseType.YES:
|
||||
if type(obj) == CmbUI:
|
||||
self.project.remove_ui(obj)
|
||||
elif type(obj) == CmbCSS:
|
||||
self.project.remove_css(obj)
|
||||
|
||||
dialog.destroy()
|
||||
dialog.destroy()
|
||||
|
||||
dialog.connect("response", on_dialog_response)
|
||||
dialog.present()
|
||||
|
||||
def _on_copy_activate(self, action, data):
|
||||
if self.project:
|
||||
@ -891,30 +915,43 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
if self.project is None:
|
||||
return
|
||||
|
||||
def dialog_callback(dialog, res):
|
||||
try:
|
||||
for file in dialog.open_multiple_finish(res):
|
||||
self.import_file(file.get_path())
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
dialog = self.__file_open_dialog_new(
|
||||
_("Choose file to import"), filter_obj=self.import_filter, select_multiple=True, accept_label=_("Import")
|
||||
_("Choose file to import"), filter_obj=self.import_filter, accept_label=_("Import")
|
||||
)
|
||||
dialog.open_multiple(self, None, dialog_callback)
|
||||
|
||||
if dialog.run() == Gtk.ResponseType.ACCEPT:
|
||||
filenames = dialog.get_filenames()
|
||||
dialog.destroy()
|
||||
def __save(self):
|
||||
if self.project.save():
|
||||
self.__last_saved_index = self.project.history_index
|
||||
self.__update_action_save()
|
||||
self.emit("project-saved", self.project)
|
||||
|
||||
for filename in filenames:
|
||||
self.import_file(filename)
|
||||
else:
|
||||
dialog.destroy()
|
||||
def save_project(self):
|
||||
if self.project is None:
|
||||
return False
|
||||
|
||||
def __save_project(self):
|
||||
if self.project is not None:
|
||||
if self.project.save():
|
||||
self.__last_saved_index = self.project.history_index
|
||||
self.__update_action_save()
|
||||
if self.project.filename is None:
|
||||
dialog = self.__file_open_dialog_new(_("Choose a file to save the project"))
|
||||
dialog.save(self, None, self.__save_dialog_callback)
|
||||
return True
|
||||
|
||||
# Save project and update last saved index
|
||||
self.__save()
|
||||
|
||||
return False
|
||||
|
||||
def _on_export_activate(self, action, data):
|
||||
if self.project is None:
|
||||
return
|
||||
|
||||
self.__save_project()
|
||||
self.save_project()
|
||||
|
||||
n = self.project.export()
|
||||
|
||||
@ -931,7 +968,7 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
fd, filename = tempfile.mkstemp(".db", "cmb")
|
||||
|
||||
self.project.db_move_to_fs(filename)
|
||||
Gtk.show_uri_on_window(self, f"file://{filename}", Gdk.CURRENT_TIME)
|
||||
Gtk.show_uri(self, f"file://{filename}", Gdk.CURRENT_TIME)
|
||||
|
||||
def _on_about_activate(self, action, data):
|
||||
self.about_dialog.present()
|
||||
@ -940,13 +977,13 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.__set_page("donate")
|
||||
|
||||
def _on_liberapay_activate(self, action, data):
|
||||
Gtk.show_uri_on_window(self, "https://liberapay.com/xjuan/donate", Gdk.CURRENT_TIME)
|
||||
Gtk.show_uri(self, "https://liberapay.com/xjuan/donate", Gdk.CURRENT_TIME)
|
||||
|
||||
def _on_patreon_activate(self, action, data):
|
||||
Gtk.show_uri_on_window(self, "https://www.patreon.com/cambalache", Gdk.CURRENT_TIME)
|
||||
Gtk.show_uri(self, "https://www.patreon.com/cambalache", Gdk.CURRENT_TIME)
|
||||
|
||||
def _on_contact_activate(self, action, data):
|
||||
Gtk.show_uri_on_window(self, "https://matrix.to/#/#cambalache:gnome.org", Gdk.CURRENT_TIME)
|
||||
Gtk.show_uri(self, "https://matrix.to/#/#cambalache:gnome.org", Gdk.CURRENT_TIME)
|
||||
|
||||
def _on_add_placeholder_activate(self, action, data):
|
||||
self.view.add_placeholder()
|
||||
@ -974,18 +1011,18 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
|
||||
def __on_project_notify(self, obj, pspec):
|
||||
if self.project:
|
||||
self.turor_waiting_for_user_action = False
|
||||
self.tutor_waiting_for_user_action = False
|
||||
self.tutor.play()
|
||||
self.disconnect_by_func(self.__on_project_notify)
|
||||
|
||||
def __on_object_added(self, project, obj, data):
|
||||
if obj.info.is_a(data):
|
||||
project.disconnect_by_func(self.__on_object_added)
|
||||
self.turor_waiting_for_user_action = False
|
||||
self.tutor_waiting_for_user_action = False
|
||||
self.tutor.play()
|
||||
|
||||
def __on_ui_added(self, project, ui):
|
||||
self.turor_waiting_for_user_action = False
|
||||
self.tutor_waiting_for_user_action = False
|
||||
project.disconnect_by_func(self.__on_ui_added)
|
||||
self.tutor.play()
|
||||
|
||||
@ -1001,14 +1038,12 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.project.connect("object-added", self.__on_object_added, "GtkGrid")
|
||||
elif node == "add-button":
|
||||
self.project.connect("object-added", self.__on_object_added, "GtkButton")
|
||||
elif node == "main-menu":
|
||||
self.main_menu.props.modal = False
|
||||
elif node in ["menu_button", "main-menu"]:
|
||||
self.menu_button.popup()
|
||||
elif node == "show-type-popover":
|
||||
widget.props.popover.modal = False
|
||||
widget.props.popover.popup()
|
||||
elif node == "show-type-popover-gtk":
|
||||
child = widget.get_children()[0]
|
||||
child.props.popover.props.modal = False
|
||||
child = utils.widget_get_children(widget)[0]
|
||||
child.props.popover.popup()
|
||||
|
||||
def __on_tutor_hide_node(self, tutor, node, widget):
|
||||
@ -1017,28 +1052,23 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.__clear_tutor()
|
||||
elif node == "add-project":
|
||||
if self.__project is None:
|
||||
self.turor_waiting_for_user_action = True
|
||||
self.tutor_waiting_for_user_action = True
|
||||
self.tutor.pause()
|
||||
elif node in ["add-ui", "add-window", "add-grid", "add-button"]:
|
||||
self.turor_waiting_for_user_action = True
|
||||
self.tutor_waiting_for_user_action = True
|
||||
self.tutor.pause()
|
||||
elif node == "main-menu":
|
||||
self.export_all.get_style_context().remove_class("cmb-tutor-highlight")
|
||||
elif node == "donate":
|
||||
self.main_menu.props.modal = True
|
||||
self.main_menu.popdown()
|
||||
elif node in ["menu_button", "donate"]:
|
||||
self.menu_button.popdown()
|
||||
elif node == "show-type-popover":
|
||||
widget.props.popover.modal = True
|
||||
widget.props.popover.popdown()
|
||||
elif node == "show-type-popover-gtk":
|
||||
child = widget.get_children()[0]
|
||||
child.props.popover.props.modal = True
|
||||
child = utils.widget_get_children(widget)[0]
|
||||
child.props.popover.popdown()
|
||||
|
||||
self.__update_actions()
|
||||
|
||||
def _on_intro_activate(self, action, data):
|
||||
if self.turor_waiting_for_user_action:
|
||||
if self.tutor_waiting_for_user_action:
|
||||
return
|
||||
|
||||
if self.tutor:
|
||||
@ -1058,28 +1088,69 @@ class CmbWindow(Gtk.ApplicationWindow):
|
||||
self.tutor.connect("hide-node", self.__on_tutor_hide_node)
|
||||
self.tutor.play()
|
||||
|
||||
def _on_workspace_restart_activate(self, action, data):
|
||||
self.view.restart_workspace()
|
||||
|
||||
def _on_workspace_theme_activate(self, action, data):
|
||||
self.view.props.gtk_theme = data.get_string()
|
||||
action.set_state(data)
|
||||
|
||||
def _on_inspect_activate(self, action, data):
|
||||
self.view.inspect()
|
||||
|
||||
def _on_open_recent_activate(self, action, data):
|
||||
self.emit("open-project", data.get_string(), None, None)
|
||||
|
||||
def __update_recent_menu(self):
|
||||
manager = Gtk.RecentManager.get_default()
|
||||
|
||||
mime_types = [
|
||||
"application/x-cambalache-project"
|
||||
]
|
||||
|
||||
for recent in manager.get_items():
|
||||
if recent.get_mime_type() not in mime_types:
|
||||
continue
|
||||
|
||||
filename, host = GLib.filename_from_uri(recent.get_uri())
|
||||
if not os.path.exists(filename):
|
||||
continue
|
||||
|
||||
item = Gio.MenuItem()
|
||||
item.set_label(recent.get_display_name())
|
||||
item.set_action_and_target_value("win.open_recent", GLib.Variant("s", filename))
|
||||
self.recent_menu.append_item(item)
|
||||
|
||||
def __load_window_state(self):
|
||||
state = self.window_settings.get_uint("state")
|
||||
|
||||
if state & Gdk.WindowState.MAXIMIZED:
|
||||
if state & self.MAXIMIZED:
|
||||
self.maximize()
|
||||
elif state & self.FULLSCREEN:
|
||||
self.fullscreen()
|
||||
else:
|
||||
size = self.window_settings.get_value("size").unpack()
|
||||
self.set_default_size(*size)
|
||||
|
||||
def __save_window_state(self):
|
||||
state = self.props.window.get_state()
|
||||
fullscreen = self.props.fullscreened
|
||||
maximized = self.props.maximized
|
||||
state = 0
|
||||
|
||||
fullscreen = state & Gdk.WindowState.FULLSCREEN
|
||||
maximized = state & Gdk.WindowState.MAXIMIZED
|
||||
if fullscreen:
|
||||
state = state | self.FULLSCREEN
|
||||
|
||||
if maximized:
|
||||
state = state | self.MAXIMIZED
|
||||
|
||||
# Maintain compatibility with Gtk 3 state
|
||||
self.window_settings.set_uint("state", state)
|
||||
|
||||
size = (0, 0) if fullscreen or maximized else self.get_size()
|
||||
size = (0, 0) if fullscreen or maximized else (self.props.default_width, self.props.default_height)
|
||||
|
||||
self.window_settings.set_value("size", GLib.Variant("(ii)", size))
|
||||
|
||||
def do_delete_event(self, event):
|
||||
def do_close_request(self):
|
||||
self.__save_window_state()
|
||||
return False
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
#
|
||||
# CmbContextMenu - Cambalache UI Editor
|
||||
#
|
||||
# Copyright (C) 2021 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2024 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
import os
|
||||
|
||||
from gi.repository import GObject, GLib, Gdk, Gtk
|
||||
from gi.repository import GObject, GLib, Gio, Gdk, Gtk
|
||||
from cambalache import _
|
||||
|
||||
|
||||
@ -31,23 +31,17 @@ from cambalache import _
|
||||
class CmbContextMenu(Gtk.PopoverMenu):
|
||||
__gtype_name__ = "CmbContextMenu"
|
||||
|
||||
gtk_theme = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
target_tk = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
main_box = Gtk.Template.Child()
|
||||
separator = Gtk.Template.Child()
|
||||
css_theme = Gtk.Template.Child()
|
||||
css_theme_box = Gtk.Template.Child()
|
||||
main_section = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.theme_submenu = None
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.connect("notify::target-tk", lambda o, p: self.__populate_css_theme_box())
|
||||
|
||||
def __on_css_theme_button_toggled(self, button, data):
|
||||
if button.props.active:
|
||||
self.gtk_theme = data
|
||||
|
||||
def __populate_css_theme_box(self):
|
||||
gtk_path = "gtk-3.0"
|
||||
|
||||
@ -56,9 +50,17 @@ class CmbContextMenu(Gtk.PopoverMenu):
|
||||
|
||||
if self.target_tk == "gtk-4.0":
|
||||
gtk_path = "gtk-4.0"
|
||||
# FIXME: whats the real default theme for gtk4?
|
||||
themes = ["Default"]
|
||||
else:
|
||||
themes = ["Adwaita", "HighContrast", "HighContrastInverse"]
|
||||
|
||||
for child in self.css_theme_box.get_children():
|
||||
self.css_theme_box.remove(child)
|
||||
if self.theme_submenu is None:
|
||||
self.theme_submenu = Gio.Menu()
|
||||
self.main_section.prepend_submenu(_("CSS theme"), self.theme_submenu)
|
||||
|
||||
# Remove all items from theme submenu
|
||||
self.theme_submenu.remove_all()
|
||||
|
||||
dirs = []
|
||||
|
||||
@ -71,9 +73,6 @@ class CmbContextMenu(Gtk.PopoverMenu):
|
||||
# Append ~/.themes
|
||||
dirs.append(os.path.join(GLib.get_home_dir(), ".themes"))
|
||||
|
||||
# Default themes
|
||||
themes = ["Adwaita", "HighContrast", "HighContrastInverse"]
|
||||
|
||||
for path in dirs:
|
||||
if not os.path.isdir(path):
|
||||
continue
|
||||
@ -86,23 +85,16 @@ class CmbContextMenu(Gtk.PopoverMenu):
|
||||
# Dedup and sort
|
||||
themes = list(dict.fromkeys(themes))
|
||||
|
||||
# Add back item
|
||||
button = Gtk.ModelButton(text=_("CSS themes"), menu_name="main", inverted=True, centered=True, visible=True)
|
||||
self.css_theme_box.add(button)
|
||||
|
||||
group = None
|
||||
for theme in sorted(themes):
|
||||
button = Gtk.RadioButton(label=theme, group=group, active=self.gtk_theme == theme, visible=True)
|
||||
if group is None:
|
||||
group = button
|
||||
|
||||
button.connect("toggled", self.__on_css_theme_button_toggled, theme)
|
||||
self.css_theme_box.add(button)
|
||||
|
||||
self.separator.props.visible = self.css_theme.props.visible = len(themes) > 0
|
||||
item = Gio.MenuItem()
|
||||
item.set_label(theme)
|
||||
item.set_action_and_target_value("win.workspace_theme", GLib.Variant("s", theme))
|
||||
self.theme_submenu.append_item(item)
|
||||
|
||||
def popup_at(self, x, y):
|
||||
r = Gdk.Rectangle()
|
||||
r.x, r.y, r.width, r.height = (x, y, 10, 10)
|
||||
r.x, r.y = (x, y)
|
||||
r.width = r.height = 0
|
||||
self.set_pointing_to(r)
|
||||
self.popup()
|
||||
|
@ -1,182 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<menu id="menu_model">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="action">win.cut</attribute>
|
||||
<attribute name="label" translatable="1">Cut</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.copy</attribute>
|
||||
<attribute name="label" translatable="1">Copy</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.paste</attribute>
|
||||
<attribute name="label" translatable="1">Paste</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.delete</attribute>
|
||||
<attribute name="label" translatable="1">Delete</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="action">win.add_object</attribute>
|
||||
<attribute name="label" translatable="1">Add object here</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.add_object_toplevel</attribute>
|
||||
<attribute name="label" translatable="1">Add object as toplevel</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.clear</attribute>
|
||||
<attribute name="label" translatable="1">Clear Properties</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.documentation</attribute>
|
||||
<attribute name="label" translatable="1">Read Documentation</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section id="main_section"/>
|
||||
</menu>
|
||||
<template class="CmbContextMenu" parent="GtkPopoverMenu">
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="main_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">4</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.cut</property>
|
||||
<property name="text" translatable="yes">Cut</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.copy</property>
|
||||
<property name="text" translatable="yes">Copy</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.paste</property>
|
||||
<property name="text" translatable="yes">Paste</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.delete</property>
|
||||
<property name="text" translatable="yes">Delete</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.add_object</property>
|
||||
<property name="text" translatable="yes">Add object here</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.add_object_toplevel</property>
|
||||
<property name="text" translatable="yes">Add object as toplevel</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.clear</property>
|
||||
<property name="text" translatable="yes">Clear Properties</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.documentation</property>
|
||||
<property name="text" translatable="yes">Read Documentation</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="separator">
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton" id="css_theme">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="text" translatable="yes">CSS theme</property>
|
||||
<property name="menu-name">css-theme</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="submenu">main</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="css_theme_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">4</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="submenu">css-theme</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<property name="menu-model">menu_model</property>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
from gi.repository import GObject, Gtk
|
||||
from .cmb_css import CmbCSS
|
||||
from . import utils
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_css_editor.ui")
|
||||
@ -121,8 +122,7 @@ class CmbCSSEditor(Gtk.Grid):
|
||||
|
||||
def __update_provider_for(self):
|
||||
# Remove all css_ui check buttons
|
||||
ui_box_children = self.ui_box.get_children()
|
||||
for child in ui_box_children:
|
||||
for child in utils.widget_get_children(self.ui_box):
|
||||
self.ui_box.remove(child)
|
||||
|
||||
if self._object is None:
|
||||
@ -137,7 +137,7 @@ class CmbCSSEditor(Gtk.Grid):
|
||||
label=ui.get_display_name(), active=ui.ui_id in provider_for, halign=Gtk.Align.START, visible=True
|
||||
)
|
||||
check.connect("toggled", self.__on_check_button_toggled, ui)
|
||||
self.ui_box.add(check)
|
||||
self.ui_box.append(check)
|
||||
|
||||
def __on_file_changed(self, obj):
|
||||
self.infobar.set_revealed(True)
|
||||
|
@ -1,89 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gladecambalache" version="0.0"/>
|
||||
<!-- n-columns=2 n-rows=6 -->
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbCSSEditor" parent="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<property name="column-spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Filename:</property>
|
||||
<property name="label" translatable="1">Filename:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Priority:</property>
|
||||
<property name="label" translatable="1">Priority:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="tooltip-text" translatable="yes">This provider will be used in all UI.</property>
|
||||
<property name="tooltip-text" translatable="1">This provider will be used in all UI.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Global:</property>
|
||||
<property name="label" translatable="1">Global:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="filename">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="placeholder-text" translatable="yes"><file name relative to project></property>
|
||||
<property name="placeholder-text" translatable="1"><file name relative to project></property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="priority">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">start</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="is_global">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">start</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="ui_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
@ -94,189 +79,116 @@
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="tooltip-text" translatable="yes">List of UI where this provider will be used</property>
|
||||
<property name="tooltip-text" translatable="1">List of UI where this provider will be used</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Provider for:</property>
|
||||
<property name="label" translatable="1">Provider for:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Remove CSS file from project</property>
|
||||
<property name="focusable">1</property>
|
||||
<!-- <property name="receives-default">1</property> -->
|
||||
<!-- <property name="tooltip-text" translatable="1">Remove CSS file from project</property> -->
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">end</property>
|
||||
<signal name="clicked" handler="on_remove_button_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">app-remove-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes"><small>Note: CSS files need to be loaded at runtime</small></property>
|
||||
<property name="use-markup">True</property>
|
||||
<property name="label" translatable="1"><small>Note: CSS files need to be loaded at runtime</small></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="save_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Save CSS file</property>
|
||||
<property name="sensitive">0</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="tooltip-text" translatable="1">Save CSS file</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">end</property>
|
||||
<signal name="clicked" handler="on_save_button_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">document-save-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">5</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">5</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label-xalign">0</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkInfoBar" id="infobar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="message-type">warning</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<property name="revealed">False</property>
|
||||
<property name="show-close-button">1</property>
|
||||
<property name="revealed">0</property>
|
||||
<signal name="response" handler="on_infobar_response" swapped="no"/>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<child type="action">
|
||||
<object class="GtkButton" id="reload_button">
|
||||
<property name="label" translatable="yes">Reload</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="1">Reload</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="content_area">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="spacing">16</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">The file changed on disk.</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="label" translatable="1">The file changed on disk.</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-5">reload_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="CmbSourceView" id="view">
|
||||
<property name="visible">True</property>
|
||||
@ -285,23 +197,18 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# CmbDB - Cambalache DataBase
|
||||
#
|
||||
# Copyright (C) 2021-2023 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2024 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -28,7 +28,7 @@ import ast
|
||||
|
||||
from lxml import etree
|
||||
from lxml.builder import E
|
||||
from gi.repository import Gio, GObject, Gtk
|
||||
from gi.repository import GLib, Gio, GObject
|
||||
from cambalache import config, getLogger, _
|
||||
from . import cmb_db_migration, utils
|
||||
from .constants import EXTERNAL_TYPE, GMENU_TYPE, GMENU_SECTION_TYPE, GMENU_SUBMENU_TYPE, GMENU_ITEM_TYPE
|
||||
@ -618,8 +618,8 @@ class CmbDB(GObject.GObject):
|
||||
|
||||
return f"\t({r})"
|
||||
|
||||
def _dump_table(c, table):
|
||||
c.execute(f"SELECT * FROM {table};")
|
||||
def _dump_query(c, query):
|
||||
c.execute(query)
|
||||
row = c.fetchone()
|
||||
|
||||
if row is None:
|
||||
@ -635,20 +635,27 @@ class CmbDB(GObject.GObject):
|
||||
|
||||
return f"\n{retval}\n "
|
||||
|
||||
def append_data(project, name, data):
|
||||
if data is None:
|
||||
return
|
||||
|
||||
element = etree.Element(name)
|
||||
element.text = data
|
||||
project.append(element)
|
||||
|
||||
self.conn.commit()
|
||||
c = self.conn.cursor()
|
||||
|
||||
project = E("cambalache-project", version=config.FILE_FORMAT_VERSION, target_tk=self.target_tk)
|
||||
|
||||
for table in self.__tables:
|
||||
data = _dump_table(c, table)
|
||||
data = _dump_query(c, f"SELECT * FROM {table};")
|
||||
append_data(project, table, data)
|
||||
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
element = etree.Element(table)
|
||||
element.text = data
|
||||
project.append(element)
|
||||
# DUMP custom properties and signals
|
||||
for table in ["property", "signal"]:
|
||||
data = _dump_query(c, f"SELECT {table}.* FROM {table},type WHERE {table}.owner_id == type.type_id AND type.library_id IS NULL;")
|
||||
append_data(project, table, data)
|
||||
|
||||
# Dump xml to file
|
||||
with open(filename, "wb") as fd:
|
||||
@ -1523,12 +1530,11 @@ class CmbDB(GObject.GObject):
|
||||
if column is not None:
|
||||
c.execute(f"UPDATE ui SET {column}=? WHERE ui_id=?", (value, ui_id))
|
||||
else:
|
||||
print(child)
|
||||
custom_fragments.append(child)
|
||||
# self.__unknown_tag(child, None, child.tag)
|
||||
|
||||
while Gtk.events_pending():
|
||||
Gtk.main_iteration_do(False)
|
||||
main_loop = GLib.MainContext.default()
|
||||
while main_loop.pending():
|
||||
main_loop.iteration(False)
|
||||
|
||||
# Fix object references!
|
||||
self.__fix_object_references(ui_id)
|
||||
|
@ -1,31 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gladecambalache" version="0.0"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbFragmentEditor" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Extra fragments:</property>
|
||||
<property name="label" translatable="1">Extra fragments:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="focusable">1</property>
|
||||
<child>
|
||||
<object class="CmbSourceView" id="view">
|
||||
<property name="visible">True</property>
|
||||
@ -34,11 +22,6 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -71,7 +71,8 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
else:
|
||||
self.__data.parent.remove_data(self.__data)
|
||||
|
||||
@Gtk.Template.Callback("on_remove_size_allocate")
|
||||
# FIXME: GTK4
|
||||
#@Gtk.Template.Callback("on_remove_size_allocate")
|
||||
def __on_remove_size_allocate(self, button, alloc):
|
||||
info = self.data.info if self.data else self.info
|
||||
|
||||
@ -182,9 +183,9 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
child_info = info.children[child]
|
||||
button = Gtk.ModelButton(label=_("Add {key}").format(key=child_info.key), visible=True)
|
||||
button.connect("clicked", self.__on_child_button_clicked, child_info)
|
||||
box.add(button)
|
||||
box.append(button)
|
||||
|
||||
popover.add(box)
|
||||
popover.set_child(box)
|
||||
|
||||
return popover
|
||||
|
||||
@ -236,7 +237,7 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
|
||||
nchildren = len(info.children)
|
||||
|
||||
self.remove_button.set_tooltip_text(_("Remove {key}").format(key=info.key))
|
||||
self.remove_button.props.tooltip_text = _("Remove {key}").format(key=info.key)
|
||||
|
||||
# Add a menu if there is more than one child type
|
||||
if nchildren > 1:
|
||||
@ -244,7 +245,7 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
self.add_child.set_visible(True)
|
||||
elif nchildren:
|
||||
key = list(info.children.keys())[0]
|
||||
self.add_only_child.set_tooltip_text(_("Add {key}").format(key=key))
|
||||
self.add_only_child.props.tooltip_text = _("Add {key}").format(key=key)
|
||||
self.add_only_child.set_visible(True)
|
||||
|
||||
# Item name
|
||||
@ -267,7 +268,7 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
|
||||
self.top_box.add(editor)
|
||||
self.top_box.append(editor)
|
||||
|
||||
nargs = len(info.args)
|
||||
|
||||
@ -287,7 +288,7 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
# Special case items with one argument and no value (like styles)
|
||||
if nargs == 1 and not info.type_id:
|
||||
self.label.props.label = f"{info.key} {arg_info.key}"
|
||||
self.top_box.add(editor)
|
||||
self.top_box.append(editor)
|
||||
else:
|
||||
label = Gtk.Label(visible=True, label=arg_info.key, xalign=1)
|
||||
self.__add(editor, label)
|
||||
|
@ -1,74 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<!-- Created with Cambalache 0.11.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbObjectDataEditor" parent="GtkBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="top_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="no-show-all">True</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add_child">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="relief">none</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_only_child">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_add_only_child_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_remove_clicked" swapped="no"/>
|
||||
<signal name="size-allocate" handler="on_remove_size_allocate" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">user-trash-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
@ -76,36 +45,15 @@
|
||||
<class name="hidden"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
<object class="GtkLabel" id="label"/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<!-- n-columns=2 n-rows=1 -->
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<property name="column-spacing">4</property>
|
||||
<child>
|
||||
@ -115,11 +63,6 @@
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -29,9 +29,10 @@ from .control import CmbEntry, CmbChildTypeComboBox, cmb_create_editor
|
||||
from .cmb_property_label import CmbPropertyLabel
|
||||
from cambalache import _
|
||||
from .constants import EXTERNAL_TYPE
|
||||
from . import utils
|
||||
|
||||
|
||||
class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
class CmbObjectEditor(Gtk.Box):
|
||||
__gtype_name__ = "CmbObjectEditor"
|
||||
|
||||
layout = GObject.Property(type=bool, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, default=False)
|
||||
@ -43,10 +44,7 @@ class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, visible=True)
|
||||
viewport = Gtk.Viewport(visible=True, shadow_type=Gtk.ShadowType.NONE)
|
||||
viewport.add(self.box)
|
||||
self.add(viewport)
|
||||
self.props.orientation = Gtk.Orientation.VERTICAL
|
||||
|
||||
def __create_id_editor(self):
|
||||
grid = Gtk.Grid(hexpand=True, row_spacing=4, column_spacing=4)
|
||||
@ -97,12 +95,12 @@ class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
box = Gtk.FlowBox(visible=True, hexpand=True, selection_mode=Gtk.SelectionMode.NONE)
|
||||
|
||||
label = Gtk.Label(label=_("Add"), xalign=0, visible=True)
|
||||
box.add(label)
|
||||
box.append(label)
|
||||
|
||||
for type_id in info.child_type_shortcuts:
|
||||
button = Gtk.Button(label=type_id, visible=True)
|
||||
button.connect("clicked", self.__on_shortcut_button_clicked, type_id)
|
||||
box.add(button)
|
||||
box.append(button)
|
||||
|
||||
return box
|
||||
|
||||
@ -127,7 +125,7 @@ class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
def __create_child_type_editor(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
||||
|
||||
box.add(Gtk.Label(label=_("Child Type"), width_chars=8))
|
||||
box.append(Gtk.Label(label=_("Child Type"), width_chars=8))
|
||||
|
||||
combo = CmbChildTypeComboBox(object=self.__object)
|
||||
|
||||
@ -138,12 +136,12 @@ class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
"cmb-value",
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
box.pack_start(combo, True, True, 0)
|
||||
box.append(combo)
|
||||
return box
|
||||
|
||||
def __update_view(self):
|
||||
for child in self.box.get_children():
|
||||
self.box.remove(child)
|
||||
for child in utils.widget_get_children(self):
|
||||
self.remove(child)
|
||||
|
||||
if self.__object is None:
|
||||
return
|
||||
@ -158,10 +156,10 @@ class CmbObjectEditor(Gtk.ScrolledWindow):
|
||||
|
||||
# Child Type input
|
||||
if parent.info.has_child_types():
|
||||
self.box.add(self.__create_child_type_editor())
|
||||
self.append(self.__create_child_type_editor())
|
||||
else:
|
||||
# ID
|
||||
self.box.add(self.__create_id_editor())
|
||||
self.append(self.__create_id_editor())
|
||||
|
||||
if obj.type_id == EXTERNAL_TYPE:
|
||||
label = Gtk.Label(
|
||||
@ -174,8 +172,8 @@ It has to be exposed by your application with GtkBuilder expose_object method."
|
||||
xalign=0,
|
||||
wrap=True,
|
||||
)
|
||||
self.box.add(label)
|
||||
self.show_all()
|
||||
self.append(label)
|
||||
self.show()
|
||||
return
|
||||
|
||||
info = parent.info if self.layout and parent else obj.info
|
||||
@ -261,11 +259,11 @@ It has to be exposed by your application with GtkBuilder expose_object method."
|
||||
expander = Gtk.Expander(label=f"<b>{owner_id}</b>", use_markup=True, expanded=True)
|
||||
revealer = Gtk.Revealer(reveal_child=True)
|
||||
expander.connect("notify::expanded", self.__on_expander_expanded, revealer)
|
||||
revealer.add(grid)
|
||||
self.box.add(expander)
|
||||
self.box.add(revealer)
|
||||
revealer.set_child(grid)
|
||||
self.append(expander)
|
||||
self.append(revealer)
|
||||
|
||||
self.show_all()
|
||||
self.show()
|
||||
|
||||
def __on_object_ui_notify(self, obj, pspec):
|
||||
if pspec.name == "template-id" and self.__template_switch:
|
||||
|
@ -78,7 +78,6 @@ class CmbProject(Gtk.TreeStore):
|
||||
"type-info-added": (GObject.SignalFlags.RUN_FIRST, None, (CmbTypeInfo,)),
|
||||
"type-info-removed": (GObject.SignalFlags.RUN_FIRST, None, (CmbTypeInfo,)),
|
||||
"type-info-changed": (GObject.SignalFlags.RUN_FIRST, None, (CmbTypeInfo,)),
|
||||
"filename-required": (GObject.SignalFlags.RUN_FIRST, str, ()),
|
||||
}
|
||||
|
||||
target_tk = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT)
|
||||
@ -282,9 +281,6 @@ class CmbProject(Gtk.TreeStore):
|
||||
self.__filename = value
|
||||
|
||||
def save(self):
|
||||
if self.filename is None:
|
||||
self.filename = self.emit("filename-required")
|
||||
|
||||
if self.filename:
|
||||
self.db.save(self.filename)
|
||||
return True
|
||||
@ -378,6 +374,9 @@ class CmbProject(Gtk.TreeStore):
|
||||
return (ui, msgs, detail_msg)
|
||||
|
||||
def __export(self, ui_id, filename, dirname=None):
|
||||
if filename is None:
|
||||
return
|
||||
|
||||
if not os.path.isabs(filename):
|
||||
if dirname is None:
|
||||
dirname = os.path.dirname(self.filename)
|
||||
@ -1178,14 +1177,15 @@ class CmbProject(Gtk.TreeStore):
|
||||
self.__object_update_row(ui.ui_id, template_id)
|
||||
|
||||
def _ui_changed(self, ui, field):
|
||||
iter = self.get_iter_from_object(ui)
|
||||
|
||||
if field == "template-id":
|
||||
self.__update_template_type_info(ui)
|
||||
|
||||
iter = self.get_iter_from_object(ui)
|
||||
if iter is None:
|
||||
return
|
||||
|
||||
path = self.get_path(iter)
|
||||
self.row_changed(path, iter)
|
||||
|
||||
self.emit("ui-changed", ui, field)
|
||||
|
||||
def _ui_library_changed(self, ui, lib):
|
||||
|
@ -43,8 +43,6 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.props.relief = Gtk.ReliefStyle.NONE
|
||||
|
||||
if not self.prop and not self.layout_prop:
|
||||
raise Exception("CmbPropertyLabel requires prop or layout_prop to be set")
|
||||
return
|
||||
@ -54,8 +52,8 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
|
||||
# Update label status
|
||||
if self.prop:
|
||||
self.bind_icon = Gtk.Image(icon_size=Gtk.IconSize.MENU, visible=True)
|
||||
box.add(self.bind_icon)
|
||||
self.bind_icon = Gtk.Image(icon_size=Gtk.IconSize.NORMAL, visible=True)
|
||||
box.append(self.bind_icon)
|
||||
|
||||
self.label.props.label = self.prop.property_id
|
||||
|
||||
@ -71,24 +69,22 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
self.__update_layout_property_label()
|
||||
self.layout_prop.connect("notify::value", lambda o, p: self.__update_layout_property_label())
|
||||
|
||||
box.add(self.label)
|
||||
self.add(box)
|
||||
box.append(self.label)
|
||||
self.set_child(box)
|
||||
|
||||
def __update_label(self, prop):
|
||||
style = self.get_style_context()
|
||||
|
||||
if prop.value != prop.info.default_value:
|
||||
style.add_class("modified")
|
||||
self.add_css_class("modified")
|
||||
else:
|
||||
style.remove_class("modified")
|
||||
self.remove_css_class("modified")
|
||||
|
||||
msg = prop.version_warning
|
||||
self.set_tooltip_text(msg)
|
||||
|
||||
if msg:
|
||||
style.add_class("warning")
|
||||
self.add_css_class("warning")
|
||||
else:
|
||||
style.remove_class("warning")
|
||||
self.remove_css_class("warning")
|
||||
|
||||
def __update_layout_property_label(self):
|
||||
self.__update_label(self.layout_prop)
|
||||
@ -101,10 +97,10 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
|
||||
if self.prop.bind_property_id:
|
||||
self.bind_icon.props.icon_name = "binded-symbolic"
|
||||
self.get_style_context().remove_class("hidden")
|
||||
self.remove_css_class("hidden")
|
||||
else:
|
||||
self.bind_icon.props.icon_name = "bind-symbolic"
|
||||
self.get_style_context().add_class("hidden")
|
||||
self.add_css_class("hidden")
|
||||
|
||||
def __on_object_editor_notify(self, object_editor, pspec, property_editor):
|
||||
object_id = object_editor.cmb_value
|
||||
@ -129,9 +125,10 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
popover.popdown()
|
||||
|
||||
def __on_bind_button_clicked(self, button):
|
||||
popover = Gtk.Popover(relative_to=button, position=Gtk.PositionType.LEFT)
|
||||
popover = Gtk.Popover(position=Gtk.PositionType.LEFT)
|
||||
popover.set_parent(self)
|
||||
|
||||
grid = Gtk.Grid(hexpand=True, row_spacing=4, column_spacing=4, border_width=4, visible=True)
|
||||
grid = Gtk.Grid(hexpand=True, row_spacing=4, column_spacing=4, visible=True)
|
||||
|
||||
grid.attach(Gtk.Label(label="<b>Property Binding</b>", use_markup=True, visible=True, xalign=0), 0, 0, 2, 1)
|
||||
|
||||
@ -177,7 +174,7 @@ class CmbPropertyLabel(Gtk.Button):
|
||||
grid.attach(clear, 0, i, 2, 1)
|
||||
object_editor.grab_focus()
|
||||
|
||||
popover.add(grid)
|
||||
popover.set_child(grid)
|
||||
popover.popup()
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkEntryCompletion" id="handler_entrycompletion">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
@ -12,42 +11,28 @@
|
||||
</object>
|
||||
<object class="GtkTreeStore" id="treestore">
|
||||
<columns>
|
||||
<!-- column-name signal -->
|
||||
<column type="GObject"/>
|
||||
<!-- column-name owner_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name signal_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name detail -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name handler -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name user_data -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name swap -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name after -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name info -->
|
||||
<column type="GObject"/>
|
||||
<!-- column-name version_warning -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<template class="CmbSignalEditor" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkTreeView" id="treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="model">treestore</property>
|
||||
<property name="tooltip-column">9</property>
|
||||
<child internal-child="selection">
|
||||
@ -55,9 +40,9 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="signal_id_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="min-width">64</property>
|
||||
<property name="title" translatable="yes">Signal</property>
|
||||
<property name="title" translatable="1">Signal</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="signal_id">
|
||||
<signal name="edited" handler="on_detail_edited" swapped="no"/>
|
||||
@ -70,13 +55,13 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="handler_column">
|
||||
<property name="resizable">True</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="min-width">64</property>
|
||||
<property name="title" translatable="yes">Handler</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="title" translatable="1">Handler</property>
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="handler">
|
||||
<property name="editable">True</property>
|
||||
<property name="editable">1</property>
|
||||
<property name="placeholder-text"><Enter callback></property>
|
||||
<signal name="edited" handler="on_handler_edited" swapped="no"/>
|
||||
</object>
|
||||
@ -88,10 +73,10 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="user_data_column">
|
||||
<property name="title" translatable="yes">Data</property>
|
||||
<property name="title" translatable="1">Data</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="user_data">
|
||||
<property name="editable">True</property>
|
||||
<property name="editable">1</property>
|
||||
<property name="placeholder-text"><object></property>
|
||||
<signal name="edited" handler="on_user_data_edited" swapped="no"/>
|
||||
</object>
|
||||
@ -103,7 +88,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="swap_column">
|
||||
<property name="title" translatable="yes">Swap</property>
|
||||
<property name="title" translatable="1">Swap</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererToggle" id="swap">
|
||||
<signal name="toggled" handler="on_swap_toggled" swapped="no"/>
|
||||
@ -116,7 +101,7 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="after_column">
|
||||
<property name="title" translatable="yes">After</property>
|
||||
<property name="title" translatable="1">After</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererToggle" id="after">
|
||||
<signal name="toggled" handler="on_after_toggled" swapped="no"/>
|
||||
@ -128,13 +113,8 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -40,7 +40,6 @@ class CmbTreeView(Gtk.TreeView):
|
||||
self.__in_selection_change = False
|
||||
self._selection.connect("changed", self.__on_selection_changed)
|
||||
self.set_headers_visible(False)
|
||||
self.__right_click = False
|
||||
|
||||
renderer = Gtk.CellRendererText()
|
||||
column = Gtk.TreeViewColumn("Object(Type)", renderer)
|
||||
@ -50,31 +49,14 @@ class CmbTreeView(Gtk.TreeView):
|
||||
self.connect("notify::model", self.__on_model_notify)
|
||||
self.connect("row-activated", self.__on_row_activated)
|
||||
|
||||
self.menu = CmbContextMenu(relative_to=self)
|
||||
|
||||
self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK)
|
||||
self.connect("button-press-event", self.__on_button_press_event)
|
||||
self.connect("button-release-event", self.__on_button_release_event)
|
||||
gesture = Gtk.GestureClick(button=3)
|
||||
gesture.connect("pressed", self.__on_button_press)
|
||||
self.add_controller(gesture)
|
||||
|
||||
self.set_reorderable(True)
|
||||
|
||||
def __on_button_press_event(self, widget, event):
|
||||
if event.window != self.get_bin_window() or event.button != 3:
|
||||
return False
|
||||
|
||||
self.__right_click = True
|
||||
return True
|
||||
|
||||
def __on_button_release_event(self, widget, event):
|
||||
if event.window != self.get_bin_window() or event.button != 3:
|
||||
return False
|
||||
|
||||
if not self.__right_click:
|
||||
return False
|
||||
|
||||
self.__right_click = False
|
||||
|
||||
retval = self.get_path_at_pos(event.x, event.y)
|
||||
def __on_button_press(self, widget, npress, x, y):
|
||||
retval = self.get_path_at_pos(x, y)
|
||||
|
||||
if retval is None:
|
||||
return False
|
||||
@ -82,7 +64,12 @@ class CmbTreeView(Gtk.TreeView):
|
||||
path, col, xx, yy = retval
|
||||
self.get_selection().select_path(path)
|
||||
|
||||
self.menu.popup_at(event.x, event.y)
|
||||
menu = CmbContextMenu()
|
||||
|
||||
# Use parent instead of self to avoid warning and focus not working properly
|
||||
# (run-dev.py:188589): Gtk-CRITICAL **: 16:45:12.790: gtk_css_node_insert_after: assertion 'previous_sibling == NULL || previous_sibling->parent == parent' failed
|
||||
menu.set_parent(self.props.parent)
|
||||
menu.popup_at(x, y)
|
||||
|
||||
return True
|
||||
|
||||
@ -156,7 +143,7 @@ class CmbTreeView(Gtk.TreeView):
|
||||
project.set_selection([obj])
|
||||
|
||||
def do_query_tooltip(self, x, y, keyboard_mode, tooltip):
|
||||
retval, xx, yy, model, path, iter_ = self.get_tooltip_context(x, y, keyboard_mode)
|
||||
retval, model, path, iter_ = self.get_tooltip_context(x, y, keyboard_mode)
|
||||
|
||||
if not retval:
|
||||
return False
|
||||
|
@ -1,216 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gladecambalache" version="0.0"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="CmbTypeChooserPopover" id="all">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="show-categories">True</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="control">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="category">control</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="display">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="category">display</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="extra">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="uncategorized-only">True</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="layout">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="category">layout</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="model">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="category">model</property>
|
||||
</object>
|
||||
<object class="CmbTypeChooserPopover" id="toplevel">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="category">toplevel</property>
|
||||
</object>
|
||||
<template class="CmbTypeChooser" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="type_chooser_all">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">all</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">edit-find-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="type_chooser_gtk">
|
||||
<object class="GtkBox" id="type_chooser_gtk">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">expand</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">toplevel</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes" comments="Widget group for toplevels/windows">Toplevel</property>
|
||||
<property name="label" translatable="1" comments="Widget group for toplevels/windows">Toplevel</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">layout</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes" comments="Widget group for container widgets liek GtkBox grid">Layout</property>
|
||||
<property name="label" translatable="1" comments="Widget group for container widgets liek GtkBox grid">Layout</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">control</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes" comments="Widget group for control wildget like buttons, entries">Control</property>
|
||||
<property name="label" translatable="1" comments="Widget group for control wildget like buttons, entries">Control</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">display</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes" comments="Widget group for display widgets (label, image)">Display</property>
|
||||
<property name="label" translatable="1" comments="Widget group for display widgets (label, image)">Display</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="focus-on-click">0</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">model</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes" comments="Widget group for model objects (ListStore, TextBuffer)">Model</property>
|
||||
<property name="label" translatable="1" comments="Widget group for model objects (ListStore, TextBuffer)">Model</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="popover">extra</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">pan-down-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="type_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="sensitive">0</property>
|
||||
<property name="halign">start</property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
<attribute name="style" value="italic"></attribute>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -47,8 +47,9 @@ class CmbTypeChooserPopover(Gtk.Popover):
|
||||
|
||||
self._chooser = CmbTypeChooserWidget()
|
||||
self._chooser.connect("type-selected", self.__on_type_selected)
|
||||
self._chooser.show_all()
|
||||
self.add(self._chooser)
|
||||
|
||||
self.set_child(self._chooser)
|
||||
self.set_default_widget(self._chooser)
|
||||
|
||||
for prop in [
|
||||
"project",
|
||||
|
@ -46,7 +46,6 @@ class CmbTypeChooserWidget(Gtk.Box):
|
||||
parent_type_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
derived_type_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
entrycompletion = Gtk.Template.Child()
|
||||
scrolledwindow = Gtk.Template.Child()
|
||||
treeview = Gtk.Template.Child()
|
||||
|
||||
@ -58,7 +57,7 @@ class CmbTypeChooserWidget(Gtk.Box):
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.connect("map", self.__on_map)
|
||||
#self.connect("map", self.__on_map)
|
||||
|
||||
def __type_info_should_append(self, info):
|
||||
retval = False
|
||||
@ -152,7 +151,6 @@ class CmbTypeChooserWidget(Gtk.Box):
|
||||
if self._filter:
|
||||
self._filter.set_visible_func(self.__visible_func)
|
||||
|
||||
self.entrycompletion.props.model = self.__model
|
||||
self.treeview.props.model = self._filter
|
||||
|
||||
if project is not None:
|
||||
@ -191,10 +189,10 @@ class CmbTypeChooserWidget(Gtk.Box):
|
||||
return type_id_lower.find(self._search_text) >= 0
|
||||
|
||||
def __on_map(self, widget):
|
||||
toplevel = widget.get_toplevel()
|
||||
root = widget.get_root()
|
||||
|
||||
if toplevel:
|
||||
height = toplevel.get_allocated_height() - 100
|
||||
if root:
|
||||
height = root.get_allocated_height() - 100
|
||||
if height > 460:
|
||||
height = height * 0.7
|
||||
|
||||
|
@ -1,54 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkEntryCompletion" id="entrycompletion">
|
||||
<property name="text-column">0</property>
|
||||
<property name="inline-completion">True</property>
|
||||
<property name="popup-completion">False</property>
|
||||
<property name="popup-single-match">False</property>
|
||||
</object>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbTypeChooserWidget" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="searchentry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="primary-icon-name">edit-find-symbolic</property>
|
||||
<property name="primary-icon-activatable">False</property>
|
||||
<property name="primary-icon-sensitive">False</property>
|
||||
<property name="completion">entrycompletion</property>
|
||||
<property name="input-hints">GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_NONE</property>
|
||||
<signal name="activate" handler="on_searchentry_activate" swapped="no"/>
|
||||
<signal name="search-changed" handler="on_searchentry_search_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="window-placement">bottom-left</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="max-content-height">512</property>
|
||||
<property name="propagate-natural-width">True</property>
|
||||
<property name="propagate-natural-height">True</property>
|
||||
<child>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkTreeView" id="treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="enable-search">False</property>
|
||||
<property name="activate-on-single-click">True</property>
|
||||
<property name="headers-visible">0</property>
|
||||
<property name="enable-search">0</property>
|
||||
<property name="activate-on-single-click">1</property>
|
||||
<signal name="row-activated" handler="on_treeview_row_activated" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection"/>
|
||||
@ -65,13 +38,8 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -1,142 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gladecambalache" version="0.0"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="CmbTextBuffer" id="authors"/>
|
||||
<object class="CmbTextBuffer" id="comment"/>
|
||||
<object class="CmbTextBuffer" id="copyright"/>
|
||||
<object class="CmbTextBuffer" id="description"/>
|
||||
<!-- n-columns=2 n-rows=8 -->
|
||||
<template class="CmbUIEditor" parent="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<property name="column-spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Filename:</property>
|
||||
<property name="label" translatable="1">Filename:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Description:</property>
|
||||
<property name="label" translatable="1">Description:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Copyright:</property>
|
||||
<property name="label" translatable="1">Copyright:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Authors:</property>
|
||||
<property name="label" translatable="1">Authors:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Domain:</property>
|
||||
<property name="label" translatable="1">Domain:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="filename">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="placeholder-text" translatable="yes"><file name relative to project></property>
|
||||
<property name="placeholder-text" translatable="1"><file name relative to project></property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="translation_domain">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="width-chars">16</property>
|
||||
<property name="placeholder-text" translatable="yes"><translation domain></property>
|
||||
<property name="placeholder-text" translatable="1"><translation domain></property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="min-content-height">96</property>
|
||||
<property name="max-content-height">256</property>
|
||||
<child>
|
||||
<property name="child">
|
||||
<object class="GtkTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">description</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="min-content-height">96</property>
|
||||
<property name="max-content-height">256</property>
|
||||
<child>
|
||||
<property name="child">
|
||||
<object class="GtkTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">authors</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbToplevelChooser" id="template_id">
|
||||
@ -144,129 +122,102 @@
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="derivable-only">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Template:</property>
|
||||
<property name="label" translatable="1">Template:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<signal name="clicked" handler="on_remove_button_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">app-remove-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="export_button">
|
||||
<property name="label" translatable="yes">Export</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Export</property>
|
||||
<property name="label" translatable="1">Export</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="tooltip-text" translatable="1">Export</property>
|
||||
<property name="halign">start</property>
|
||||
<signal name="clicked" handler="on_export_button_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">7</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">7</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="min-content-height">96</property>
|
||||
<property name="max-content-height">256</property>
|
||||
<child>
|
||||
<property name="child">
|
||||
<object class="GtkTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">copyright</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Comment:</property>
|
||||
<property name="label" translatable="1">Comment:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="min-content-height">96</property>
|
||||
<property name="max-content-height">256</property>
|
||||
<child>
|
||||
<property name="child">
|
||||
<object class="GtkTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">comment</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -24,6 +24,7 @@
|
||||
from gi.repository import GObject, Gtk
|
||||
|
||||
from .cmb_ui import CmbUI
|
||||
from . import utils
|
||||
|
||||
|
||||
class CmbUIRequiresEditor(Gtk.Grid):
|
||||
@ -71,7 +72,7 @@ class CmbUIRequiresEditor(Gtk.Grid):
|
||||
def __update(self):
|
||||
self.__combos = {}
|
||||
|
||||
for child in self.get_children():
|
||||
for child in utils.widget_get_children(self):
|
||||
self.remove(child)
|
||||
|
||||
if self.__object is None:
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# CmbView - Cambalache View
|
||||
#
|
||||
# Copyright (C) 2021 Juan Pablo Ugarte
|
||||
# Copyright (C) 2021-2024 Juan Pablo Ugarte
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@ -27,20 +27,21 @@ import socket
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from gi.repository import GObject, GLib, Gtk, WebKit2
|
||||
from gi.repository import GObject, GLib, Gtk, WebKit
|
||||
|
||||
from . import config
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_context_menu import CmbContextMenu
|
||||
from . import utils
|
||||
from cambalache import getLogger, _
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
basedir = os.path.dirname(__file__) or "."
|
||||
|
||||
GObject.type_ensure(WebKit2.Settings.__gtype__)
|
||||
GObject.type_ensure(WebKit2.WebView.__gtype__)
|
||||
GObject.type_ensure(WebKit.Settings.__gtype__)
|
||||
GObject.type_ensure(WebKit.WebView.__gtype__)
|
||||
|
||||
|
||||
class CmbProcess(GObject.Object):
|
||||
@ -111,7 +112,7 @@ class CmbProcess(GObject.Object):
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_view.ui")
|
||||
class CmbView(Gtk.Stack):
|
||||
class CmbView(Gtk.Box):
|
||||
__gtype_name__ = "CmbView"
|
||||
|
||||
__gsignals__ = {
|
||||
@ -121,6 +122,7 @@ class CmbView(Gtk.Stack):
|
||||
|
||||
preview = GObject.Property(type=bool, default=False, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
stack = Gtk.Template.Child()
|
||||
webview = Gtk.Template.Child()
|
||||
text_view = Gtk.Template.Child()
|
||||
|
||||
@ -129,6 +131,7 @@ class CmbView(Gtk.Stack):
|
||||
self.__restart_project = None
|
||||
self.__ui_id = 0
|
||||
self.__theme = None
|
||||
self.__dark = False
|
||||
|
||||
self.menu = self.__create_context_menu()
|
||||
|
||||
@ -145,23 +148,12 @@ class CmbView(Gtk.Stack):
|
||||
self.__port = None
|
||||
self.__merengue_last_exit = None
|
||||
|
||||
context = self.get_style_context()
|
||||
context.connect("changed", lambda ctx: self.__update_webview_bg())
|
||||
|
||||
if self.__broadwayd_bin is None:
|
||||
logger.warning("broadwayd not found, Gtk 3 workspace wont work.")
|
||||
|
||||
if self.__gtk4_broadwayd_bin is None:
|
||||
logger.warning("gtk4-broadwayd not found, Gtk 4 workspace wont work.")
|
||||
|
||||
GObject.Object.bind_property(
|
||||
self,
|
||||
"gtk-theme",
|
||||
self.menu,
|
||||
"gtk-theme",
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
|
||||
self.connect("notify::preview", self.__on_preview_notify)
|
||||
|
||||
def do_destroy(self):
|
||||
@ -174,23 +166,18 @@ class CmbView(Gtk.Stack):
|
||||
def __evaluate_js(self, script):
|
||||
self.webview.evaluate_javascript(script, -1, None, None, None, None, None, None)
|
||||
|
||||
def __update_webview_bg(self):
|
||||
context = self.get_style_context()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||
bg = context.get_background_color(Gtk.StateFlags.NORMAL)
|
||||
|
||||
self.__evaluate_js(f"document.body.style.background = '{bg.to_string()}';")
|
||||
def _set_dark_mode(self, dark):
|
||||
self.__dark = dark
|
||||
self.__evaluate_js(f"document.body.style.background = '{'#222' if dark else 'inherit'}';")
|
||||
|
||||
def __on_load_changed(self, webview, event):
|
||||
if event != WebKit2.LoadEvent.FINISHED:
|
||||
if event != WebKit.LoadEvent.FINISHED:
|
||||
return
|
||||
|
||||
self.__update_webview_bg()
|
||||
self._set_dark_mode(self.__dark)
|
||||
|
||||
# Disable alert() function used when broadwayd get disconnected
|
||||
# Monkey patch setupDocument() to avoid disabling document.oncontextmenu
|
||||
# Monkey pat ch setupDocument() to avoid disabling document.oncontextmenu
|
||||
self.__evaluate_js(
|
||||
"""
|
||||
window.alert = function (message) {
|
||||
@ -232,7 +219,7 @@ window.setupDocument = function (document) {
|
||||
|
||||
def __update_view(self):
|
||||
if self.__project is not None and self.__ui_id > 0:
|
||||
if self.props.visible_child_name == "ui_xml":
|
||||
if self.stack.props.visible_child_name == "ui_xml":
|
||||
ui = self.__get_ui_xml(self.__ui_id)
|
||||
self.text_view.buffer.set_text(ui)
|
||||
return
|
||||
@ -468,8 +455,8 @@ window.setupDocument = function (document) {
|
||||
self.__merengue_command("gtk_settings_set", args={"property": "gtk-theme-name", "value": theme})
|
||||
|
||||
@Gtk.Template.Callback("on_context_menu")
|
||||
def __on_context_menu(self, webview, menu, e, hit_test_result):
|
||||
self.menu.popup_at(e.x, e.y)
|
||||
def __on_context_menu(self, webview, menu, hit_test_result):
|
||||
self.menu.popup_at(*utils.get_pointer(self))
|
||||
return True
|
||||
|
||||
def __webview_set_msg(self, msg):
|
||||
@ -494,25 +481,20 @@ window.setupDocument = function (document) {
|
||||
if bin is not None:
|
||||
self.__webview_set_msg(_("Workspace not available\n{bin} executable not found").format(bin=bin))
|
||||
|
||||
def __on_inspect_button_clicked(self, button):
|
||||
self.props.visible_child_name = "ui_xml"
|
||||
def inspect(self):
|
||||
self.stack.props.visible_child_name = "ui_xml"
|
||||
self.__update_view()
|
||||
|
||||
def __on_restart_button_clicked(self, button):
|
||||
def restart_workspace(self):
|
||||
self.__restart_project = self.__project
|
||||
self.project = None
|
||||
|
||||
def __create_context_menu(self):
|
||||
retval = CmbContextMenu(relative_to=self)
|
||||
retval = CmbContextMenu()
|
||||
retval.set_parent(self)
|
||||
|
||||
restart = Gtk.ModelButton(text=_("Restart workspace"), visible=True)
|
||||
restart.connect("clicked", self.__on_restart_button_clicked)
|
||||
|
||||
inspect = Gtk.ModelButton(text=_("Inspect UI definition"), visible=True)
|
||||
inspect.connect("clicked", self.__on_inspect_button_clicked)
|
||||
|
||||
retval.main_box.add(restart)
|
||||
retval.main_box.add(inspect)
|
||||
retval.main_section.append(_("Restart workspace"), "win.workspace_restart")
|
||||
retval.main_section.append(_("Inspect UI definition"), "win.inspect")
|
||||
|
||||
return retval
|
||||
|
||||
|
@ -1,87 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="webkit2gtk" version="2.28"/>
|
||||
<object class="WebKitSettings" type-func="webkit_settings_get_type" id="settings">
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="WebKitSettings" id="settings">
|
||||
<property name="enable-html5-local-storage">False</property>
|
||||
<property name="enable-html5-database">False</property>
|
||||
<property name="enable-java">False</property>
|
||||
<property name="enable-fullscreen">False</property>
|
||||
<property name="enable-webaudio">False</property>
|
||||
<property name="media-playback-allows-inline">False</property>
|
||||
<property name="user-agent">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15</property>
|
||||
<property name="enable-accelerated-2d-canvas">True</property>
|
||||
<property name="enable-media">False</property>
|
||||
</object>
|
||||
<template class="CmbView" parent="GtkStack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="events">GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
|
||||
<template class="CmbView" parent="GtkBox">
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="transition-duration">300</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<child>
|
||||
<object class="WebKitWebView" type-func="webkit_web_view_get_type" id="webview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="settings">settings</property>
|
||||
<signal name="context-menu" handler="on_context_menu" swapped="no"/>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">ui_view</property>
|
||||
<property name="title" translatable="yes">Project View</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="title" translatable="1">Project View</property>
|
||||
<property name="child">
|
||||
<object class="WebKitWebView" id="webview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="settings">settings</property>
|
||||
<signal name="context-menu" handler="on_context_menu" swapped="no"/>
|
||||
<child>
|
||||
<object class="CmbSourceView" id="text_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="cursor-visible">False</property>
|
||||
<property name="lang">xml</property>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">ui_xml</property>
|
||||
<property name="title" translatable="1">UI Definition</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="focusable">1</property>
|
||||
<child>
|
||||
<object class="CmbSourceView" id="text_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="cursor-visible">False</property>
|
||||
<property name="lang">xml</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackSwitcher">
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">4</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="stack">CmbView</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackSwitcher">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-top">4</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="stack">CmbView</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">ui_xml</property>
|
||||
<property name="title" translatable="yes">UI Definition</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -35,23 +35,30 @@ class CmbColorEntry(Gtk.Box):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.entry = Gtk.Entry(visible=True, width_chars=14, editable=False)
|
||||
self.button = Gtk.ColorButton(visible=True, use_alpha=True)
|
||||
self.button = Gtk.ColorDialogButton(
|
||||
visible=True,
|
||||
dialog=Gtk.ColorDialog()
|
||||
)
|
||||
|
||||
self.__default_color = self.button.props.color
|
||||
#self.__default_color = self.button.props.color
|
||||
self.__default_rgba = self.button.props.rgba
|
||||
|
||||
self.pack_start(self.entry, False, True, 0)
|
||||
self.pack_start(self.button, False, True, 4)
|
||||
self.append(self.entry)
|
||||
self.append(self.button)
|
||||
|
||||
self.button.connect("color-set", self.__on_color_set)
|
||||
# FIXME: GTK4
|
||||
self.button.connect("notify::rgba", self.__on_color_set)
|
||||
self.entry.connect("icon-press", self.__on_entry_icon_pressed)
|
||||
|
||||
def __on_entry_icon_pressed(self, widget, icon_pos, event):
|
||||
self.cmb_value = None
|
||||
|
||||
def __on_color_set(self, obj):
|
||||
def __on_color_set(self, obj, pspec):
|
||||
print(self.use_color, self.button.props.rgba.to_string())
|
||||
if self.use_color:
|
||||
self.cmb_value = self.button.props.color.to_string() if self.button.props.color else None
|
||||
pass
|
||||
# FIXME: GTK4
|
||||
#self.cmb_value = self.button.props.color.to_string() if self.button.props.color else None
|
||||
else:
|
||||
self.cmb_value = self.button.props.rgba.to_string() if self.button.props.rgba else None
|
||||
|
||||
@ -75,7 +82,8 @@ class CmbColorEntry(Gtk.Box):
|
||||
if value:
|
||||
valid, color = Gdk.Color.parse(value)
|
||||
|
||||
self.button.set_color(color if valid else self.__default_color)
|
||||
# FIXME: GTK4
|
||||
#self.button.set_color(color if valid else self.__default_color)
|
||||
else:
|
||||
rgba = Gdk.RGBA()
|
||||
|
||||
|
@ -37,8 +37,9 @@ class CmbEntry(Gtk.Entry):
|
||||
self.props.secondary_icon_name = "document-edit-symbolic"
|
||||
self.connect("icon-press", self.__on_icon_pressed)
|
||||
|
||||
def __on_icon_pressed(self, widget, icon_pos, event):
|
||||
popover = CmbTranslatablePopover(relative_to=self)
|
||||
def __on_icon_pressed(self, widget, icon_pos):
|
||||
popover = CmbTranslatablePopover()
|
||||
popover.set_parent(self)
|
||||
popover.bind_properties(self._target)
|
||||
popover.popup()
|
||||
|
||||
|
@ -47,14 +47,16 @@ class CmbFlagsEntry(Gtk.Entry):
|
||||
self.__init_popover()
|
||||
|
||||
def __init_popover(self):
|
||||
self._popover = Gtk.Popover(relative_to=self)
|
||||
self._popover = Gtk.Popover()
|
||||
self._popover.set_parent(self)
|
||||
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
box.pack_start(Gtk.Label(label=f"<b>{self.info.type_id}</b>", use_markup=True), False, True, 4)
|
||||
box.pack_start(Gtk.Separator(), False, False, 0)
|
||||
box.prepend(Gtk.Label(label=f"<b>{self.info.type_id}</b>", use_markup=True))
|
||||
box.prepend(Gtk.Separator())
|
||||
sw = Gtk.ScrolledWindow(hscrollbar_policy=Gtk.PolicyType.NEVER, propagate_natural_height=True, max_content_height=360)
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
sw.add(vbox)
|
||||
box.pack_start(sw, True, True, 0)
|
||||
sw.set_child(vbox)
|
||||
box.prepend(sw)
|
||||
|
||||
for row in self.info.flags:
|
||||
flag = row[self.text_column]
|
||||
@ -62,18 +64,17 @@ class CmbFlagsEntry(Gtk.Entry):
|
||||
|
||||
check = Gtk.CheckButton(label=flag)
|
||||
check.connect("toggled", self.__on_check_toggled, flag_id)
|
||||
vbox.pack_start(check, False, True, 4)
|
||||
vbox.prepend(check)
|
||||
self._checks[flag_id] = check
|
||||
|
||||
box.show_all()
|
||||
self._popover.add(box)
|
||||
self._popover.set_child(box)
|
||||
|
||||
def __on_check_toggled(self, check, flag_id):
|
||||
self.flags[flag_id] = check.props.active
|
||||
self.props.text = self.__to_string()
|
||||
self.notify("cmb-value")
|
||||
|
||||
def __on_icon_release(self, obj, pos, event):
|
||||
def __on_icon_release(self, obj, pos):
|
||||
self._popover.popup()
|
||||
|
||||
def __to_string(self):
|
||||
|
@ -24,7 +24,7 @@
|
||||
import os
|
||||
|
||||
from cambalache import _
|
||||
from gi.repository import GdkPixbuf, GObject, Gtk, Pango
|
||||
from gi.repository import GLib, Gio, GdkPixbuf, GObject, Gdk, Gtk, Pango
|
||||
from .cmb_entry import CmbEntry
|
||||
from .icon_naming_spec import standard_icon_context, standard_icon_names
|
||||
|
||||
@ -48,6 +48,8 @@ class CmbIconNameEntry(CmbEntry):
|
||||
# Model, store it in a Python class variable to share between all instances
|
||||
icon_model = None
|
||||
|
||||
iconlist = []
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._filters = {}
|
||||
|
||||
@ -91,32 +93,56 @@ class CmbIconNameEntry(CmbEntry):
|
||||
|
||||
iconlist = []
|
||||
|
||||
theme = Gtk.IconTheme.get_default()
|
||||
theme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default())
|
||||
|
||||
for context in theme.list_contexts():
|
||||
for icon in theme.list_icons(context):
|
||||
iconlist.append((icon, context, icon in standard_icon_names))
|
||||
# FIXME: get the context/category of each icon
|
||||
for icon in theme.get_icon_names():
|
||||
iconlist.append((icon, "cmb_all", icon in standard_icon_names))
|
||||
|
||||
for icon, context, standard in sorted(iconlist, key=lambda i: i[0].lower()):
|
||||
if icon.endswith(".symbolic"):
|
||||
continue
|
||||
|
||||
info = theme.lookup_icon(icon, 32, Gtk.IconLookupFlags.FORCE_SIZE)
|
||||
symbolic = info.is_symbolic()
|
||||
icon_paintable = theme.lookup_icon(icon, None, 32, 1, Gtk.TextDirection.NONE, Gtk.IconLookupFlags.PRELOAD)
|
||||
symbolic = icon_paintable.is_symbolic()
|
||||
|
||||
if not os.path.exists(info.get_filename()):
|
||||
icon_file = icon_paintable.get_file()
|
||||
if icon_file is None:
|
||||
continue
|
||||
|
||||
icon_path = icon_file.get_path()
|
||||
if icon_path is None or not os.path.exists(icon_path):
|
||||
continue
|
||||
|
||||
standard_symbolic = symbolic and icon.removesuffix("-symbolic") in standard_icon_names
|
||||
|
||||
iter = cls.icon_model.append(
|
||||
[icon, icon if standard else f"<i>{icon}</i>", context, standard, symbolic, standard_symbolic, None]
|
||||
)
|
||||
info.load_icon_async(None, cls.__load_icon_finish, iter)
|
||||
try:
|
||||
iter = cls.icon_model.append(
|
||||
[icon, icon if standard else f"<i>{icon}</i>", context, standard, symbolic, standard_symbolic, None]
|
||||
)
|
||||
cls.iconlist.append((icon_file, iter))
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
# Kickoff async loading
|
||||
file, iter = cls.iconlist.pop()
|
||||
file.read_async(GLib.PRIORITY_DEFAULT, None, cls.__load_file_finish, iter)
|
||||
|
||||
@classmethod
|
||||
def __load_icon_finish(cls, info, res, data):
|
||||
cls.icon_model[data][6] = info.load_icon_finish(res)
|
||||
def __load_file_finish(cls, obj, res, iter):
|
||||
stream = obj.read_finish(res)
|
||||
GdkPixbuf.Pixbuf.new_from_stream_at_scale_async(stream, 32, 32, True, None, cls.__load_icon_finish, iter)
|
||||
|
||||
@classmethod
|
||||
def __load_icon_finish(cls, obj, res, iter):
|
||||
try:
|
||||
cls.icon_model[iter][cls.COL_PIXBUF] = GdkPixbuf.Pixbuf.new_from_stream_finish(res)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
if len(cls.iconlist):
|
||||
file, iter = cls.iconlist.pop()
|
||||
file.read_async(GLib.PRIORITY_DEFAULT, None, cls.__load_file_finish, iter)
|
||||
|
||||
def __model_filter_func(self, model, iter, data):
|
||||
if self.standard_only and self.symbolic_only:
|
||||
@ -146,20 +172,23 @@ class CmbIconNameEntry(CmbEntry):
|
||||
else:
|
||||
self.cmb_value = None
|
||||
|
||||
def __on_icon_pressed(self, widget, icon_pos, event):
|
||||
def __on_icon_pressed(self, widget, icon_pos):
|
||||
# Create popover with icon chooser
|
||||
popover = Gtk.Popover(relative_to=self)
|
||||
popover = Gtk.Popover()
|
||||
popover.set_parent(self)
|
||||
|
||||
hbox = Gtk.Box(visible=True)
|
||||
vbox = Gtk.Box(visible=True, orientation=Gtk.Orientation.VERTICAL, vexpand=True)
|
||||
stack = Gtk.Stack(visible=True, transition_type=Gtk.StackTransitionType.CROSSFADE)
|
||||
sidebar = Gtk.StackSidebar(visible=True, stack=stack, vexpand=True)
|
||||
vbox.pack_start(sidebar, True, True, 4)
|
||||
hbox.pack_start(vbox, False, True, 4)
|
||||
hbox.pack_start(stack, True, True, 4)
|
||||
vbox.append(sidebar)
|
||||
hbox.append(vbox)
|
||||
hbox.append(stack)
|
||||
|
||||
theme = Gtk.IconTheme.get_default()
|
||||
theme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default())
|
||||
|
||||
sorted_contexts = sorted(theme.list_contexts())
|
||||
# sorted_contexts = sorted(theme.list_contexts())
|
||||
sorted_contexts = []
|
||||
sorted_contexts.insert(0, "cmb_all")
|
||||
|
||||
# Add one icon view per context
|
||||
@ -175,7 +204,7 @@ class CmbIconNameEntry(CmbEntry):
|
||||
sw = Gtk.ScrolledWindow(visible=True, min_content_width=600, min_content_height=480)
|
||||
view = Gtk.IconView(visible=True, model=filter, pixbuf_column=self.COL_PIXBUF, text_column=self.COL_ICON_NAME)
|
||||
view.connect("selection-changed", self.__on_view_selection_changed)
|
||||
sw.add(view)
|
||||
sw.set_child(view)
|
||||
stack.add_titled(sw, context, standard_icon_context.get(context, context))
|
||||
|
||||
# Add filters
|
||||
@ -185,8 +214,8 @@ class CmbIconNameEntry(CmbEntry):
|
||||
self, prop, check, "active", GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL
|
||||
)
|
||||
check.connect_after("notify::active", self.__on_check_active_notify)
|
||||
vbox.pack_start(check, False, True, 4)
|
||||
vbox.append(check)
|
||||
|
||||
popover.get_style_context().add_class("cmb-icon-chooser")
|
||||
popover.add(hbox)
|
||||
popover.add_css_class("cmb-icon-chooser")
|
||||
popover.set_child(hbox)
|
||||
popover.popup()
|
||||
|
@ -106,7 +106,7 @@ class CmbObjectChooser(Gtk.Entry):
|
||||
parent.project.add_object(parent.ui_id, info.type_id, parent_id=parent.object_id, inline_property=self.prop.property_id)
|
||||
self.__update_icons()
|
||||
|
||||
def __on_icon_pressed(self, widget, icon_pos, event):
|
||||
def __on_icon_pressed(self, widget, icon_pos):
|
||||
parent = self.parent
|
||||
project = parent.project
|
||||
prop = self.prop
|
||||
@ -116,7 +116,8 @@ class CmbObjectChooser(Gtk.Entry):
|
||||
project.remove_object(obj)
|
||||
self.__update_icons()
|
||||
else:
|
||||
chooser = CmbTypeChooserPopover(relative_to=self, parent_type_id=parent.type_id, derived_type_id=prop.info.type_id)
|
||||
chooser = CmbTypeChooserPopover(parent_type_id=parent.type_id, derived_type_id=prop.info.type_id)
|
||||
chooser.set_parent(self)
|
||||
chooser.project = project
|
||||
chooser.connect("type-selected", self.__on_type_selected)
|
||||
chooser.popup()
|
||||
|
@ -33,7 +33,6 @@ class CmbTextView(Gtk.ScrolledWindow):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.props.shadow_type = Gtk.ShadowType.IN
|
||||
self.props.height_request = 64
|
||||
self.buffer = CmbTextBuffer()
|
||||
self.view = Gtk.TextView(visible=True, buffer=self.buffer)
|
||||
@ -46,4 +45,4 @@ class CmbTextView(Gtk.ScrolledWindow):
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
|
||||
self.add(self.view)
|
||||
self.set_child(self.view)
|
||||
|
@ -35,14 +35,13 @@ class CmbTranslatablePopover(Gtk.Popover):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
box.pack_start(Gtk.Label(label=_("<b>Translation</b>"), use_markup=True), False, True, 4)
|
||||
box.pack_start(Gtk.Separator(), False, False, 0)
|
||||
box.append(Gtk.Label(label=_("<b>Translation</b>"), use_markup=True))
|
||||
box.append(Gtk.Separator())
|
||||
|
||||
self._translation = CmbTranslatableWidget()
|
||||
box.pack_start(self._translation, False, False, 0)
|
||||
box.append(self._translation)
|
||||
|
||||
box.show_all()
|
||||
self.add(box)
|
||||
self.set_child(box)
|
||||
|
||||
def bind_properties(self, target):
|
||||
self._translation.bind_properties(target)
|
||||
|
@ -1,13 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkTextBuffer" id="buffer_comments"/>
|
||||
<object class="GtkTextBuffer" id="buffer_context"/>
|
||||
<object class="GtkTextBuffer" id="buffer_text"/>
|
||||
<template class="CmbTranslatableWidget" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">4</property>
|
||||
<property name="margin-end">4</property>
|
||||
<property name="margin-top">4</property>
|
||||
@ -16,126 +13,70 @@
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Text:</property>
|
||||
<property name="label" translatable="1">Text:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width-request">300</property>
|
||||
<property name="height-request">60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<property name="focusable">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkTextView" id="text_view_value">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="border-width">2</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">buffer_text</property>
|
||||
<property name="accepts-tab">False</property>
|
||||
<property name="accepts-tab">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_button_translatable">
|
||||
<property name="label" translatable="yes">translatable</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="label" translatable="1">translatable</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="label" translatable="yes">Translation context:</property>
|
||||
<property name="label" translatable="1">Translation context:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="height-request">60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<property name="focusable">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkTextView" id="text_view_context">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="border-width">2</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">buffer_context</property>
|
||||
<property name="accepts-tab">False</property>
|
||||
<property name="accepts-tab">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="label" translatable="yes">Comments for translators:</property>
|
||||
<property name="label" translatable="1">Comments for translators:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="height-request">60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<property name="focusable">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkTextView" id="text_view_comments">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="border-width">2</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="buffer">buffer_comments</property>
|
||||
<property name="accepts-tab">False</property>
|
||||
<property name="accepts-tab">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -136,8 +136,8 @@ class MrgApplication(Gtk.Application):
|
||||
# FIXME: object_id could be reused for a different object type
|
||||
# if you undo the creation of a widget and create a different type
|
||||
# As a workaround if the types do not match we create a new controller
|
||||
# This could be fixed if we alway auto increment object_id but then
|
||||
# we would have to clean up unussed controllers
|
||||
# This could be fixed if we always auto increment object_id but then
|
||||
# we would have to clean up unused controllers
|
||||
if pspec is None or pspec.value_type != obj.__gtype__:
|
||||
controller = self.registry.new_controller_for_type(obj.__gtype__, self)
|
||||
|
||||
|
@ -100,15 +100,20 @@ class MrgGtkWidget(MrgController):
|
||||
if self.object is None:
|
||||
return
|
||||
|
||||
if self.selected:
|
||||
self.object.get_style_context().add_class("merengue_selected")
|
||||
else:
|
||||
self.object.get_style_context().remove_class("merengue_selected")
|
||||
|
||||
# Update toplevel backdrop state
|
||||
if Gtk.MAJOR_VERSION == 4:
|
||||
if self.selected:
|
||||
self.object.add_css_class("merengue_selected")
|
||||
else:
|
||||
self.object.remove_css_class("merengue_selected")
|
||||
|
||||
toplevel = self.object.get_root()
|
||||
else:
|
||||
if self.selected:
|
||||
self.object.get_style_context().add_class("merengue_selected")
|
||||
else:
|
||||
self.object.get_style_context().remove_class("merengue_selected")
|
||||
|
||||
toplevel = self.object.get_toplevel()
|
||||
|
||||
if toplevel:
|
||||
|
@ -80,8 +80,10 @@ class MrgGtkWindow(MrgGtkBin):
|
||||
self.object.show_all()
|
||||
|
||||
# Add gtk version CSS class
|
||||
gtkversion = "gtk4" if Gtk.MAJOR_VERSION == 4 else "gtk3"
|
||||
self.object.get_style_context().add_class(gtkversion)
|
||||
if Gtk.MAJOR_VERSION == 4:
|
||||
self.object.add_css_class("gtk4")
|
||||
else:
|
||||
self.object.get_style_context().add_class("gtk3")
|
||||
|
||||
self._restore_state()
|
||||
|
||||
|
@ -48,15 +48,17 @@ def version_cmp_str(a, b):
|
||||
|
||||
|
||||
def unset_scroll_event(widget):
|
||||
def ignore_scroll_event(widget, event):
|
||||
Gtk.propagate_event(widget.get_parent(), event)
|
||||
return True
|
||||
pass
|
||||
# FIXME: GTK4
|
||||
# def ignore_scroll_event(widget, event):
|
||||
# Gtk.propagate_event(widget.get_parent(), event)
|
||||
# return True
|
||||
|
||||
events = widget.get_events()
|
||||
widget.set_events(events & ~(Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.SMOOTH_SCROLL_MASK))
|
||||
# events = widget.get_events()
|
||||
# widget.set_events(events & ~(Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.SMOOTH_SCROLL_MASK))
|
||||
|
||||
if isinstance(widget, Gtk.ComboBox):
|
||||
widget.connect("scroll-event", ignore_scroll_event)
|
||||
# if isinstance(widget, Gtk.ComboBox):
|
||||
# widget.connect("scroll-event", ignore_scroll_event)
|
||||
|
||||
|
||||
def get_version_warning(target, version, deprecated_version, this):
|
||||
@ -69,3 +71,32 @@ def get_version_warning(target, version, deprecated_version, this):
|
||||
return f"UI targets {target} but {this} was deprecated in {deprecated_version}"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def widget_get_children(widget):
|
||||
retval = []
|
||||
|
||||
child = widget.get_first_child()
|
||||
while child is not None:
|
||||
retval.append(child)
|
||||
child = child.get_next_sibling()
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def get_pointer(widget):
|
||||
root = widget.get_root()
|
||||
pointer = widget.get_display().get_default_seat().get_pointer()
|
||||
valid, x, y, mask = root.get_surface().get_device_position(pointer)
|
||||
|
||||
if valid:
|
||||
return root.translate_coordinates(widget, x, y)
|
||||
|
||||
return (None, None)
|
||||
|
||||
|
||||
def get_pointing_to(widget):
|
||||
r = Gdk.Rectangle()
|
||||
r.x, r.y = get_pointer(widget)
|
||||
r.width = r.height = 0
|
||||
return r
|
||||
|
@ -6,7 +6,7 @@ project(
|
||||
|
||||
# File format version follows app version and only changes when there is a
|
||||
# change that prevents older versions to load it.
|
||||
fileformatversion = '0.13.1'
|
||||
fileformatversion = '0.17.0'
|
||||
|
||||
python = import('python')
|
||||
python_bin = python.find_installation('python3')
|
||||
|
@ -61,7 +61,7 @@ def close_compositor():
|
||||
|
||||
|
||||
# Make sure the right gtk version is loaded
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version("Gtk", "4.0")
|
||||
|
||||
# Make sure we can run Cambalache from sources
|
||||
cmb_init_dev()
|
||||
|
@ -28,28 +28,23 @@ import struct
|
||||
from gi.repository import GLib, Gtk
|
||||
|
||||
|
||||
# Based on Gtk sources gtk-reftest.c
|
||||
# Based on Gtk sources gtktestutils.c gtk_test_widget_wait_for_draw()
|
||||
def wait_for_drawing(window):
|
||||
def on_window_draw(widget, cr, loop):
|
||||
loop.quit()
|
||||
return False
|
||||
done = { "done": False }
|
||||
main_loop = GLib.MainContext.default()
|
||||
|
||||
def quit_when_idle(loop):
|
||||
loop.quit()
|
||||
def quit_main_loop_callback(widget, frame_clock, done):
|
||||
done["done"] = True
|
||||
print("BBBBBBBBB")
|
||||
main_loop.wakeup()
|
||||
print("CCCCCCCCCCCCCC")
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
loop = GLib.MainLoop()
|
||||
window.add_tick_callback(quit_main_loop_callback, done)
|
||||
|
||||
# We wait until the widget is drawn for the first time.
|
||||
# We are running in a dedicated compositor so the window should not be obstructed by other windows
|
||||
window.connect("draw", on_window_draw, loop)
|
||||
loop.run()
|
||||
window.disconnect_by_func(on_window_draw)
|
||||
|
||||
# give the WM/server some time to sync. They need it.
|
||||
window.get_display().sync()
|
||||
GLib.timeout_add(500, quit_when_idle, loop)
|
||||
loop.run()
|
||||
print("AAAAAAAAAAAA")
|
||||
while not done["done"]:
|
||||
main_loop.iteration(True)
|
||||
|
||||
|
||||
def surface_write_ppm(surface, path):
|
||||
@ -71,13 +66,20 @@ def window_screenshot(window):
|
||||
# Wait for window to finish drawing
|
||||
wait_for_drawing(window)
|
||||
|
||||
w = window.get_allocated_width()
|
||||
h = window.get_allocated_height()
|
||||
paintable = Gtk.WidgetPaintable.new(window)
|
||||
snapshot = Gtk.Snapshot()
|
||||
|
||||
w = paintable.get_intrinsic_width()
|
||||
h = paintable.get_intrinsic_height()
|
||||
|
||||
# Draw widget to cairo surface
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h)
|
||||
|
||||
paintable.snapshot(snapshot, w, h)
|
||||
node = snapshot.to_node()
|
||||
|
||||
cr = cairo.Context(surface)
|
||||
window.draw(cr)
|
||||
node.draw(cr)
|
||||
|
||||
surface.flush()
|
||||
|
||||
@ -124,26 +126,36 @@ def mean_squared_error(original, screenshot, ignore_color=None):
|
||||
|
||||
|
||||
def process_all_pending_gtk_events():
|
||||
while Gtk.events_pending():
|
||||
Gtk.main_iteration_do(False)
|
||||
main_loop = GLib.MainContext.default()
|
||||
while main_loop.pending():
|
||||
main_loop.iteration(False)
|
||||
|
||||
|
||||
def __get_children(obj):
|
||||
if obj is None:
|
||||
return []
|
||||
|
||||
retval = []
|
||||
|
||||
child = obj.get_first_child()
|
||||
while child is not None:
|
||||
retval.append(child)
|
||||
child = child.get_next_sibling()
|
||||
return retval
|
||||
|
||||
|
||||
def find_by_buildable_id(widget, name):
|
||||
retval = None
|
||||
|
||||
if isinstance(widget, Gtk.Buildable) and Gtk.Buildable.get_name(widget) == name:
|
||||
if isinstance(widget, Gtk.Buildable) and Gtk.Buildable.get_buildable_id(widget) == name:
|
||||
return widget
|
||||
|
||||
if not isinstance(widget, Gtk.Container):
|
||||
return None
|
||||
for child in __get_children(widget):
|
||||
retval = find_by_buildable_id(child, name)
|
||||
if retval:
|
||||
return retval
|
||||
|
||||
for child in widget.get_children():
|
||||
if isinstance(child, Gtk.Container):
|
||||
retval = find_by_buildable_id(child, name)
|
||||
if retval:
|
||||
return retval
|
||||
|
||||
if isinstance(child, Gtk.Buildable) and Gtk.Buildable.get_name(child) == name:
|
||||
if isinstance(child, Gtk.Buildable) and Gtk.Buildable.get_buildable_id(child) == name:
|
||||
return child
|
||||
|
||||
return retval
|
||||
@ -159,8 +171,9 @@ def cmb_create_app():
|
||||
window = None
|
||||
|
||||
# Spin until we get the main window
|
||||
while Gtk.events_pending() and not window:
|
||||
Gtk.main_iteration_do(False)
|
||||
main_loop = GLib.MainContext.default()
|
||||
while main_loop.pending() and not window:
|
||||
main_loop.iteration(False)
|
||||
|
||||
# Get window if any
|
||||
windows = app.get_windows()
|
||||
|
Loading…
x
Reference in New Issue
Block a user