mirror of
https://gitlab.gnome.org/jpu/cambalache.git
synced 2025-06-25 00:02:51 -04:00
Compare commits
131 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
53062b7d3c | ||
|
9aaace82f7 | ||
|
bbb2ce2bf9 | ||
|
dd90c3fc2b | ||
|
8742945f3f | ||
|
06c62349a7 | ||
|
bc6163b1ac | ||
|
ac74e23fde | ||
|
2e29c016f7 | ||
|
b572a7eae3 | ||
|
f96d19ab64 | ||
|
680f9d3243 | ||
|
6fa7f22c9c | ||
|
6ac16ca8c0 | ||
|
e2dbb15a18 | ||
|
c57891a3c8 | ||
|
ccdf5d6ef0 | ||
|
bb39873cd5 | ||
|
9529bfaf76 | ||
|
13db1c20c2 | ||
|
963cee5eec | ||
|
08a73f9c28 | ||
|
02935555bf | ||
|
befb056d2c | ||
|
9cd6e05d5f | ||
|
57a3f3832a | ||
|
8c80fc5d3d | ||
|
7baf191c0b | ||
|
8d170bab39 | ||
|
b592367640 | ||
|
d41c08b68a | ||
|
7de36972dd | ||
|
6b1ae2ad75 | ||
|
296d7767f9 | ||
|
e6e55da821 | ||
|
530c211262 | ||
|
175d1d1b61 | ||
|
1401c0c480 | ||
|
acadc33f02 | ||
|
9d8794cfb0 | ||
|
011c6dc082 | ||
|
258f04825b | ||
|
61893998dd | ||
|
7baa2cfbbe | ||
|
60f3e49672 | ||
|
7213b0351f | ||
|
0709c8487b | ||
|
b2d95c576d | ||
|
211d13b14a | ||
|
5e16c964ee | ||
|
bda30ef76e | ||
|
8858257f6d | ||
|
14d0b3dd39 | ||
|
05bdb5d98e | ||
|
af6258fe8a | ||
|
5de6214da2 | ||
|
4c8cbda88d | ||
|
04ec6758f0 | ||
|
ecf21c544d | ||
|
a9c05ef202 | ||
|
df1dd90146 | ||
|
477c45a32c | ||
|
99d58df208 | ||
|
5f69f152a1 | ||
|
45f6cf920b | ||
|
425aed1872 | ||
|
0d93f151bf | ||
|
a2945f2de2 | ||
|
34bdc5e530 | ||
|
dcc4b0a199 | ||
|
3f23b4a9e7 | ||
|
4db249bf28 | ||
|
8b02d13e01 | ||
|
31b93cef82 | ||
|
c7885f5ab6 | ||
|
9a0db6c2f3 | ||
|
cb1aed17b8 | ||
|
09d118dbc0 | ||
|
829dc50bae | ||
|
94cce882aa | ||
|
f0c1543982 | ||
|
fb930b36da | ||
|
48c004a1e6 | ||
|
f3662b8095 | ||
|
986e3705b4 | ||
|
e30b93506b | ||
|
907c4938a0 | ||
|
874a506f47 | ||
|
2623583f3a | ||
|
1f709586fb | ||
|
6e1935d9fb | ||
|
bc74332ecf | ||
|
7aaabca392 | ||
|
53854f6615 | ||
|
edee67cc72 | ||
|
937211565c | ||
|
c6c278444f | ||
|
56b8af7f97 | ||
|
526b880187 | ||
|
e8cf3eb578 | ||
|
0e4d55eaa2 | ||
|
627c7a4fa9 | ||
|
7f6cd3c005 | ||
|
ffdeb0c6c0 | ||
|
d3e52c3b3b | ||
|
bfe13f87d4 | ||
|
e4a6ae3e36 | ||
|
e242742a29 | ||
|
458e93abce | ||
|
1c0d1a686a | ||
|
0ce1286acc | ||
|
f6ffc64988 | ||
|
5ca4aa2377 | ||
|
2468a22178 | ||
|
3b6b8023af | ||
|
afd241b7ea | ||
|
23c6576514 | ||
|
4c219cd58a | ||
|
39b47123dd | ||
|
f941661e49 | ||
|
572bf8f1ac | ||
|
097ccce2f7 | ||
|
530ed75c79 | ||
|
be19adfba0 | ||
|
cf7a91ceb4 | ||
|
c88712db76 | ||
|
9ea01bdec7 | ||
|
6b323e4475 | ||
|
ee660f396e | ||
|
92cc81894a | ||
|
db70b1c2b8 |
12
.local.env
12
.local.env
@ -1,12 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
SCRIPT=$(readlink -f $0)
|
||||
DIRNAME=$(dirname $SCRIPT)
|
||||
ARCH_TRIPLET=$(cc -dumpmachine)
|
||||
export LD_LIBRARY_PATH=$DIRNAME/.local/lib/$ARCH_TRIPLET:$LD_LIBRARY_PATH
|
||||
export GI_TYPELIB_PATH=$DIRNAME/.local/lib/$ARCH_TRIPLET/girepository-1.0:$GI_TYPELIB_PATH
|
||||
export PKG_CONFIG_PATH=$DIRNAME/.local/lib/$ARCH_TRIPLET/pkgconfig:$PKG_CONFIG_PATH
|
||||
export GSETTINGS_SCHEMA_DIR=$DIRNAME/.local/share/glib-2.0/schemas:$GSETTINGS_SCHEMA_DIR
|
||||
export XDG_DATA_DIRS=$DIRNAME/.local/share:$XDG_DATA_DIRS
|
||||
export PYTHONPATH=$DIRNAME/.local/lib/python3/dist-packages:$PYTHONPATH
|
||||
export PATH=$DIRNAME/.local/bin:$PATH
|
36
CHANGELOG.md
36
CHANGELOG.md
@ -9,6 +9,42 @@ Cambalache used even/odd minor numbers to differentiate between stable and
|
||||
development releases.
|
||||
|
||||
|
||||
## 0.96.0
|
||||
|
||||
- Add GResource support
|
||||
- Add internal children support
|
||||
- New project format
|
||||
- Save directly to .ui files
|
||||
- Show directory structure in navigation
|
||||
- Unified import dialog for all file types
|
||||
- Add Finnish translation. Erwinjitsu
|
||||
- Use AdwAboutDialog lo-vely
|
||||
- Add action child type to GtkDialog
|
||||
|
||||
### Packaging changes
|
||||
|
||||
- pygobject-3.0 dependency bumped to 3.52 which depends on the new gi repository from GLib
|
||||
- libcambalacheprivate-[3|4] and its typelib are now installed under libdir/cambalache
|
||||
- libcmbcatalogutils-[3|4] and its typelib are now installed under libdir/cmb_catalog_gen
|
||||
- Gtk 3, Handy, webkit2gtk and webkitgtk are now optional dependencies
|
||||
|
||||
### Issues
|
||||
|
||||
- #253 "Error updating UI 1: gtk-builder-error-quark: .:8:1 Invalid object type 'AdwApplicationWindow' (6)"
|
||||
- #145 "Consider Cambalache to manage resource description file for building the resource bundle"
|
||||
- #54 "Add support for internal children"
|
||||
- #255 "Unable to open files via the UI in a KDE Plasma session"
|
||||
- #260 "Wrong default for Swap setting in signals"
|
||||
- #259 "Install private shared libraries in sub directories of the main library path"
|
||||
- #263 "Translatable setting resets when label field is empty"
|
||||
- #264 "Error undoing removal of parent GtkGrid"
|
||||
- #266 "Error "Unknown internal child: entry (6)" with particular GTK 3 UI file"
|
||||
- #265 "GtkButtonBox shows too many buttons"
|
||||
- #267 "Make drag'n'drop of top-level more intuitive"
|
||||
- #269 "Failed to display some element of a validated ui file"
|
||||
- #272 "Background of compositor does not change colors, when adwaita colors are changed"
|
||||
- #273 "GtkComboBoxText items gets their translatable property removed"
|
||||
|
||||
## 0.94.0
|
||||
|
||||
2024-11-25 - Accessibility release
|
||||
|
4
Makefile
4
Makefile
@ -1,7 +1,7 @@
|
||||
repo: ar.xjuan.Cambalache.json .git/objects
|
||||
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak install --noninteractive --user flathub org.gnome.Sdk//47
|
||||
flatpak install --noninteractive --user flathub org.gnome.Platform//47
|
||||
flatpak install --noninteractive --user flathub org.gnome.Sdk//48
|
||||
flatpak install --noninteractive --user flathub org.gnome.Platform//48
|
||||
flatpak-builder --force-clean --repo=repo build ar.xjuan.Cambalache.json
|
||||
|
||||
cambalache.flatpak: repo
|
||||
|
@ -152,7 +152,7 @@ cambalache under .local directoy and set up all environment variables needed to
|
||||
run the app from the source directory. (Follow manual installation to ensure
|
||||
you have everything needed)
|
||||
|
||||
`./run-dev.sh`
|
||||
`./run-dev.py`
|
||||
|
||||
This is meant for Cambalache development only.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"app-id" : "ar.xjuan.Cambalache",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "47",
|
||||
"runtime-version" : "48",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"separate-locales" : false,
|
||||
"command" : "cambalache",
|
||||
@ -34,8 +34,8 @@
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "file",
|
||||
"url" : "https://files.pythonhosted.org/packages/63/f7/ffbb6d2eb67b80a45b8a0834baa5557a14a5ffce0979439e7cd7f0c4055b/lxml-5.2.2.tar.gz",
|
||||
"sha256" : "bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"
|
||||
"url" : "https://files.pythonhosted.org/packages/80/61/d3dc048cd6c7be6fe45b80cedcbdd4326ba4d550375f266d9f4246d0f4bc/lxml-5.3.2.tar.gz",
|
||||
"sha256" : "773947d0ed809ddad824b7b14467e1a481b8976e87278ac4a730c2f7c7fcddc1"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -83,8 +83,8 @@
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/jpu/casilda.git",
|
||||
"tag" : "0.2.0",
|
||||
"commit" : "99a0173f21345b85713198c1fa1fbb388d00182f"
|
||||
"tag" : "0.9.0",
|
||||
"commit" : "4f7b1be321cf76832b12bda11fd91897257377e2"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -30,10 +30,12 @@ import builtins
|
||||
|
||||
from . import config
|
||||
|
||||
gi.require_version("GIRepository", "3.0")
|
||||
gi.require_version("Gdk", "4.0")
|
||||
gi.require_version("Gtk", "4.0")
|
||||
gi.require_version("GtkSource", "5")
|
||||
gi.require_version("WebKit", "6.0")
|
||||
gi.require_version('Adw', '1')
|
||||
|
||||
# Ensure _() builtin
|
||||
if "_" not in builtins.__dict__:
|
||||
@ -55,7 +57,7 @@ resource._register()
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_resource("/ar/xjuan/Cambalache/cambalache.css")
|
||||
display = Gdk.Display.get_default()
|
||||
Gtk.StyleContext.add_provider_for_display(display, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
Gtk.StyleContext.add_provider_for_display(display, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - 1)
|
||||
|
||||
# FIXME: this is needed in flatpak for icons to work
|
||||
Gtk.IconTheme.get_for_display(display).add_search_path("/app/share/icons")
|
||||
@ -78,6 +80,7 @@ from .cmb_objects_base import CmbBaseObject
|
||||
from .cmb_css import CmbCSS
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_gresource import CmbGResource
|
||||
|
||||
# from .cmb_object_data import CmbObjectData
|
||||
from .cmb_property import CmbProperty
|
||||
@ -88,12 +91,15 @@ from .cmb_project import CmbProject
|
||||
|
||||
from .cmb_db_inspector import CmbDBInspector
|
||||
from .cmb_view import CmbView
|
||||
from .cmb_column_view import CmbColumnView
|
||||
from .cmb_list_view import CmbListView
|
||||
from .cmb_notification import notification_center, CmbNotification, CmbNotificationCenter
|
||||
from .cmb_notification_list_view import CmbNotificationListView
|
||||
from .cmb_object_editor import CmbObjectEditor
|
||||
from .cmb_signal_editor import CmbSignalEditor
|
||||
from .cmb_ui_editor import CmbUIEditor
|
||||
from .cmb_ui_requires_editor import CmbUIRequiresEditor
|
||||
from .cmb_css_editor import CmbCSSEditor
|
||||
from .cmb_gresource_editor import CmbGResourceEditor
|
||||
from .cmb_fragment_editor import CmbFragmentEditor
|
||||
from .cmb_accessible_editor import CmbAccessibleEditor
|
||||
from .cmb_type_chooser import CmbTypeChooser
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<gresources>
|
||||
<gresource prefix="/ar/xjuan/Cambalache/app">
|
||||
<file>metainfo.xml</file>
|
||||
|
@ -38,7 +38,25 @@ window.cmb-window label.message {
|
||||
background-color: rgba(0, 0, 0, .6);
|
||||
}
|
||||
|
||||
window.cmb-window.dark label.message {
|
||||
window.cmb-window list.notifications {
|
||||
margin: 1em 2em;
|
||||
border-radius: 1em;
|
||||
border: 1px solid var(--secondary-sidebar-border-color);
|
||||
}
|
||||
|
||||
window.cmb-window list.notifications > row {
|
||||
padding: 1ex;
|
||||
}
|
||||
|
||||
window.cmb-window list.notifications > row:last-child {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
window.cmb-window list.notifications row > revealer > box > box:last-child {
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
window.cmb-window.dark .message {
|
||||
color: black;
|
||||
background-color: rgba(255, 255, 255, .6);
|
||||
}
|
||||
@ -95,6 +113,8 @@ CmbAccessibleEditor {
|
||||
}
|
||||
|
||||
CmbCSSEditor,
|
||||
CmbGResourceEditor,
|
||||
CmbGResourceFileEditor,
|
||||
stackswitcher.property-pane {
|
||||
padding: 4px;
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ class CmbApplication(Adw.Application):
|
||||
|
||||
self.add_main_option("version", b"v", GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _("Print version"), None)
|
||||
|
||||
self.add_main_option("export-all", b"E", GLib.OptionFlags.NONE, GLib.OptionArg.FILENAME, _("Export project"), None)
|
||||
self.add_main_option(
|
||||
"export-all", b"E", GLib.OptionFlags.NONE, GLib.OptionArg.FILENAME, _("Deprecated: Export project"), None
|
||||
)
|
||||
|
||||
def add_new_window(self):
|
||||
window = CmbWindow(application=self)
|
||||
@ -179,6 +181,10 @@ class CmbApplication(Adw.Application):
|
||||
def _on_open_activate(self, action, data):
|
||||
filename, target_tk = data.unpack()
|
||||
|
||||
# FIXME: use nullable parameter
|
||||
target_tk = target_tk if target_tk else None
|
||||
filename = filename if filename else None
|
||||
|
||||
window = self.props.active_window
|
||||
|
||||
if window and window.project is None:
|
||||
@ -190,7 +196,9 @@ class CmbApplication(Adw.Application):
|
||||
target_tk, filename, uipath = data.unpack()
|
||||
|
||||
# FIXME: use nullable parameter
|
||||
target_tk = target_tk if target_tk else None
|
||||
filename = filename if filename else None
|
||||
uipath = uipath if uipath else None
|
||||
|
||||
window = self.props.active_window
|
||||
|
||||
@ -245,10 +253,7 @@ class CmbApplication(Adw.Application):
|
||||
return 0
|
||||
|
||||
if options.contains("export-all"):
|
||||
filename = options.lookup_value("export-all")
|
||||
filename = "".join([chr(c) for c in filename.unpack()])
|
||||
project = CmbProject(filename=filename)
|
||||
project.export()
|
||||
print("Export has been deprecated and does nothing. Every UI file is updated on project save.")
|
||||
return 0
|
||||
|
||||
return -1
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_shortcuts.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
@ -15,32 +15,56 @@
|
||||
<property name="view">shortcuts</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>n</property>
|
||||
<property name="accelerator"><primary>n</property>
|
||||
<property name="title" translatable="yes">Create new project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>o</property>
|
||||
<property name="accelerator"><primary>o</property>
|
||||
<property name="title" translatable="yes">Open a project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>w</property>
|
||||
<property name="accelerator"><primary>i</property>
|
||||
<property name="title" translatable="yes">Import file</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><primary>s</property>
|
||||
<property name="title" translatable="yes">Save project</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><primary><shift>s</property>
|
||||
<property name="title" translatable="yes">Save project as</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><primary>w</property>
|
||||
<property name="title" translatable="yes">Close the project</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes">General</property>
|
||||
<property name="view">general</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>s</property>
|
||||
<property name="title" translatable="yes">Save the project</property>
|
||||
<property name="accelerator"><primary>question</property>
|
||||
<property name="title" translatable="yes">Keyboard Shortcuts</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>e</property>
|
||||
<property name="title" translatable="yes">Save and Export</property>
|
||||
<property name="accelerator"><primary>q</property>
|
||||
<property name="title" translatable="yes">Quit application</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -51,25 +75,31 @@
|
||||
<property name="view">shortcuts</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>Insert</property>
|
||||
<property name="accelerator">Delete</property>
|
||||
<property name="title" translatable="yes">Delete object</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><primary>Insert</property>
|
||||
<property name="title" translatable="yes">Add slot/column</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control>Delete</property>
|
||||
<property name="accelerator"><primary>Delete</property>
|
||||
<property name="title" translatable="yes">Remove slot/column</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control><shift>Insert</property>
|
||||
<property name="accelerator"><primary><shift>Insert</property>
|
||||
<property name="title" translatable="yes">Add row</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="accelerator"><Control><shift>Delete</property>
|
||||
<property name="accelerator"><primary><shift>Delete</property>
|
||||
<property name="title" translatable="yes">Remove row</property>
|
||||
</object>
|
||||
</child>
|
||||
|
@ -72,13 +72,6 @@ intro = [
|
||||
(_("Try adding a grid"), "intro_button", 3, "add-grid"),
|
||||
(_("and a button"), "intro_button", 3, "add-button"),
|
||||
(_("Quite easy! Isn't it?"), "intro_button", 3),
|
||||
(
|
||||
_("Once you finish, you can export all UI files to xml here"),
|
||||
_("Export all"),
|
||||
5,
|
||||
None,
|
||||
CmbTutorPosition.LEFT,
|
||||
),
|
||||
(
|
||||
_("If you have any question, contact us on Matrix!"),
|
||||
_("Contact"),
|
||||
|
@ -31,10 +31,28 @@ from gi.repository import GLib, GObject, Gio, Gdk, Gtk, Pango, Adw
|
||||
from .cmb_tutor import CmbTutor, CmbTutorState
|
||||
from . import cmb_tutorial
|
||||
|
||||
from cambalache import CmbProject, CmbUI, CmbCSS, CmbObject, CmbTypeChooserPopover, getLogger, config, utils, _
|
||||
from cambalache import (
|
||||
CmbProject,
|
||||
CmbUI,
|
||||
CmbCSS,
|
||||
CmbObject,
|
||||
CmbGResource,
|
||||
CmbGResourceEditor,
|
||||
CmbTypeChooserPopover,
|
||||
getLogger,
|
||||
notification_center,
|
||||
config,
|
||||
utils,
|
||||
_,
|
||||
N_
|
||||
)
|
||||
|
||||
from cambalache.cmb_blueprint import CmbBlueprintError
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
GObject.type_ensure(CmbGResourceEditor.__gtype__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/app/cmb_window.ui")
|
||||
class CmbWindow(Adw.ApplicationWindow):
|
||||
@ -46,8 +64,13 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
}
|
||||
|
||||
open_filter = Gtk.Template.Child()
|
||||
gtk3_import_filter = Gtk.Template.Child()
|
||||
gtk4_import_filter = Gtk.Template.Child()
|
||||
gtk4_filter = Gtk.Template.Child()
|
||||
gtk3_filter = Gtk.Template.Child()
|
||||
gtk_builder_filter = Gtk.Template.Child()
|
||||
blueprint_filter = Gtk.Template.Child()
|
||||
glade_filter = Gtk.Template.Child()
|
||||
css_filter = Gtk.Template.Child()
|
||||
gresource_filter = Gtk.Template.Child()
|
||||
|
||||
headerbar = Gtk.Template.Child()
|
||||
title = Gtk.Template.Child()
|
||||
@ -59,6 +82,9 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
# Start screen
|
||||
version_label = Gtk.Template.Child()
|
||||
front_notification_list_view = Gtk.Template.Child()
|
||||
notification_dialog = Gtk.Template.Child()
|
||||
notification_list_view = Gtk.Template.Child()
|
||||
|
||||
# New Project
|
||||
np_name_entry = Gtk.Template.Child()
|
||||
@ -73,8 +99,10 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
message_label = Gtk.Template.Child()
|
||||
|
||||
# Workspace
|
||||
workspace_stack = Gtk.Template.Child()
|
||||
view = Gtk.Template.Child()
|
||||
column_view = Gtk.Template.Child()
|
||||
source_view = Gtk.Template.Child()
|
||||
list_view = Gtk.Template.Child()
|
||||
type_chooser = Gtk.Template.Child()
|
||||
editor_stack = Gtk.Template.Child()
|
||||
ui_editor = Gtk.Template.Child()
|
||||
@ -86,6 +114,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
accessible_editor = Gtk.Template.Child()
|
||||
signal_editor = Gtk.Template.Child()
|
||||
css_editor = Gtk.Template.Child()
|
||||
gresource_editor = Gtk.Template.Child()
|
||||
|
||||
# Tutor widgets
|
||||
intro_button = Gtk.Template.Child()
|
||||
@ -98,7 +127,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
FULLSCREEN = 1 << 4
|
||||
|
||||
__portal_access_msg = _(
|
||||
"Cambalache will not have access to the file for export because it is outside of your home directory. "
|
||||
"Cambalache will not have access to the file for save because it is outside of your home directory. "
|
||||
"Consider using Flatseal or flatpak to give permissions to the host directory."
|
||||
)
|
||||
|
||||
@ -109,6 +138,21 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.gtk4_import_filters = Gio.ListStore()
|
||||
|
||||
for filter in [
|
||||
self.gtk4_filter,
|
||||
self.gtk_builder_filter,
|
||||
self.blueprint_filter,
|
||||
self.css_filter,
|
||||
self.gresource_filter
|
||||
]:
|
||||
self.gtk4_import_filters.append(filter)
|
||||
|
||||
self.gtk3_import_filters = Gio.ListStore()
|
||||
for filter in [self.gtk3_filter, self.gtk_builder_filter, self.glade_filter, self.css_filter, self.gresource_filter]:
|
||||
self.gtk3_import_filters.append(filter)
|
||||
|
||||
self.__recent_manager = self.__get_recent_manager()
|
||||
|
||||
self.editor_stack.set_size_request(420, -1)
|
||||
@ -118,6 +162,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
for action in [
|
||||
"about",
|
||||
"add_css",
|
||||
"add_gresource",
|
||||
"add_object",
|
||||
"add_object_toplevel",
|
||||
"add_placeholder",
|
||||
@ -132,12 +177,12 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
"debug",
|
||||
"delete",
|
||||
"donate",
|
||||
"export",
|
||||
"import",
|
||||
"inspect",
|
||||
"intro",
|
||||
"liberapay",
|
||||
"new",
|
||||
"notification",
|
||||
"open",
|
||||
"paste",
|
||||
"patreon",
|
||||
@ -178,7 +223,6 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
("win.save", ["<Primary>s"]),
|
||||
("win.save_as", ["<Shift><Primary>s"]),
|
||||
("win.import", ["<Primary>i"]),
|
||||
("win.export", ["<Primary>e"]),
|
||||
("win.close", ["<Primary>w"]),
|
||||
("win.undo", ["<Primary>z"]),
|
||||
("win.redo", ["<Primary><shift>z"]),
|
||||
@ -279,6 +323,10 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
self.__recent_manager.connect("changed", lambda rm: self.__update_recent_menu())
|
||||
self.__update_recent_menu()
|
||||
|
||||
self.notification_list_view.notification_center = notification_center
|
||||
self.front_notification_list_view.notification_center = notification_center
|
||||
notification_center.connect("new-notification", self.__on_new_notification)
|
||||
|
||||
def __get_recent_manager(self):
|
||||
# Load the user host recently used file
|
||||
if os.environ.get("container", None) == "flatpak":
|
||||
@ -301,12 +349,13 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
if self.__project:
|
||||
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_gresource_changed)
|
||||
self.__project.disconnect_by_func(self.__on_project_changed)
|
||||
|
||||
self.__project = project
|
||||
self.view.project = project
|
||||
self.type_chooser.project = project
|
||||
self.column_view.project = project
|
||||
self.list_view.project = project
|
||||
|
||||
# Clear Editors
|
||||
self.ui_editor.object = None
|
||||
@ -321,6 +370,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
if project:
|
||||
self.__project.connect("notify::filename", self.__on_project_filename_notify)
|
||||
self.__project.connect("selection-changed", self.__on_project_selection_changed)
|
||||
self.__project.connect("gresource-changed", self.__on_project_gresource_changed)
|
||||
self.__project.connect("changed", self.__on_project_changed)
|
||||
self.__on_project_selection_changed(project)
|
||||
|
||||
@ -403,20 +453,6 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
)
|
||||
popover.popup()
|
||||
|
||||
@Gtk.Template.Callback("on_ui_editor_remove_ui")
|
||||
def __on_ui_editor_remove_ui(self, editor, ui):
|
||||
self.__remove_object_with_confirmation(ui)
|
||||
|
||||
@Gtk.Template.Callback("on_ui_editor_export_ui")
|
||||
def __on_ui_editor_export_ui(self, editor, ui):
|
||||
if ui.export():
|
||||
self._show_message(_("File Exported"))
|
||||
|
||||
@Gtk.Template.Callback("on_css_editor_remove_ui")
|
||||
def __on_css_editor_remove_ui(self, editor):
|
||||
self.__remove_object_with_confirmation(editor.object)
|
||||
return True
|
||||
|
||||
def __on_focus_widget_notify(self, obj, pspec):
|
||||
widget = self.props.focus_widget
|
||||
|
||||
@ -436,6 +472,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
sensitive = len(editable.get_chars(0, -1)) != 0
|
||||
self.np_location_chooser.set_sensitive(sensitive)
|
||||
self.np_ui_entry.set_sensitive(sensitive)
|
||||
self.__update_action_new()
|
||||
|
||||
def __update_dark_mode(self, style_manager):
|
||||
if style_manager.props.dark:
|
||||
@ -506,26 +543,55 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
self.__update_action_undo_redo()
|
||||
self.__update_action_save()
|
||||
|
||||
def __update_gresource_view(self):
|
||||
if self.workspace_stack.get_visible_child_name() != "gresource":
|
||||
return
|
||||
|
||||
sel = self.project.get_selection()
|
||||
if len(sel) < 1:
|
||||
return
|
||||
|
||||
obj = sel[0]
|
||||
|
||||
if isinstance(obj, CmbGResource):
|
||||
gresource_id = obj.gresources_bundle.gresource_id
|
||||
resource_xml = self.project.db.gresource_tostring(gresource_id)
|
||||
else:
|
||||
resource_xml = ""
|
||||
|
||||
self.source_view.buffer.set_text(resource_xml)
|
||||
|
||||
def __on_project_gresource_changed(self, project, gresource, field):
|
||||
self.__update_gresource_view()
|
||||
|
||||
def __on_project_selection_changed(self, project):
|
||||
sel = project.get_selection()
|
||||
self.__update_action_clipboard()
|
||||
|
||||
obj = sel[0] if len(sel) > 0 else None
|
||||
|
||||
if type(obj) is CmbUI:
|
||||
if isinstance(obj, CmbUI):
|
||||
self.ui_editor.object = obj
|
||||
self.ui_requires_editor.object = obj
|
||||
self.ui_fragment_editor.object = obj
|
||||
self.workspace_stack.set_visible_child_name("ui")
|
||||
self.editor_stack.set_visible_child_name("ui")
|
||||
obj = None
|
||||
elif type(obj) is CmbObject:
|
||||
elif isinstance(obj, CmbObject):
|
||||
self.workspace_stack.set_visible_child_name("ui")
|
||||
self.editor_stack.set_visible_child_name("object")
|
||||
if obj:
|
||||
self.__user_message_by_type(obj.info)
|
||||
elif type(obj) is CmbCSS:
|
||||
elif isinstance(obj, CmbCSS):
|
||||
self.css_editor.object = obj
|
||||
self.editor_stack.set_visible_child_name("css")
|
||||
obj = None
|
||||
elif isinstance(obj, CmbGResource):
|
||||
self.gresource_editor.object = obj
|
||||
self.workspace_stack.set_visible_child_name("gresource")
|
||||
self.editor_stack.set_visible_child_name("gresource")
|
||||
self.__update_gresource_view()
|
||||
obj = None
|
||||
|
||||
self.object_editor.object = obj
|
||||
|
||||
@ -546,6 +612,9 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
self.intro_button.set_visible(enabled)
|
||||
|
||||
def __update_action_notification(self):
|
||||
self.actions["notification"].set_enabled(len(notification_center.store) > 0)
|
||||
|
||||
def __update_action_add_object(self):
|
||||
has_project = self.__is_project_visible()
|
||||
has_selection = True if self.project and len(self.project.get_selection()) > 0 else False
|
||||
@ -586,24 +655,39 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
else:
|
||||
self.title.remove_css_class("changed")
|
||||
|
||||
def __update_action_new(self):
|
||||
self.actions["new"].set_enabled(len(self.np_name_entry.props.text) > 0)
|
||||
|
||||
def __update_actions(self):
|
||||
has_project = self.__is_project_visible()
|
||||
|
||||
for action in ["save_as", "add_ui", "add_css", "delete", "import", "export", "close", "debug"]:
|
||||
for action in [
|
||||
"save_as",
|
||||
"add_ui",
|
||||
"add_css",
|
||||
"add_gresource",
|
||||
"delete",
|
||||
"import",
|
||||
"close",
|
||||
"debug"
|
||||
]:
|
||||
self.actions[action].set_enabled(has_project)
|
||||
|
||||
self.__update_action_new()
|
||||
self.__update_action_save()
|
||||
self.__update_action_intro()
|
||||
self.__update_action_notification()
|
||||
self.__update_action_clipboard()
|
||||
self.__update_action_undo_redo()
|
||||
self.__update_action_add_object()
|
||||
self.__update_action_remove_parent()
|
||||
|
||||
def __file_open_dialog_new(self, title, filter_obj=None, accept_label=None, use_project_dir=False):
|
||||
def __file_open_dialog_new(self, title, filter_obj=None, accept_label=None, use_project_dir=False, filters=None):
|
||||
dialog = Gtk.FileDialog(
|
||||
modal=True,
|
||||
title=title,
|
||||
default_filter=filter_obj,
|
||||
filters=filters,
|
||||
accept_label=accept_label,
|
||||
)
|
||||
|
||||
@ -654,9 +738,13 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
basename = os.path.basename(filename)
|
||||
name, ext = os.path.splitext(basename)
|
||||
|
||||
if target_tk is None:
|
||||
if not target_tk:
|
||||
target_tk = CmbProject.get_target_from_ui_file(filename)
|
||||
|
||||
if not target_tk:
|
||||
self.ask_gtk_version(filename)
|
||||
return
|
||||
|
||||
self.project = CmbProject(filename=os.path.join(dirname, f"{name}.cmb"), target_tk=target_tk)
|
||||
self.__set_page("workspace")
|
||||
self.__update_actions()
|
||||
@ -693,14 +781,14 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
first_msg = _("Cambalache encounter the following issues:")
|
||||
|
||||
# Translators: this is the last message after the list of unsupported features
|
||||
last_msg = _("Your file will be exported as '{name}.cmb.ui' to avoid data loss.").format(name=name)
|
||||
last_msg = _("Your file will be saved as '{name}.cmb.ui' to avoid data loss.").format(name=name)
|
||||
|
||||
unsupported_features_list = [first_msg] + list + [last_msg]
|
||||
else:
|
||||
unsupported_feature = msg[0]
|
||||
text = _(
|
||||
"Cambalache encounter {unsupported_feature}\n"
|
||||
"Your file will be exported as '{name}.cmb.ui' to avoid data loss."
|
||||
"Your file will be saved as '{name}.cmb.ui' to avoid data loss."
|
||||
).format(unsupported_feature=unsupported_feature, name=name)
|
||||
|
||||
self.present_message_to_user(
|
||||
@ -864,7 +952,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
else:
|
||||
self.project.redo()
|
||||
except Exception as e:
|
||||
logger.warning(f"Undo/Redo error", exc_info=True)
|
||||
logger.warning("Undo/Redo error", exc_info=True)
|
||||
self.present_message_to_user(
|
||||
_("Undo/Redo stack got corrupted"),
|
||||
secondary_text=_("Please try to reproduce and file an issue\n Error: {msg}").format(msg=str(e))
|
||||
@ -937,10 +1025,12 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
def on_dialog_response(dialog, response):
|
||||
if response == Gtk.ResponseType.YES:
|
||||
if type(obj) is CmbUI:
|
||||
if isinstance(obj, CmbUI):
|
||||
self.project.remove_ui(obj)
|
||||
elif type(obj) is CmbCSS:
|
||||
elif isinstance(obj, CmbCSS):
|
||||
self.project.remove_css(obj)
|
||||
elif isinstance(obj, CmbGResource):
|
||||
self.project.remove_gresource(obj)
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
@ -968,10 +1058,18 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
selection = self.project.get_selection()
|
||||
for obj in selection:
|
||||
if type(obj) is CmbObject:
|
||||
try:
|
||||
if isinstance(obj, CmbObject):
|
||||
self.project.remove_object(obj)
|
||||
elif isinstance(obj, CmbGResource):
|
||||
if obj.resource_type == "gresources":
|
||||
self.__remove_object_with_confirmation(obj)
|
||||
else:
|
||||
self.project.remove_gresource(obj)
|
||||
else:
|
||||
self.__remove_object_with_confirmation(obj)
|
||||
except Exception as e:
|
||||
self.present_message_to_user(_("Error deleting {name}").format(name=obj.display_name_type), secondary_text=str(e))
|
||||
|
||||
def _on_add_object_activate(self, action, data):
|
||||
info = self.type_chooser.props.selected_type
|
||||
@ -1020,13 +1118,13 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
first_msg = _("Cambalache encounter the following issues:")
|
||||
|
||||
# Translators: this is the last message after the list of unsupported features
|
||||
last_msg = _("Your file will be exported as '{name}.cmb.ui' to avoid data loss.").format(name=name)
|
||||
last_msg = _("Your file will be saved as '{name}.cmb.ui' to avoid data loss.").format(name=name)
|
||||
|
||||
unsupported_features_list = [first_msg] + list + [last_msg]
|
||||
else:
|
||||
unsupported_feature = msg[0]
|
||||
text = _(
|
||||
"Cambalache encounter {unsupported_feature}\nYour file will be exported as '{name}.cmb.ui' to avoid data loss."
|
||||
"Cambalache encounter {unsupported_feature}\nYour file will be saved as '{name}.cmb.ui' to avoid data loss."
|
||||
).format(unsupported_feature=unsupported_feature, name=name)
|
||||
|
||||
self.present_message_to_user(
|
||||
@ -1042,24 +1140,56 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
def dialog_callback(dialog, res):
|
||||
try:
|
||||
for file in dialog.open_multiple_finish(res):
|
||||
path = file.get_path()
|
||||
content_type = utils.content_type_guess(path)
|
||||
|
||||
print("IMPORT", path, content_type)
|
||||
|
||||
if content_type in ["application/x-gtk-builder", "application/x-glade", "text/x-blueprint"]:
|
||||
self.import_file(file.get_path())
|
||||
elif content_type == "text/css":
|
||||
self.project.add_css(path)
|
||||
elif content_type == "application/xml" and path.endswith("gresource.xml"):
|
||||
self.project.import_gresource(path)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error {e}")
|
||||
|
||||
if self.project.target_tk == "gtk-4.0":
|
||||
import_filter = self.gtk4_import_filter
|
||||
import_filters = self.gtk4_import_filters
|
||||
else:
|
||||
import_filter = self.gtk3_import_filter
|
||||
import_filters = self.gtk3_import_filters
|
||||
|
||||
dialog = self.__file_open_dialog_new(
|
||||
_("Choose file to import"),
|
||||
filter_obj=import_filter,
|
||||
filters=import_filters,
|
||||
accept_label=_("Import")
|
||||
)
|
||||
dialog.open_multiple(self, None, dialog_callback)
|
||||
|
||||
def _on_add_gresource_activate(self, action, data):
|
||||
if self.project is None:
|
||||
return
|
||||
|
||||
gresource = self.project.add_gresource("gresources")
|
||||
self.project.set_selection([gresource])
|
||||
|
||||
def __save(self):
|
||||
if self.project.save():
|
||||
retval = False
|
||||
|
||||
try :
|
||||
retval = self.project.save()
|
||||
except CmbBlueprintError as e:
|
||||
self.present_message_to_user(
|
||||
_("Error saving project"),
|
||||
secondary_text=N_(
|
||||
"blueprintcompiler encounter the following error:",
|
||||
"blueprintcompiler encounter the following errors:",
|
||||
len(e.errors)
|
||||
),
|
||||
details=[str(e)]
|
||||
)
|
||||
finally:
|
||||
if retval:
|
||||
self.__last_saved_index = self.project.history_index
|
||||
self.__update_action_save()
|
||||
self.emit("project-saved", self.project)
|
||||
@ -1078,16 +1208,6 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
|
||||
return False
|
||||
|
||||
def _on_export_activate(self, action, data):
|
||||
if self.project is None:
|
||||
return
|
||||
|
||||
self.save_project()
|
||||
|
||||
n = self.project.export()
|
||||
|
||||
self._show_message(_("{n} files exported").format(n=n) if n > 1 else _("File exported"))
|
||||
|
||||
def _close_project_dialog_new(self):
|
||||
text = _("Save changes before closing?")
|
||||
dialog = Gtk.MessageDialog(
|
||||
@ -1187,20 +1307,19 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
about.props.translator_credits = "\n".join(translator_list)
|
||||
|
||||
def _on_about_activate(self, action, data):
|
||||
about = Adw.AboutWindow.new_from_appdata("/ar/xjuan/Cambalache/app/metainfo.xml", config.VERSION)
|
||||
about = Adw.AboutDialog.new_from_appdata("/ar/xjuan/Cambalache/app/metainfo.xml", config.VERSION)
|
||||
|
||||
about.props.transient_for = self
|
||||
about.props.artists = [
|
||||
"Franco Dodorico",
|
||||
"Juan Pablo Ugarte",
|
||||
]
|
||||
about.props.copyright = "© 2020-2024 Juan Pablo Ugarte"
|
||||
about.props.copyright = "© 2020-2025 Juan Pablo Ugarte"
|
||||
about.props.license_type = Gtk.License.LGPL_2_1_ONLY
|
||||
|
||||
self.__update_translators(about)
|
||||
self.__populate_supporters(about)
|
||||
|
||||
about.present()
|
||||
about.present(self)
|
||||
|
||||
def _on_add_parent_activate(self, action, data):
|
||||
obj = self.project.get_selection()[0]
|
||||
@ -1295,7 +1414,7 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
elif node in ["add-ui", "add-window", "add-grid", "add-button"]:
|
||||
self.tutor_waiting_for_user_action = True
|
||||
self.tutor.pause()
|
||||
elif node in ["donate", "export_all"]:
|
||||
elif node in ["donate"]:
|
||||
self.menu_button.popdown()
|
||||
elif node == "show-type-popover":
|
||||
widget.props.popover.popdown()
|
||||
@ -1424,4 +1543,13 @@ class CmbWindow(Adw.ApplicationWindow):
|
||||
else:
|
||||
self.message_revealer.props.reveal_child = False
|
||||
|
||||
def __notification_present(self):
|
||||
if self.stack.get_visible_child_name() != "cambalache":
|
||||
self.notification_dialog.present(self)
|
||||
|
||||
def _on_notification_activate(self, action, data):
|
||||
self.__notification_present()
|
||||
|
||||
def __on_new_notification(self, center, notification):
|
||||
self.__notification_present()
|
||||
self.__update_action_notification()
|
||||
|
@ -1,41 +1,45 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.93.0 -->
|
||||
<!-- Created with Cambalache 0.97.1 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_window.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
<requires lib="gio" version="2.0"/>
|
||||
<requires lib="gtk" version="4.14"/>
|
||||
<requires lib="libadwaita" version="1.5"/>
|
||||
<object class="GtkFileFilter" id="gtk4_import_filter">
|
||||
<property name="mime-types">application/x-gtk-builder</property>
|
||||
</object>
|
||||
<menu id="main_menu">
|
||||
<item>
|
||||
<attribute name="action">win.create_new</attribute>
|
||||
<attribute name="label">New Project</attribute>
|
||||
<attribute name="label" translatable="yes">New Project</attribute>
|
||||
</item>
|
||||
<section>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">Add file</attribute>
|
||||
<item>
|
||||
<attribute name="action">win.import</attribute>
|
||||
<attribute name="label" translatable="yes">Import UI</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.export</attribute>
|
||||
<attribute name="label" translatable="yes">Export all UI</attribute>
|
||||
<attribute name="action">win.add_ui</attribute>
|
||||
<attribute name="label" translatable="yes">Add UI</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.add_css</attribute>
|
||||
<attribute name="label" translatable="yes">Add CSS file</attribute>
|
||||
<attribute name="label" translatable="yes">Add CSS</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.add_gresource</attribute>
|
||||
<attribute name="label" translatable="yes">Add GResource</attribute>
|
||||
</item>
|
||||
</submenu>
|
||||
<item>
|
||||
<attribute name="action">win.import</attribute>
|
||||
<attribute name="label" translatable="yes">Import file</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="action">win.save</attribute>
|
||||
<attribute name="label">Save</attribute>
|
||||
<attribute name="label" translatable="yes">Save</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.save_as</attribute>
|
||||
<attribute name="label">Save As</attribute>
|
||||
<attribute name="label" translatable="yes">Save As</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.close</attribute>
|
||||
@ -47,6 +51,10 @@
|
||||
<attribute name="action">win.intro</attribute>
|
||||
<attribute name="label" translatable="yes">Interactive intro</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.notification</attribute>
|
||||
<attribute name="label" translatable="yes">Notifications</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.contact</attribute>
|
||||
<attribute name="label" translatable="yes">Contact</attribute>
|
||||
@ -88,7 +96,7 @@
|
||||
<object class="AdwSplitButton" id="open_button">
|
||||
<property name="action-name">win.open</property>
|
||||
<property name="dropdown-tooltip">Recent Projects</property>
|
||||
<property name="label">_Open</property>
|
||||
<property name="label" translatable="yes">_Open</property>
|
||||
<property name="menu-model">recent_menu</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
@ -169,13 +177,19 @@
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="CmbNotificationListView" id="front_notification_list_view">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="version_label">
|
||||
<property name="halign">center</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="name">version</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="vexpand">1</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="9000"/>
|
||||
</attributes>
|
||||
@ -245,7 +259,7 @@
|
||||
<child>
|
||||
<object class="GtkEntry" id="np_name_entry">
|
||||
<property name="focusable">1</property>
|
||||
<property name="input-hints">GTK_INPUT_HINT_LOWERCASE | GTK_INPUT_HINT_NONE</property>
|
||||
<property name="input-hints">lowercase|none</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<property name="placeholder-text" translatable="yes"><project basename></property>
|
||||
<property name="width-chars">32</property>
|
||||
@ -395,7 +409,7 @@
|
||||
<child>
|
||||
<object class="GtkEntry" id="np_ui_entry">
|
||||
<property name="focusable">1</property>
|
||||
<property name="input-hints">GTK_INPUT_HINT_LOWERCASE | GTK_INPUT_HINT_NONE</property>
|
||||
<property name="input-hints">lowercase|none</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<property name="sensitive">0</property>
|
||||
<property name="width-chars">32</property>
|
||||
@ -534,8 +548,6 @@
|
||||
<object class="CmbUIEditor" id="ui_editor">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<signal name="remove-ui" handler="on_ui_editor_remove_ui"/>
|
||||
<signal name="export-ui" handler="on_ui_editor_export_ui"/>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">properties</property>
|
||||
@ -578,13 +590,21 @@
|
||||
<object class="CmbCSSEditor" id="css_editor">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<signal name="remove-css" handler="on_css_editor_remove_ui"/>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">css</property>
|
||||
<property name="title" translatable="yes">CSS Editor</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="CmbGResourceEditor" id="gresource_editor"/>
|
||||
</property>
|
||||
<property name="name">gresource</property>
|
||||
<property name="title">GResource Editor</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="focusable">1</property>
|
||||
@ -595,11 +615,16 @@
|
||||
<property name="start-child">
|
||||
<object class="GtkPaned">
|
||||
<property name="end-child">
|
||||
<object class="GtkStack" id="workspace_stack">
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="CmbTypeChooser" id="type_chooser">
|
||||
<property name="spacing">2</property>
|
||||
<property name="valign">start</property>
|
||||
<signal name="chooser-popdown" handler="on_type_chooser_chooser_popdown"/>
|
||||
<signal name="chooser-popup" handler="on_type_chooser_chooser_popup"/>
|
||||
<signal name="type-selected" handler="on_type_chooser_type_selected"/>
|
||||
@ -614,6 +639,26 @@
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">ui</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="child">
|
||||
<object class="CmbSourceView" id="source_view">
|
||||
<property name="editable">False</property>
|
||||
<property name="lang">xml</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">gresource</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="focusable">1</property>
|
||||
<property name="resize-start-child">0</property>
|
||||
<property name="shrink-end-child">0</property>
|
||||
@ -627,7 +672,7 @@
|
||||
<property name="propagate-natural-height">True</property>
|
||||
<property name="propagate-natural-width">True</property>
|
||||
<child>
|
||||
<object class="CmbColumnView" id="column_view"/>
|
||||
<object class="CmbListView" id="list_view"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
@ -774,9 +819,7 @@
|
||||
<property name="halign">center</property>
|
||||
<property name="transition-type">slide-up</property>
|
||||
<property name="valign">end</property>
|
||||
<style>
|
||||
<class name="message"/>
|
||||
</style>
|
||||
<style/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -787,8 +830,48 @@
|
||||
<class name="cmb-window"/>
|
||||
</style>
|
||||
</template>
|
||||
<object class="GtkFileFilter" id="gtk3_import_filter">
|
||||
<object class="GtkFileFilter" id="gtk_builder_filter">
|
||||
<property name="mime-types">application/x-gtk-builder</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="glade_filter">
|
||||
<property name="mime-types">application/x-glade</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="blueprint_filter">
|
||||
<property name="mime-types">text/x-blueprint</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="css_filter">
|
||||
<property name="mime-types">text/css</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="gresource_filter">
|
||||
<property name="suffixes">gresource.xml</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="gtk4_filter">
|
||||
<property name="mime-types">application/x-gtk-builder
|
||||
application/x-glade</property>
|
||||
text/x-blueprint
|
||||
text/css</property>
|
||||
<property name="name">All supported files</property>
|
||||
<property name="suffixes">gresource.xml</property>
|
||||
</object>
|
||||
<object class="GtkFileFilter" id="gtk3_filter">
|
||||
<property name="mime-types">application/x-gtk-builder
|
||||
application/x-glade
|
||||
text/css</property>
|
||||
<property name="name">All supported files</property>
|
||||
<property name="suffixes">gresource.xml</property>
|
||||
</object>
|
||||
<object class="AdwDialog" id="notification_dialog">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="AdwHeaderBar"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbNotificationListView" id="notification_list_view"/>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="follows-content-size">True</property>
|
||||
<property name="title" translatable="yes">Notifications</property>
|
||||
</object>
|
||||
</interface>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,8 @@ CmbPropertyLabel.hidden:hover > box > image {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
popover.cmb-binding-popover button.close {
|
||||
popover.cmb-binding-popover button.close,
|
||||
list.notifications button.close {
|
||||
padding: unset;
|
||||
margin: unset;
|
||||
border: unset;
|
||||
@ -84,10 +85,47 @@ CmbPropertyLabel.warning > box > label {
|
||||
text-decoration: underline wavy @warning_color;
|
||||
}
|
||||
|
||||
row.drop-before:drop(active) {
|
||||
box-shadow: 0px 1px 0px @theme_selected_bg_color inset;
|
||||
listview.cmb-list-view {
|
||||
background-color: @theme_bg_color;
|
||||
}
|
||||
|
||||
row.drop-after:drop(active) {
|
||||
box-shadow: 0px -1px 0px @theme_selected_bg_color inset;
|
||||
listview.cmb-list-view > row {
|
||||
padding: 2px 8px;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row:drop(active):not(.drop-after):not(.drop-before) {
|
||||
outline: 2px solid color-mix(in srgb, @theme_bg_color 80%, black);
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row.drop-before:drop(active) {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
border-top: 2px solid color-mix(in srgb, @theme_bg_color 80%, black);
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row.drop-after:drop(active) {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
border-bottom: 2px solid color-mix(in srgb, @theme_bg_color 80%, black);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row > treeexpander.cmb-path > expander {
|
||||
-gtk-icon-source: -gtk-icontheme("folder-symbolic");
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row > treeexpander.cmb-path > expander:checked {
|
||||
-gtk-icon-source: -gtk-icontheme("folder-open-symbolic");
|
||||
}
|
||||
|
||||
listview.cmb-list-view > row > treeexpander.cmb-unsaved-path > expander {
|
||||
-gtk-icon-source: -gtk-icontheme("view-list-symbolic");
|
||||
}
|
||||
|
||||
button.compact {
|
||||
padding: 2px 4px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -1,22 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<gresources>
|
||||
<gresource prefix="/ar/xjuan/Cambalache">
|
||||
<file>control/cmb_translatable_widget.ui</file>
|
||||
<file>db/cmb_base.sql</file>
|
||||
<file>db/cmb_project.sql</file>
|
||||
<file>db/cmb_history.sql</file>
|
||||
<file>cmb_view.ui</file>
|
||||
<file>cambalache.css</file>
|
||||
<file>cmb_context_menu.ui</file>
|
||||
<file>cmb_css_editor.ui</file>
|
||||
<file>cmb_db_inspector.ui</file>
|
||||
<file>cmb_fragment_editor.ui</file>
|
||||
<file>cmb_gresource_editor.ui</file>
|
||||
<file>cmb_notification_list_view.ui</file>
|
||||
<file>cmb_version_notification_view.ui</file>
|
||||
<file>cmb_message_notification_view.ui</file>
|
||||
<file>cmb_poll_option_check.ui</file>
|
||||
<file>cmb_poll_notification_view.ui</file>
|
||||
<file>cmb_object_data_editor.ui</file>
|
||||
<file>cmb_signal_editor.ui</file>
|
||||
<file>cmb_type_chooser.ui</file>
|
||||
<file>cmb_type_chooser_widget.ui</file>
|
||||
<file>cmb_ui_editor.ui</file>
|
||||
<file>cmb_css_editor.ui</file>
|
||||
<file>cmb_fragment_editor.ui</file>
|
||||
<file>cmb_object_data_editor.ui</file>
|
||||
<file>cmb_signal_editor.ui</file>
|
||||
<file>cmb_db_inspector.ui</file>
|
||||
<file>cambalache.css</file>
|
||||
<file>icons/scalable/actions/bind-symbolic.svg</file>
|
||||
<file>cmb_view.ui</file>
|
||||
<file>control/cmb_file_button.ui</file>
|
||||
<file>control/cmb_translatable_widget.ui</file>
|
||||
<file>db/cmb_base.sql</file>
|
||||
<file>db/cmb_history.sql</file>
|
||||
<file>db/cmb_project.sql</file>
|
||||
<file>icons/scalable/actions/binded-symbolic.svg</file>
|
||||
<file>icons/scalable/actions/bind-symbolic.svg</file>
|
||||
<file>cmb_notification_list_row.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
86
cambalache/cmb_blueprint.py
Normal file
86
cambalache/cmb_blueprint.py
Normal file
@ -0,0 +1,86 @@
|
||||
#
|
||||
# Blueprint compiler integration functions
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import io
|
||||
|
||||
try:
|
||||
import blueprintcompiler as bp
|
||||
from blueprintcompiler import parser, tokenizer
|
||||
from blueprintcompiler.decompiler import decompile_string
|
||||
from blueprintcompiler.outputs import XmlOutput
|
||||
except Exception:
|
||||
bp = None
|
||||
|
||||
|
||||
class CmbBlueprintError(Exception):
|
||||
def __init__(self, message, errors=[]):
|
||||
super().__init__(message)
|
||||
self.errors = errors
|
||||
|
||||
|
||||
class CmbBlueprintUnsupportedError(CmbBlueprintError):
|
||||
pass
|
||||
|
||||
|
||||
class CmbBlueprintMissingError(CmbBlueprintError):
|
||||
def __init__(self):
|
||||
super().__init__("blueprintcompiler is not available")
|
||||
|
||||
|
||||
def cmb_blueprint_decompile(data: str) -> str:
|
||||
if bp is None:
|
||||
raise CmbBlueprintMissingError()
|
||||
|
||||
try:
|
||||
retval = decompile_string(data)
|
||||
except bp.decompiler.UnsupportedError as e:
|
||||
raise CmbBlueprintUnsupportedError(str(e))
|
||||
except Exception as e:
|
||||
raise CmbBlueprintError(str(e))
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def cmb_blueprint_compile(data: str) -> str:
|
||||
if bp is None:
|
||||
raise CmbBlueprintMissingError()
|
||||
|
||||
tokens = tokenizer.tokenize(data)
|
||||
ast, errors, warnings = parser.parse(tokens)
|
||||
|
||||
if errors:
|
||||
f = io.StringIO("")
|
||||
errors.pretty_print("temp", data, f)
|
||||
f.seek(0)
|
||||
raise CmbBlueprintError(f.read(), errors=errors)
|
||||
|
||||
if ast is None:
|
||||
raise CmbBlueprintError("AST is None")
|
||||
|
||||
# Ignore warnings
|
||||
|
||||
retval = XmlOutput().emit(ast)
|
||||
return retval.encode()
|
||||
|
@ -1,524 +0,0 @@
|
||||
#
|
||||
# CmbColumnView
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gdk, Gtk
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_context_menu import CmbContextMenu
|
||||
from .cmb_project import CmbProject
|
||||
from cambalache import _
|
||||
|
||||
|
||||
class CmbColumnView(Gtk.ColumnView):
|
||||
__gtype_name__ = "CmbColumnView"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__project = None
|
||||
self.__tree_model = None
|
||||
self.__in_selection_change = False
|
||||
self.single_selection = Gtk.SingleSelection()
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.props.has_tooltip = True
|
||||
self.props.hexpand = True
|
||||
self.props.show_row_separators = False
|
||||
self.props.show_column_separators = False
|
||||
self.props.reorderable = False
|
||||
|
||||
self.__add_column("display-name")
|
||||
self.single_selection.connect("notify::selected-item", self.__on_selected_item_notify)
|
||||
self.set_model(self.single_selection)
|
||||
|
||||
gesture = Gtk.GestureClick(button=Gdk.BUTTON_SECONDARY)
|
||||
gesture.connect("pressed", self.__on_button_press)
|
||||
self.add_controller(gesture)
|
||||
|
||||
self.connect("activate", self.__on_activate)
|
||||
|
||||
def __add_column(self, property_id):
|
||||
factory = Gtk.SignalListItemFactory()
|
||||
factory.connect("setup", self._on_factory_setup)
|
||||
factory.connect("bind", self._on_factory_bind, property_id)
|
||||
factory.connect("unbind", self._on_factory_unbind)
|
||||
|
||||
column = Gtk.ColumnViewColumn(factory=factory, expand=True)
|
||||
self.append_column(column)
|
||||
|
||||
# FIXME: Add api to Gtk to hide column title widget
|
||||
column_view = column.get_column_view()
|
||||
child = column_view.get_first_child()
|
||||
if GObject.type_name(child.__gtype__) == "GtkColumnViewRowWidget":
|
||||
child.set_visible(False)
|
||||
|
||||
def __on_button_press(self, gesture, npress, x, y):
|
||||
expander = self.__get_tree_expander(x, y)
|
||||
|
||||
if expander is None or npress != 1:
|
||||
return False
|
||||
|
||||
# Select row at x,y
|
||||
list_row = expander.get_list_row()
|
||||
self.single_selection.set_selected(list_row.get_position())
|
||||
|
||||
menu = CmbContextMenu()
|
||||
|
||||
if self.__project:
|
||||
menu.target_tk = self.__project.target_tk
|
||||
|
||||
menu.set_parent(self)
|
||||
menu.popup_at(x, y)
|
||||
return True
|
||||
|
||||
def __get_object_ancestors(self, obj):
|
||||
if isinstance(obj, CmbObject):
|
||||
ancestors = {obj.ui}
|
||||
parent = obj.parent
|
||||
while parent:
|
||||
ancestors.add(parent)
|
||||
parent = parent.parent
|
||||
|
||||
return ancestors
|
||||
|
||||
# CmbUI and CmbCSS do not have ancestors
|
||||
return {}
|
||||
|
||||
def __object_ancestor_expand(self, obj):
|
||||
ancestors = self.__get_object_ancestors(obj)
|
||||
i = 0
|
||||
|
||||
# Iterate over tree model
|
||||
# NOTE: only visible/expanded rows are returned
|
||||
list_row = self.__tree_model.get_row(i)
|
||||
while list_row:
|
||||
item = list_row.get_item()
|
||||
|
||||
# Return position if we reached the object row
|
||||
if item == obj:
|
||||
return i
|
||||
elif item in ancestors:
|
||||
# Expand row if its part of the hierarchy
|
||||
list_row.set_expanded(True)
|
||||
|
||||
i += 1
|
||||
list_row = self.__tree_model.get_row(i)
|
||||
|
||||
return None
|
||||
|
||||
def __on_project_selection_changed(self, p):
|
||||
list_row = self.single_selection.get_selected_item()
|
||||
current_selection = [list_row.get_item()] if list_row else []
|
||||
selection = self.__project.get_selection()
|
||||
|
||||
if selection == current_selection:
|
||||
return
|
||||
|
||||
self.__in_selection_change = True
|
||||
|
||||
if len(selection) > 0:
|
||||
position = self.__object_ancestor_expand(selection[0])
|
||||
if position is not None:
|
||||
self.single_selection.select_item(position, True)
|
||||
else:
|
||||
self.single_selection.unselect_all()
|
||||
else:
|
||||
self.single_selection.unselect_all()
|
||||
|
||||
self.__in_selection_change = False
|
||||
|
||||
@GObject.Property(type=CmbProject)
|
||||
def project(self):
|
||||
return self.__project
|
||||
|
||||
@project.setter
|
||||
def _set_project(self, project):
|
||||
if self.__project:
|
||||
self.__project.disconnect_by_func(self.__on_project_selection_changed)
|
||||
|
||||
self.__project = project
|
||||
|
||||
if project:
|
||||
self.__tree_model = Gtk.TreeListModel.new(
|
||||
project,
|
||||
False,
|
||||
False,
|
||||
self.__tree_model_create_func,
|
||||
None
|
||||
)
|
||||
self.single_selection.props.model = self.__tree_model
|
||||
self.__project.connect("selection-changed", self.__on_project_selection_changed)
|
||||
else:
|
||||
self.single_selection.props.model = None
|
||||
|
||||
def __tree_model_create_func(self, item, data):
|
||||
if isinstance(item, CmbObject):
|
||||
return item
|
||||
elif isinstance(item, CmbUI):
|
||||
return item
|
||||
|
||||
return None
|
||||
|
||||
def __on_selected_item_notify(self, single_selection, pspec):
|
||||
if self.__in_selection_change or self.__project is None:
|
||||
return
|
||||
|
||||
list_item = single_selection.get_selected_item()
|
||||
|
||||
if list_item:
|
||||
item = list_item.get_item()
|
||||
self.__project.set_selection([item])
|
||||
else:
|
||||
self.__project.set_selection([])
|
||||
|
||||
def __on_item_notify(self, item, pspec, label):
|
||||
self.__update_label(item, label, pspec.name)
|
||||
|
||||
def __update_label(self, item, label, property_id):
|
||||
val = str(item.get_property(property_id))
|
||||
label.set_markup(val if val else "")
|
||||
|
||||
def _on_factory_setup(self, factory, list_item):
|
||||
expander = Gtk.TreeExpander()
|
||||
label = Gtk.Inscription(hexpand=True)
|
||||
expander.set_child(label)
|
||||
list_item.set_child(expander)
|
||||
|
||||
def __on_list_store_n_items_notify(self, list_store, pspec, expander):
|
||||
expander.props.hide_expander = list_store.props.n_items == 0
|
||||
|
||||
def __drop_target_new(self):
|
||||
drop_target = Gtk.DropTarget.new(
|
||||
type=GObject.TYPE_NONE, actions=Gdk.DragAction.COPY
|
||||
)
|
||||
drop_target.set_gtypes([CmbObject, CmbUI])
|
||||
|
||||
return drop_target
|
||||
|
||||
def _on_factory_bind(self, factory, list_item, property_id):
|
||||
row = list_item.get_item()
|
||||
expander = list_item.get_child()
|
||||
row_widget = expander.props.parent.props.parent
|
||||
expander.set_list_row(row)
|
||||
item = row.get_item()
|
||||
label = expander.get_child()
|
||||
|
||||
# ensure drag&drop variables
|
||||
row_widget._drop_target = None
|
||||
row_widget._drag_source = None
|
||||
expander._drop_target = None
|
||||
|
||||
# Handle label
|
||||
self.__update_label(item, label, property_id)
|
||||
item.connect(f"notify::{property_id}", self.__on_item_notify, label)
|
||||
|
||||
# Add controllers and drag sources
|
||||
if isinstance(item, CmbObject):
|
||||
# Drag source, only objects can be dragged
|
||||
drag_source = Gtk.DragSource()
|
||||
drag_source.connect("prepare", self.__on_drag_prepare)
|
||||
drag_source.connect("drag-begin", self.__on_drag_begin)
|
||||
row_widget.add_controller(drag_source)
|
||||
row_widget._drag_source = drag_source
|
||||
|
||||
# Expander Drop target
|
||||
drop_target = self.__drop_target_new()
|
||||
drop_target.connect("accept", self.__on_expander_drop_accept)
|
||||
drop_target.connect("drop", self.__on_expander_drop_drop)
|
||||
expander.add_controller(drop_target)
|
||||
expander._drop_target = drop_target
|
||||
|
||||
# Row Drop target
|
||||
drop_target = self.__drop_target_new()
|
||||
drop_target.connect("accept", self.__on_row_drop_accept)
|
||||
drop_target.connect("motion", self.__on_row_drop_motion)
|
||||
drop_target.connect("drop", self.__on_row_drop_drop)
|
||||
row_widget.add_controller(drop_target)
|
||||
row_widget._drop_target = drop_target
|
||||
elif isinstance(item, CmbUI):
|
||||
# Expander Drop target
|
||||
drop_target = self.__drop_target_new()
|
||||
drop_target.connect("accept", self.__on_ui_expander_drop_accept)
|
||||
drop_target.connect("drop", self.__on_ui_expander_drop_drop)
|
||||
expander.add_controller(drop_target)
|
||||
expander._drop_target = drop_target
|
||||
|
||||
# Row Drop target
|
||||
drop_target = self.__drop_target_new()
|
||||
drop_target.connect("accept", self.__on_ui_row_drop_accept)
|
||||
drop_target.connect("drop", self.__on_ui_row_drop_drop)
|
||||
row_widget.add_controller(drop_target)
|
||||
row_widget.__drop_target = drop_target
|
||||
else:
|
||||
expander.props.hide_expander = True
|
||||
return
|
||||
|
||||
expander.props.hide_expander = item.props.n_items == 0
|
||||
item.connect("notify::n-items", self.__on_list_store_n_items_notify, expander)
|
||||
|
||||
def _on_factory_unbind(self, factory, list_item):
|
||||
row = list_item.get_item()
|
||||
item = row.get_item()
|
||||
expander = list_item.get_child()
|
||||
|
||||
item.disconnect_by_func(self.__on_item_notify)
|
||||
|
||||
if isinstance(item, CmbObject) or isinstance(item, CmbUI):
|
||||
item.disconnect_by_func(self.__on_list_store_n_items_notify)
|
||||
|
||||
if expander is None:
|
||||
return
|
||||
|
||||
# Clear controllers
|
||||
if expander._drop_target:
|
||||
expander.remove_controller(expander._drop_target)
|
||||
expander._drop_target = None
|
||||
|
||||
row_widget = expander.props.parent.props.parent
|
||||
if row_widget:
|
||||
if row_widget._drop_target:
|
||||
row_widget.remove_controller(row_widget._drop_target)
|
||||
row_widget._drop_target = None
|
||||
if row_widget._drag_source:
|
||||
row_widget.remove_controller(row_widget._drag_source)
|
||||
row_widget._drag_source = None
|
||||
|
||||
def __get_item_from_target(self, target):
|
||||
target_widget = target.get_widget()
|
||||
|
||||
if isinstance(target_widget, Gtk.TreeExpander):
|
||||
expander = target_widget
|
||||
else:
|
||||
cell = target_widget.get_first_child()
|
||||
expander = cell.get_first_child()
|
||||
|
||||
list_row = expander.get_list_row()
|
||||
item = list_row.get_item()
|
||||
|
||||
return item
|
||||
|
||||
def __on_drag_prepare(self, drag_source, x, y):
|
||||
item = self.__get_item_from_target(drag_source)
|
||||
return Gdk.ContentProvider.new_for_value(item)
|
||||
|
||||
def __on_drag_begin(self, drag_source, drag):
|
||||
expander = drag_source.get_widget().get_first_child().get_first_child()
|
||||
drag._item = self.__get_item_from_target(drag_source)
|
||||
drag_source.set_icon(Gtk.WidgetPaintable.new(expander.get_first_child()), 0, 0)
|
||||
|
||||
def __get_drop_before(self, widget, x, y):
|
||||
return True if y < widget.get_height()/2 else False
|
||||
|
||||
def __ui_drop_accept(self, drop, item):
|
||||
origin_item = drop.get_drag()._item
|
||||
|
||||
if origin_item == item:
|
||||
return False
|
||||
|
||||
# Ignore if its the same UI and item is already a toplevel
|
||||
if origin_item.ui_id == item.ui_id and origin_item.parent_id is None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __on_ui_expander_drop_accept(self, target, drop):
|
||||
item = self.__get_item_from_target(target)
|
||||
return self.__ui_drop_accept(drop, item)
|
||||
|
||||
def __on_ui_row_drop_accept(self, target, drop):
|
||||
item = self.__get_item_from_target(target)
|
||||
return self.__ui_drop_accept(drop, item)
|
||||
|
||||
def __on_object_drop_accept(self, drop, item):
|
||||
origin_item = drop.get_drag()._item
|
||||
|
||||
if origin_item == item:
|
||||
return None
|
||||
|
||||
if not isinstance(item, CmbObject):
|
||||
return None
|
||||
|
||||
# Ignore if its the same parent
|
||||
if origin_item.parent_id == item.object_id:
|
||||
return None
|
||||
|
||||
return origin_item
|
||||
|
||||
def __on_expander_drop_accept(self, target, drop):
|
||||
item = self.__get_item_from_target(target)
|
||||
origin_item = self.__on_object_drop_accept(drop, item)
|
||||
|
||||
if origin_item is None:
|
||||
return False
|
||||
|
||||
return self.__project._check_can_add(origin_item.type_id, item.type_id)
|
||||
|
||||
def __on_row_drop_accept(self, target, drop):
|
||||
item = self.__get_item_from_target(target)
|
||||
origin_item = self.__on_object_drop_accept(drop, item)
|
||||
|
||||
if origin_item is None or item.parent is None:
|
||||
return False
|
||||
|
||||
return self.__project._check_can_add(origin_item.type_id, item.parent.type_id)
|
||||
|
||||
def __on_row_drop_motion(self, target, x, y):
|
||||
row_widget = target.get_widget()
|
||||
|
||||
drop_before = self.__get_drop_before(row_widget, x, y)
|
||||
|
||||
row_widget.remove_css_class("drop-before")
|
||||
row_widget.remove_css_class("drop-after")
|
||||
|
||||
if drop_before:
|
||||
row_widget.add_css_class("drop-before")
|
||||
else:
|
||||
row_widget.add_css_class("drop-after")
|
||||
|
||||
return Gdk.DragAction.COPY
|
||||
|
||||
def __on_drop_drop(self, origin_item, item):
|
||||
if not isinstance(item, CmbUI):
|
||||
return
|
||||
|
||||
if origin_item.ui_id == item.ui_id:
|
||||
self.__project.history_push(_("Move {name} as toplevel").format(name=origin_item.display_name))
|
||||
origin_item.parent_id = 0
|
||||
self.__project.history_pop()
|
||||
else:
|
||||
# TODO: Use copy/paste to move across UI files
|
||||
pass
|
||||
|
||||
def __on_ui_row_drop_drop(self, target, origin_item, x, y):
|
||||
item = self.__get_item_from_target(target)
|
||||
self.__on_drop_drop(origin_item, item)
|
||||
|
||||
def __on_ui_expander_drop_drop(self, target, origin_item, x, y):
|
||||
item = self.__get_item_from_target(target)
|
||||
self.__on_drop_drop(origin_item, item)
|
||||
|
||||
def __on_expander_drop_drop(self, target, origin_item, x, y):
|
||||
item = self.__get_item_from_target(target)
|
||||
|
||||
if not isinstance(item, CmbObject):
|
||||
return
|
||||
|
||||
# TODO: handle dragging from one UI to another
|
||||
if origin_item.ui_id != item.ui_id:
|
||||
return
|
||||
|
||||
if origin_item.parent_id != item.object_id:
|
||||
self.__project.history_push(
|
||||
_("Move {name} to {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
)
|
||||
origin_item.parent_id = item.object_id
|
||||
self.__project.history_pop()
|
||||
|
||||
def __on_row_drop_drop(self, target, origin_item, x, y):
|
||||
row_widget = target.get_widget()
|
||||
item = self.__get_item_from_target(target)
|
||||
|
||||
drop_before = self.__get_drop_before(row_widget, x, y)
|
||||
|
||||
if not isinstance(item, CmbObject):
|
||||
return
|
||||
|
||||
# TODO: handle dragging from one UI to another
|
||||
if origin_item.ui_id != item.ui_id:
|
||||
return
|
||||
|
||||
if origin_item.parent_id != item.parent_id:
|
||||
if drop_before:
|
||||
msg = _("Move {name} before {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
else:
|
||||
msg = _("Move {name} after {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
|
||||
self.__project.history_push(msg)
|
||||
|
||||
origin_item.parent_id = item.parent_id
|
||||
else:
|
||||
msg = None
|
||||
|
||||
parent = item.parent
|
||||
|
||||
origin_position = origin_item.position
|
||||
target_position = item.position
|
||||
|
||||
if origin_position > target_position:
|
||||
if drop_before:
|
||||
position = item.position
|
||||
else:
|
||||
position = item.position + 1
|
||||
else:
|
||||
if drop_before:
|
||||
position = item.position - 1
|
||||
else:
|
||||
position = item.position
|
||||
|
||||
parent.reorder_child(origin_item, position)
|
||||
|
||||
if msg:
|
||||
self.__project.history_pop()
|
||||
|
||||
self.__project.set_selection([origin_item])
|
||||
|
||||
def __get_tree_expander(self, x, y):
|
||||
pick = self.pick(x, y, Gtk.PickFlags.DEFAULT)
|
||||
|
||||
if pick is None:
|
||||
return None
|
||||
|
||||
if isinstance(pick, Gtk.TreeExpander):
|
||||
return pick
|
||||
|
||||
child = pick.get_first_child()
|
||||
|
||||
if child and isinstance(child, Gtk.TreeExpander):
|
||||
return child
|
||||
|
||||
parent = pick.props.parent
|
||||
if parent and isinstance(parent, Gtk.TreeExpander):
|
||||
return parent
|
||||
|
||||
return None
|
||||
|
||||
def __on_activate(self, column_view, position):
|
||||
item = self.__tree_model.get_item(position)
|
||||
item.set_expanded(not item.get_expanded())
|
||||
|
||||
def do_query_tooltip(self, x, y, keyboard_mode, tooltip):
|
||||
expander = self.__get_tree_expander(x, y)
|
||||
|
||||
if expander is None:
|
||||
return False
|
||||
|
||||
obj = expander.get_item()
|
||||
|
||||
if isinstance(obj, CmbObject):
|
||||
msg = obj.version_warning
|
||||
if msg:
|
||||
tooltip.set_text(msg)
|
||||
return True
|
||||
|
||||
return False
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_context_menu.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
|
@ -24,7 +24,10 @@
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from gi.repository import GObject, Gio
|
||||
|
||||
from .cmb_path import CmbPath
|
||||
from .cmb_objects_base import CmbBaseCSS
|
||||
from cambalache import _
|
||||
|
||||
@ -34,6 +37,7 @@ class CmbCSS(CmbBaseCSS):
|
||||
"file-changed": (GObject.SignalFlags.RUN_FIRST, None, ()),
|
||||
}
|
||||
|
||||
path_parent = GObject.Property(type=CmbPath, flags=GObject.ParamFlags.READWRITE)
|
||||
css = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@ -53,9 +57,13 @@ class CmbCSS(CmbBaseCSS):
|
||||
if pspec.name == "filename":
|
||||
self.load_css()
|
||||
|
||||
@classmethod
|
||||
def get_display_name(cls, css_id, filename):
|
||||
return os.path.basename(filename) if filename else _("Unnamed CSS {css_id}").format(css_id=css_id)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def display_name(self):
|
||||
return self.filename if self.filename else _("Unnamed CSS {css_id}").format(css_id=self.css_id)
|
||||
return CmbCSS.get_display_name(self.css_id, self.filename)
|
||||
|
||||
@GObject.Property(type=int)
|
||||
def priority(self):
|
||||
|
@ -81,6 +81,7 @@ class CmbCSSEditor(Gtk.Grid):
|
||||
self.set_sensitive(False)
|
||||
return
|
||||
|
||||
self.filename.dirname = obj.project.dirname
|
||||
self.set_sensitive(True)
|
||||
|
||||
for field, target in self.fields:
|
||||
@ -107,10 +108,6 @@ class CmbCSSEditor(Gtk.Grid):
|
||||
self.__update_provider_for()
|
||||
self.__update_ui_button_label()
|
||||
|
||||
@Gtk.Template.Callback("on_remove_button_clicked")
|
||||
def __on_remove_button_clicked(self, button):
|
||||
self.emit("remove-css")
|
||||
|
||||
@Gtk.Template.Callback("on_save_button_clicked")
|
||||
def __on_save_button_clicked(self, button):
|
||||
self._object.save_css()
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_css_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
@ -39,11 +39,8 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="filename">
|
||||
<property name="can-focus">True</property>
|
||||
<object class="CmbFileButton" id="filename">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="placeholder-text" translatable="yes"><file name relative to project></property>
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
@ -111,20 +108,6 @@
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="focusable">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"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">app-remove-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">center</property>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_db_inspector.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbDBInspector" parent="GtkBox">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_fragment_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
|
151
cambalache/cmb_gresource.py
Normal file
151
cambalache/cmb_gresource.py
Normal file
@ -0,0 +1,151 @@
|
||||
#
|
||||
# Cambalache GResource wrapper
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gio
|
||||
|
||||
from .cmb_path import CmbPath
|
||||
from .cmb_objects_base import CmbBaseGResource
|
||||
from .cmb_list_error import CmbListError
|
||||
from cambalache import _
|
||||
|
||||
|
||||
class CmbGResource(CmbBaseGResource, Gio.ListModel):
|
||||
|
||||
path_parent = GObject.Property(type=CmbPath, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._last_known = None
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.connect("notify", self.__on_notify)
|
||||
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return f"CmbGResource<{self.resource_type}> id={self.gresource_id}"
|
||||
|
||||
def __on_notify(self, obj, pspec):
|
||||
resource_type = self.resource_type
|
||||
|
||||
if (resource_type == "gresources" and pspec.name == "gresources-filename") or \
|
||||
(resource_type == "gresource" and pspec.name == "gresource-prefix") or \
|
||||
(resource_type == "file" and pspec.name == "file-filename"):
|
||||
obj.notify("display-name")
|
||||
|
||||
self.project._gresource_changed(self, pspec.name)
|
||||
|
||||
@GObject.Property(type=CmbBaseGResource)
|
||||
def parent(self):
|
||||
if self.resource_type in ["gresource", "file"]:
|
||||
return self.project.get_gresource_by_id(self.parent_id)
|
||||
|
||||
return None
|
||||
|
||||
@GObject.Property(type=CmbBaseGResource)
|
||||
def gresources_bundle(self):
|
||||
resource_type = self.resource_type
|
||||
if resource_type == "gresource":
|
||||
return self.parent
|
||||
elif resource_type == "file":
|
||||
return self.parent.parent
|
||||
|
||||
return self
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def display_name(self):
|
||||
resource_type = self.resource_type
|
||||
|
||||
if resource_type == "gresources":
|
||||
gresources_filename = self.gresources_filename
|
||||
if gresources_filename:
|
||||
basename, relpath = self.project._get_basename_relpath(self.gresources_filename)
|
||||
return basename
|
||||
|
||||
return _("Unnamed GResource {id}").format(id=self.gresource_id)
|
||||
elif resource_type == "gresource":
|
||||
gresource_prefix = self.gresource_prefix
|
||||
return gresource_prefix if gresource_prefix else _("Unprefixed resource {id}").format(id=self.gresource_id)
|
||||
elif resource_type == "file":
|
||||
file_filename = self.file_filename
|
||||
return file_filename if file_filename else _("Unnamed file {id}").format(id=self.gresource_id)
|
||||
|
||||
# GListModel helpers
|
||||
def _save_last_known_parent_and_position(self):
|
||||
self._last_known = (self.parent, self.position)
|
||||
|
||||
def _update_new_parent(self):
|
||||
parent = self.parent
|
||||
position = self.position
|
||||
|
||||
# Emit GListModel signal to update model
|
||||
if parent:
|
||||
parent.items_changed(position, 0, 1)
|
||||
parent.notify("n-items")
|
||||
|
||||
self._last_known = None
|
||||
|
||||
def _remove_from_old_parent(self):
|
||||
if self._last_known is None:
|
||||
return
|
||||
|
||||
parent, position = self._last_known
|
||||
|
||||
# Emit GListModel signal to update model
|
||||
if parent:
|
||||
parent.items_changed(position, 1, 0)
|
||||
parent.notify("n-items")
|
||||
|
||||
self._last_known = None
|
||||
|
||||
# GListModel iface
|
||||
def do_get_item(self, position):
|
||||
gresource_id = self.gresource_id
|
||||
key = self.db_get(
|
||||
"SELECT gresource_id FROM gresource WHERE parent_id=? AND position=?;",
|
||||
(gresource_id, position)
|
||||
)
|
||||
|
||||
if key is not None:
|
||||
return self.project.get_gresource_by_id(key)
|
||||
|
||||
# This should not happen
|
||||
return CmbListError()
|
||||
|
||||
def do_get_item_type(self):
|
||||
return CmbBaseGResource
|
||||
|
||||
@GObject.Property(type=int)
|
||||
def n_items(self):
|
||||
if self.resource_type in ["gresources", "gresource"]:
|
||||
retval = self.db_get("SELECT COUNT(gresource_id) FROM gresource WHERE parent_id=?;", (self.gresource_id, ))
|
||||
return retval if retval is not None else 0
|
||||
else:
|
||||
return 0
|
||||
|
||||
def do_get_n_items(self):
|
||||
return self.n_items
|
||||
|
117
cambalache/cmb_gresource_editor.py
Normal file
117
cambalache/cmb_gresource_editor.py
Normal file
@ -0,0 +1,117 @@
|
||||
#
|
||||
# CmbGResourceEditor - Cambalache GResource Editor
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gtk
|
||||
|
||||
from .cmb_gresource import CmbGResource
|
||||
from cambalache import getLogger
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_gresource_editor.ui")
|
||||
class CmbGResourceEditor(Gtk.Box):
|
||||
__gtype_name__ = "CmbGResourceEditor"
|
||||
|
||||
stack = Gtk.Template.Child()
|
||||
|
||||
gresources_filename = Gtk.Template.Child()
|
||||
gresource_prefix = Gtk.Template.Child()
|
||||
file_filename = Gtk.Template.Child()
|
||||
file_compressed = Gtk.Template.Child()
|
||||
file_preprocess = Gtk.Template.Child()
|
||||
file_alias = Gtk.Template.Child()
|
||||
|
||||
fields = [
|
||||
("gresources", "gresources_filename", "cmb-value"),
|
||||
("gresource", "gresource_prefix", "cmb-value"),
|
||||
("file", "file_filename", "cmb-value"),
|
||||
("file", "file_compressed", "active"),
|
||||
("file", "file_preprocess", "cmb-value"),
|
||||
("file", "file_alias", "cmb-value"),
|
||||
]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._object = None
|
||||
self._bindings = []
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@GObject.Property(type=CmbGResource)
|
||||
def object(self):
|
||||
return self._object
|
||||
|
||||
@object.setter
|
||||
def _set_object(self, obj):
|
||||
if obj == self._object:
|
||||
return
|
||||
|
||||
for binding in self._bindings:
|
||||
binding.unbind()
|
||||
|
||||
self._bindings = []
|
||||
self._object = obj
|
||||
|
||||
if obj is None:
|
||||
self.set_sensitive(False)
|
||||
for for_type, field, target in self.fields:
|
||||
widget = getattr(self, field)
|
||||
target_prop = getattr(widget, target)
|
||||
|
||||
if isinstance(target_prop, int):
|
||||
setattr(widget, target, 0)
|
||||
else:
|
||||
setattr(widget, target, None)
|
||||
return
|
||||
|
||||
resource_type = obj.resource_type
|
||||
self.set_sensitive(True)
|
||||
self.stack.set_visible_child_name(resource_type)
|
||||
self.gresources_filename.dirname = obj.project.dirname
|
||||
self.file_filename.dirname = obj.project.dirname
|
||||
|
||||
for for_type, field, target in self.fields:
|
||||
if resource_type != for_type:
|
||||
continue
|
||||
|
||||
binding = GObject.Object.bind_property(
|
||||
obj,
|
||||
field,
|
||||
getattr(self, field),
|
||||
target,
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
)
|
||||
self._bindings.append(binding)
|
||||
|
||||
@Gtk.Template.Callback("on_add_gresource_button_clicked")
|
||||
def __on_add_gresource_button_clicked(self, button):
|
||||
self._object.project.add_gresource("gresource", parent_id=self._object.gresource_id)
|
||||
|
||||
@Gtk.Template.Callback("on_add_file_button_clicked")
|
||||
def __on_add_file_button_clicked(self, button):
|
||||
self._object.project.add_gresource("file", parent_id=self._object.gresource_id)
|
||||
|
||||
|
||||
Gtk.WidgetClass.set_css_name(CmbGResourceEditor, "CmbGResourceEditor")
|
241
cambalache/cmb_gresource_editor.ui
Normal file
241
cambalache/cmb_gresource_editor.ui
Normal file
@ -0,0 +1,241 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_gresource_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
<requires lib="gtk" version="4.12"/>
|
||||
<template class="CmbGResourceEditor" parent="GtkBox">
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="transition-type">crossfade</property>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="GtkGrid">
|
||||
<property name="column-spacing">4</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Filename</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbFileButton" id="gresources_filename">
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">* This resource file need to be compiled and loaded at runtime</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="column-span">2</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_gresource_button">
|
||||
<property name="halign">start</property>
|
||||
<property name="label">GResource</property>
|
||||
<signal name="clicked" handler="on_add_gresource_button_clicked"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">gresources</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="GtkGrid">
|
||||
<property name="column-spacing">4</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Prefix</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="gresource_prefix">
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">* Files defined inside this will be available at gresource://prefix</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="column-span">2</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_file_button">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">file</property>
|
||||
<signal name="clicked" handler="on_add_file_button_clicked"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">gresource</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="child">
|
||||
<object class="GtkGrid">
|
||||
<property name="column-spacing">4</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Filename</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Compressed</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Preprocess</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Alias</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="file_compressed">
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="file_preprocess">
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="file_alias">
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbFileButton" id="file_filename">
|
||||
<property name="use-open">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">0</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="name">file</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@ -35,9 +35,7 @@ class CmbLayoutProperty(CmbBaseLayoutProperty):
|
||||
info = GObject.Property(type=CmbPropertyInfo, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__on_init = True
|
||||
super().__init__(**kwargs)
|
||||
self.__on_init = False
|
||||
self.version_warning = None
|
||||
|
||||
owner_info = self.project.type_info.get(self.info.owner_id, None)
|
||||
@ -68,11 +66,6 @@ class CmbLayoutProperty(CmbBaseLayoutProperty):
|
||||
|
||||
@value.setter
|
||||
def _set_value(self, value):
|
||||
# Update object position if this is a position property
|
||||
if self.info.is_position and not self.__on_init:
|
||||
self.object.parent.reorder_child(self.object, int(value) if value else 0)
|
||||
return
|
||||
|
||||
c = self.project.db.cursor()
|
||||
|
||||
if value is None or value == self.info.default_value:
|
||||
@ -113,9 +106,6 @@ class CmbLayoutProperty(CmbBaseLayoutProperty):
|
||||
(self.ui_id, self.object_id, self.child_id, self.owner_id, self.property_id, value),
|
||||
)
|
||||
|
||||
if not self.__on_init:
|
||||
self.object._layout_property_changed(self)
|
||||
|
||||
c.close()
|
||||
|
||||
def _update_version_warning(self):
|
||||
|
@ -36,3 +36,7 @@ class CmbListError(CmbBase):
|
||||
def display_name(self):
|
||||
return "list error"
|
||||
|
||||
@GObject.Property(type=int)
|
||||
def n_items(self):
|
||||
return 0
|
||||
|
||||
|
260
cambalache/cmb_list_view.py
Normal file
260
cambalache/cmb_list_view.py
Normal file
@ -0,0 +1,260 @@
|
||||
#
|
||||
# CmbColumnView
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GLib, GObject, Gdk, Gtk
|
||||
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_gresource import CmbGResource
|
||||
from .cmb_context_menu import CmbContextMenu
|
||||
from .cmb_path import CmbPath
|
||||
from .cmb_project import CmbProject
|
||||
from .cmb_tree_expander import CmbTreeExpander
|
||||
|
||||
|
||||
class CmbListView(Gtk.ListView):
|
||||
__gtype_name__ = "CmbListView"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__project = None
|
||||
self.__tree_model = None
|
||||
self.__in_selection_change = False
|
||||
self.single_selection = Gtk.SingleSelection()
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.props.has_tooltip = True
|
||||
self.props.hexpand = True
|
||||
|
||||
factory = Gtk.SignalListItemFactory()
|
||||
factory.connect("setup", self._on_factory_setup)
|
||||
factory.connect("bind", self._on_factory_bind)
|
||||
factory.connect("unbind", self._on_factory_unbind)
|
||||
self.props.factory = factory
|
||||
|
||||
self.single_selection.connect("notify::selected-item", self.__on_selected_item_notify)
|
||||
self.set_model(self.single_selection)
|
||||
|
||||
gesture = Gtk.GestureClick(button=Gdk.BUTTON_SECONDARY)
|
||||
gesture.connect("pressed", self.__on_button_press)
|
||||
self.add_controller(gesture)
|
||||
|
||||
self.connect("activate", self.__on_activate)
|
||||
|
||||
self.add_css_class("navigation-sidebar")
|
||||
self.add_css_class("cmb-list-view")
|
||||
|
||||
def __on_button_press(self, gesture, npress, x, y):
|
||||
expander = self.__get_tree_expander(x, y)
|
||||
|
||||
if expander is None or npress != 1:
|
||||
return False
|
||||
|
||||
# Select row at x,y
|
||||
list_row = expander.get_list_row()
|
||||
self.single_selection.set_selected(list_row.get_position())
|
||||
|
||||
menu = CmbContextMenu()
|
||||
|
||||
if self.__project:
|
||||
menu.target_tk = self.__project.target_tk
|
||||
|
||||
menu.set_parent(self)
|
||||
menu.popup_at(x, y)
|
||||
return True
|
||||
|
||||
def __get_path_parent(self, obj):
|
||||
if isinstance(obj, CmbObject):
|
||||
parent = obj.parent
|
||||
return parent if parent else obj.ui
|
||||
elif isinstance(obj, CmbGResource):
|
||||
return obj.path_parent if obj.resource_type == "gresources" else obj.parent
|
||||
elif isinstance(obj, CmbProject):
|
||||
return None
|
||||
|
||||
return obj.path_parent
|
||||
|
||||
def __get_object_ancestors(self, obj):
|
||||
ancestors = set()
|
||||
|
||||
parent = self.__get_path_parent(obj)
|
||||
while parent:
|
||||
ancestors.add(parent)
|
||||
parent = self.__get_path_parent(parent)
|
||||
|
||||
return ancestors
|
||||
|
||||
def __object_ancestor_expand(self, obj):
|
||||
ancestors = self.__get_object_ancestors(obj)
|
||||
i = 0
|
||||
|
||||
# Iterate over tree model
|
||||
# NOTE: only visible/expanded rows are returned
|
||||
list_row = self.__tree_model.get_row(i)
|
||||
while list_row:
|
||||
item = list_row.get_item()
|
||||
|
||||
# Return position if we reached the object row
|
||||
if item == obj:
|
||||
return i
|
||||
elif item in ancestors:
|
||||
# Expand row if its part of the hierarchy
|
||||
list_row.set_expanded(True)
|
||||
|
||||
i += 1
|
||||
list_row = self.__tree_model.get_row(i)
|
||||
|
||||
return None
|
||||
|
||||
def __on_project_selection_changed(self, p):
|
||||
list_row = self.single_selection.get_selected_item()
|
||||
current_selection = [list_row.get_item()] if list_row else []
|
||||
selection = self.__project.get_selection()
|
||||
|
||||
if selection == current_selection:
|
||||
return
|
||||
|
||||
self.__in_selection_change = True
|
||||
|
||||
if len(selection) > 0:
|
||||
position = self.__object_ancestor_expand(selection[0])
|
||||
if position is not None:
|
||||
self.single_selection.select_item(position, True)
|
||||
else:
|
||||
self.single_selection.unselect_all()
|
||||
else:
|
||||
self.single_selection.unselect_all()
|
||||
|
||||
self.__in_selection_change = False
|
||||
|
||||
@GObject.Property(type=CmbProject)
|
||||
def project(self):
|
||||
return self.__project
|
||||
|
||||
@project.setter
|
||||
def _set_project(self, project):
|
||||
if self.__project:
|
||||
self.__project.disconnect_by_func(self.__on_project_selection_changed)
|
||||
|
||||
self.__project = project
|
||||
|
||||
if project:
|
||||
self.__tree_model = Gtk.TreeListModel.new(
|
||||
project,
|
||||
False,
|
||||
False,
|
||||
self.__tree_model_create_func,
|
||||
None
|
||||
)
|
||||
self.single_selection.props.model = self.__tree_model
|
||||
self.__project.connect("selection-changed", self.__on_project_selection_changed)
|
||||
else:
|
||||
self.single_selection.props.model = None
|
||||
|
||||
def __tree_model_create_func(self, item, data):
|
||||
if isinstance(item, CmbObject):
|
||||
return item
|
||||
elif isinstance(item, CmbUI):
|
||||
return item
|
||||
elif isinstance(item, CmbGResource):
|
||||
return item
|
||||
elif isinstance(item, CmbPath):
|
||||
return item
|
||||
|
||||
return None
|
||||
|
||||
def __on_selected_item_notify(self, single_selection, pspec):
|
||||
if self.__in_selection_change or self.__project is None:
|
||||
return
|
||||
|
||||
list_item = single_selection.get_selected_item()
|
||||
position = single_selection.get_selected()
|
||||
|
||||
if list_item is None:
|
||||
self.__project.set_selection([])
|
||||
return
|
||||
|
||||
item = list_item.get_item()
|
||||
self.activate_action("list.activate-item", GLib.Variant("u", position))
|
||||
|
||||
if item and not isinstance(item, CmbPath):
|
||||
item = list_item.get_item()
|
||||
self.__project.set_selection([item])
|
||||
else:
|
||||
self.__project.set_selection([])
|
||||
|
||||
def _on_factory_setup(self, factory, list_item):
|
||||
expander = CmbTreeExpander()
|
||||
list_item.set_child(expander)
|
||||
|
||||
def _on_factory_bind(self, factory, list_item):
|
||||
row = list_item.get_item()
|
||||
expander = list_item.get_child()
|
||||
expander.set_list_row(row)
|
||||
expander.update_bind()
|
||||
|
||||
def _on_factory_unbind(self, factory, list_item):
|
||||
expander = list_item.get_child()
|
||||
expander.clear_bind()
|
||||
|
||||
def __get_tree_expander(self, x, y):
|
||||
pick = self.pick(x, y, Gtk.PickFlags.DEFAULT)
|
||||
|
||||
if pick is None:
|
||||
return None
|
||||
|
||||
if isinstance(pick, Gtk.TreeExpander):
|
||||
return pick
|
||||
|
||||
child = pick.get_first_child()
|
||||
|
||||
if child and isinstance(child, Gtk.TreeExpander):
|
||||
return child
|
||||
|
||||
parent = pick.props.parent
|
||||
if parent and isinstance(parent, Gtk.TreeExpander):
|
||||
return parent
|
||||
|
||||
return None
|
||||
|
||||
def __on_activate(self, column_view, position):
|
||||
item = self.__tree_model.get_item(position)
|
||||
item.set_expanded(not item.get_expanded())
|
||||
|
||||
def do_query_tooltip(self, x, y, keyboard_mode, tooltip):
|
||||
expander = self.__get_tree_expander(x, y)
|
||||
|
||||
if expander is None:
|
||||
return False
|
||||
|
||||
obj = expander.get_item()
|
||||
|
||||
if isinstance(obj, CmbObject):
|
||||
msg = obj.version_warning
|
||||
if msg:
|
||||
tooltip.set_text(msg)
|
||||
return True
|
||||
|
||||
return False
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# CmbListStore - Cambalache List Store
|
||||
# CmbMessageNotificationView
|
||||
#
|
||||
# Copyright (C) 2021 Juan Pablo Ugarte
|
||||
# Copyright (C) 2025 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,26 +23,28 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from cambalache import getLogger
|
||||
from gi.repository import GObject, Gtk
|
||||
from .cmb_notification import CmbMessageNotification
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class CmbListStore(Gtk.ListStore):
|
||||
__gtype_name__ = "CmbListStore"
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_message_notification_view.ui")
|
||||
class CmbMessageNotificationView(Gtk.Box):
|
||||
__gtype_name__ = "CmbMessageNotificationView"
|
||||
|
||||
table = GObject.Property(type=str)
|
||||
query = GObject.Property(type=str)
|
||||
project = GObject.Property(type=GObject.GObject)
|
||||
notification = GObject.Property(
|
||||
type=CmbMessageNotification, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY
|
||||
)
|
||||
|
||||
# Message
|
||||
title_label = Gtk.Template.Child()
|
||||
message_label = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
data = self.project._get_table_data(self.table)
|
||||
self.set_column_types(data["types"])
|
||||
self.__populate()
|
||||
|
||||
def __populate(self):
|
||||
c = self.project.db.cursor()
|
||||
for row in c.execute(self.query):
|
||||
self.append(row)
|
||||
|
||||
c.close()
|
||||
notification = self.notification
|
||||
self.title_label.props.label = f"<b>{notification.title}</b>"
|
||||
self.message_label.props.label = notification.message
|
22
cambalache/cmb_message_notification_view.ui
Normal file
22
cambalache/cmb_message_notification_view.ui
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_message_notification_view.ui -->
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbMessageNotificationView" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="message_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
378
cambalache/cmb_notification.py
Normal file
378
cambalache/cmb_notification.py
Normal file
@ -0,0 +1,378 @@
|
||||
#
|
||||
# Cambalache notification system
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import os
|
||||
import json
|
||||
import threading
|
||||
import http.client
|
||||
import time
|
||||
import platform
|
||||
|
||||
from uuid import uuid4
|
||||
from urllib.parse import urlparse
|
||||
from .config import VERSION
|
||||
from gi.repository import GObject, GLib, Gio, Gdk, Gtk, Adw, HarfBuzz
|
||||
from cambalache import getLogger
|
||||
from . import utils
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class CmbBaseData(GObject.GObject):
|
||||
def __init__(self, **kwargs):
|
||||
for prop in self.list_properties():
|
||||
name = prop.name.replace("-", "_")
|
||||
|
||||
if name not in kwargs:
|
||||
continue
|
||||
|
||||
value = kwargs[name]
|
||||
|
||||
if isinstance(value, dict) and prop.value_type in GTYPE_PTYHON:
|
||||
Klass = GTYPE_PTYHON[prop.value_type]
|
||||
kwargs[name] = Klass(**value)
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def dict(self):
|
||||
retval = {}
|
||||
|
||||
for prop in self.list_properties():
|
||||
name = prop.name.replace("-", "_")
|
||||
|
||||
value = self.get_property(prop.name)
|
||||
|
||||
if prop.value_type in GTYPE_PTYHON:
|
||||
retval[name] = value.dict() if value else None
|
||||
elif not isinstance(value, GObject.Object):
|
||||
retval[name] = value
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
class CmbPollData(CmbBaseData):
|
||||
id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
title = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
description = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
options = GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
|
||||
allowed_votes = GObject.Property(type=int, default=1, flags=GObject.ParamFlags.READWRITE)
|
||||
start_date = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
end_date = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
class CmbPollResult(CmbBaseData):
|
||||
votes = GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
|
||||
total = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
GTYPE_PTYHON = {CmbPollData.__gtype__: CmbPollData, CmbPollResult.__gtype__: CmbPollResult}
|
||||
|
||||
|
||||
class CmbNotification(CmbBaseData):
|
||||
center = GObject.Property(type=GObject.Object, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
type = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
start_date = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
end_date = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
class CmbVersionNotification(CmbNotification):
|
||||
version = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
release_notes = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
read_more_url = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
class CmbMessageNotification(CmbNotification):
|
||||
title = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
message = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
class CmbPollNotification(CmbNotification):
|
||||
poll = GObject.Property(type=CmbPollData, flags=GObject.ParamFlags.READWRITE)
|
||||
results = GObject.Property(type=CmbPollResult, flags=GObject.ParamFlags.READWRITE)
|
||||
my_votes = GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
|
||||
class CmbNotificationCenter(GObject.GObject):
|
||||
__gsignals__ = {
|
||||
"new-notification": (GObject.SignalFlags.RUN_FIRST, None, (CmbNotification,)),
|
||||
}
|
||||
|
||||
# Settings
|
||||
enabled = GObject.Property(type=bool, default=True, flags=GObject.ParamFlags.READWRITE)
|
||||
uuid = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
next_request = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE)
|
||||
notifications = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
store = GObject.Property(type=Gio.ListStore, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.retry_interval = 2
|
||||
self.user_agent = self.__get_user_agent()
|
||||
self.store = Gio.ListStore(item_type=CmbNotification)
|
||||
self.settings = Gio.Settings(schema_id="ar.xjuan.Cambalache.notification")
|
||||
|
||||
for prop in ["enabled", "uuid", "next-request", "notifications"]:
|
||||
self.settings.bind(prop, self, prop.replace("-", "_"), Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
# Disable notifications if settings backend is ephemeral
|
||||
if GObject.type_name(Gio.SettingsBackend.get_default()) == "GMemorySettingsBackend":
|
||||
logger.info("Disabling notifications")
|
||||
self.enabled = False
|
||||
|
||||
self.__load_notifications()
|
||||
|
||||
backend = urlparse(os.environ.get("CMB_NOTIFICATION_URL", "https://xjuan.ar:1934"))
|
||||
self.REQUEST_INTERVAL = 4 if backend.hostname == "localhost" else 24 * 60 * 60
|
||||
|
||||
if backend.scheme == "https":
|
||||
logger.info(f"Backend: {backend.scheme}://{backend.hostname}:{backend.port}")
|
||||
self.connection = http.client.HTTPSConnection(backend.hostname, backend.port, timeout=8)
|
||||
else:
|
||||
self.connection = None
|
||||
logger.warning(f"{backend.scheme} is not supported, only HTTPS")
|
||||
return
|
||||
|
||||
# Ensure we have a UUID
|
||||
if not self.uuid:
|
||||
self.uuid = str(uuid4())
|
||||
|
||||
logger.info(f"User Agent: {self.user_agent}")
|
||||
logger.info(f"UUID: {self.uuid}")
|
||||
|
||||
self._get_notification()
|
||||
|
||||
def __get_container(self):
|
||||
if "FLATPAK_ID" in os.environ:
|
||||
return "flatpak"
|
||||
elif "APPIMAGE" in os.environ:
|
||||
return "appimage"
|
||||
elif "SNAP" in os.environ:
|
||||
return "snap"
|
||||
return None
|
||||
|
||||
def __get_user_agent(self):
|
||||
u = platform.uname()
|
||||
platform_strings = []
|
||||
table = str.maketrans({",": "\\,"})
|
||||
|
||||
if u.system == "Linux":
|
||||
release = platform.freedesktop_os_release()
|
||||
system = f"Linux {release['ID']}"
|
||||
|
||||
if "VERSION_ID" in release:
|
||||
system += f" {release['VERSION_ID']}"
|
||||
if "VERSION_CODENAME" in release:
|
||||
system += f" {release['VERSION_CODENAME']}"
|
||||
else:
|
||||
system = u.system
|
||||
|
||||
display_type = GObject.type_name(Gdk.Display.get_default())
|
||||
backend = display_type.removeprefix("Gdk").removesuffix("Display")
|
||||
lang = HarfBuzz.language_to_string(HarfBuzz.language_get_default())
|
||||
extra = []
|
||||
|
||||
# Container type
|
||||
container = self.__get_container()
|
||||
if container:
|
||||
extra.append(f"container {container}")
|
||||
|
||||
# GSettings backend
|
||||
settings_backend = Gio.SettingsBackend.get_default()
|
||||
gsettings_backend = GObject.type_name(settings_backend).removesuffix("SettingsBackend")
|
||||
|
||||
for name, lib in [("GLib", GLib), ("Gtk", Gtk), ("Adw", Adw)]:
|
||||
extra.append(f"{name} {lib.MAJOR_VERSION}.{lib.MINOR_VERSION}.{lib.MICRO_VERSION}")
|
||||
|
||||
# Ignore node name as that is private and irrelevant information
|
||||
for string in [system, u.release, u.version, u.machine, backend, gsettings_backend]:
|
||||
if not string:
|
||||
continue
|
||||
platform_strings.append(string.translate(table))
|
||||
|
||||
return f"Cambalache/{VERSION} ({', '.join(platform_strings)}; {'; '.join(extra)}; {lang})"
|
||||
|
||||
def __load_notifications(self):
|
||||
self.store.remove_all()
|
||||
|
||||
if not self.notifications:
|
||||
return
|
||||
|
||||
notifications = json.loads(self.notifications)
|
||||
now = utils.utcnow()
|
||||
|
||||
for data in notifications:
|
||||
if "end_date" in data and now > data["end_date"]:
|
||||
continue
|
||||
|
||||
self.store.append(self.__notification_from_dict(data))
|
||||
|
||||
def __save_notifications(self):
|
||||
notifications = []
|
||||
|
||||
for notification in self.store:
|
||||
notifications.append(notification.dict())
|
||||
|
||||
# Store in GSettings
|
||||
self.notifications = json.dumps(notifications, indent=2, sort_keys=True)
|
||||
|
||||
def __notification_from_dict(self, data):
|
||||
ntype = data.get("type", None)
|
||||
|
||||
if ntype == "version":
|
||||
return CmbVersionNotification(center=self, **data)
|
||||
elif ntype == "message":
|
||||
return CmbMessageNotification(center=self, **data)
|
||||
elif ntype == "poll":
|
||||
return CmbPollNotification(center=self, **data)
|
||||
|
||||
def __get_notification_idle(self, data):
|
||||
logger.debug(f"Got notification response {json.dumps(data, indent=2, sort_keys=True)}")
|
||||
|
||||
if "notification" in data:
|
||||
notification = self.__notification_from_dict(data["notification"])
|
||||
self.store.insert(0, notification)
|
||||
self.__save_notifications()
|
||||
self.emit("new-notification", notification)
|
||||
|
||||
now = int(time.time())
|
||||
self.next_request = now + self.REQUEST_INTERVAL
|
||||
self._get_notification()
|
||||
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def __get_notification_thread(self):
|
||||
headers = {
|
||||
"User-Agent": self.user_agent,
|
||||
"x-cambalache-uuid": self.uuid,
|
||||
}
|
||||
|
||||
try:
|
||||
logger.info(f"GET /notification {headers=}")
|
||||
|
||||
self.connection.request("GET", "/notification", headers=headers)
|
||||
response = self.connection.getresponse()
|
||||
assert response.status == 200
|
||||
|
||||
# Reset retry interval
|
||||
self.retry_interval = 8
|
||||
|
||||
data = response.read().decode()
|
||||
|
||||
logger.info(f"response={data}")
|
||||
|
||||
if data:
|
||||
GLib.idle_add(self.__get_notification_idle, json.loads(data))
|
||||
except Exception as e:
|
||||
# If it fails we just wait a bit before retrying
|
||||
self.retry_interval *= 2
|
||||
self.retry_interval = min(self.retry_interval, 256)
|
||||
|
||||
logger.info(f"Request error {e}, retrying in {self.retry_interval}s")
|
||||
GLib.timeout_add_seconds(self.retry_interval, self._get_notification)
|
||||
|
||||
self.connection.close()
|
||||
|
||||
def __run_in_thread(self, function, *args, **kwargs):
|
||||
if not self.connection:
|
||||
logger.warning("No connection defined")
|
||||
return
|
||||
|
||||
if not self.enabled:
|
||||
logger.info("Notifications disabled")
|
||||
return
|
||||
|
||||
thread = threading.Thread(target=function, args=args, kwargs=kwargs, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def _get_notification(self):
|
||||
now = int(time.time())
|
||||
|
||||
if now >= self.next_request:
|
||||
self.__run_in_thread(self.__get_notification_thread)
|
||||
else:
|
||||
GLib.timeout_add_seconds(self.next_request - now, self._get_notification)
|
||||
|
||||
def __poll_vote_idle(self, data):
|
||||
logger.debug(f"Got vote response {data}")
|
||||
|
||||
poll_uuid = data["uuid"]
|
||||
results = data["results"]
|
||||
|
||||
for notification in self.store:
|
||||
if isinstance(notification, CmbPollNotification) and notification.poll.id == poll_uuid:
|
||||
notification.results = CmbPollResult(**results)
|
||||
self.__save_notifications()
|
||||
break
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def __poll_vote_exception_idle(self, poll_uuid):
|
||||
for notification in self.store:
|
||||
if isinstance(notification, CmbPollNotification) and notification.poll.id == poll_uuid:
|
||||
notification.my_votes = []
|
||||
break
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def __poll_vote_thread(self, method, poll_uuid, votes=None):
|
||||
headers = {"User-Agent": self.user_agent, "x-cambalache-uuid": self.uuid, "Content-type": "application/json"}
|
||||
|
||||
try:
|
||||
payload = json.dumps({"votes": votes}) if method == "POST" else None
|
||||
self.connection.request(method, f"/poll/{poll_uuid}", payload, headers)
|
||||
response = self.connection.getresponse()
|
||||
assert response.status == 200
|
||||
|
||||
data = response.read().decode()
|
||||
GLib.idle_add(self.__poll_vote_idle, json.loads(data))
|
||||
except Exception as e:
|
||||
logger.warning(f"Error voting {e}")
|
||||
GLib.idle_add(self.__poll_vote_exception_idle, poll_uuid)
|
||||
|
||||
self.connection.close()
|
||||
|
||||
def poll_vote(self, notification: CmbPollNotification, votes: list[int]):
|
||||
if self.uuid is None:
|
||||
return
|
||||
|
||||
notification.my_votes = votes
|
||||
|
||||
self.__run_in_thread(self.__poll_vote_thread, "POST", notification.poll.id, votes)
|
||||
|
||||
def poll_refresh_results(self, notification: CmbPollNotification):
|
||||
if self.uuid is None:
|
||||
return
|
||||
|
||||
self.__run_in_thread(self.__poll_vote_thread, "GET", notification.poll.id)
|
||||
|
||||
def remove(self, notification: CmbNotification):
|
||||
valid, position = self.store.find(notification)
|
||||
if valid:
|
||||
self.store.remove(position)
|
||||
self.__save_notifications()
|
||||
|
||||
|
||||
notification_center = CmbNotificationCenter()
|
60
cambalache/cmb_notification_list_row.py
Normal file
60
cambalache/cmb_notification_list_row.py
Normal file
@ -0,0 +1,60 @@
|
||||
#
|
||||
# CmbNotificationListRow
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import datetime
|
||||
|
||||
from cambalache import getLogger
|
||||
from gi.repository import GObject, Gtk
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_notification_list_row.ui")
|
||||
class CmbNotificationListRow(Gtk.ListBoxRow):
|
||||
__gtype_name__ = "CmbNotificationListRow"
|
||||
|
||||
view = GObject.Property(type=Gtk.Widget, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
box = Gtk.Template.Child()
|
||||
date_label = Gtk.Template.Child()
|
||||
close_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.props.activatable = False
|
||||
|
||||
notification = self.view.notification
|
||||
start_date = datetime.datetime.utcfromtimestamp(notification.start_date).strftime("%x")
|
||||
self.date_label.set_label(f"<small>{start_date}</small>")
|
||||
self.box.append(self.view)
|
||||
|
||||
@Gtk.Template.Callback("on_map")
|
||||
def __on_map(self, w):
|
||||
self.props.child.props.reveal_child = True
|
||||
|
||||
@Gtk.Template.Callback("on_close_button_clicked")
|
||||
def __on_close_button_clicked(self, button):
|
||||
notification = self.view.notification
|
||||
notification.center.remove(notification)
|
42
cambalache/cmb_notification_list_row.ui
Normal file
42
cambalache/cmb_notification_list_row.ui
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_notification_list_row.ui -->
|
||||
<requires lib="gtk" version="4.12"/>
|
||||
<template class="CmbNotificationListRow" parent="GtkListBoxRow">
|
||||
<signal name="map" handler="on_map"/>
|
||||
<child>
|
||||
<object class="GtkRevealer">
|
||||
<child>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<property name="vexpand-set">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="date_label">
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="icon-name">window-close-symbolic</property>
|
||||
<signal name="clicked" handler="on_close_button_clicked"/>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="compact"/>
|
||||
<class name="close"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
67
cambalache/cmb_notification_list_view.py
Normal file
67
cambalache/cmb_notification_list_view.py
Normal file
@ -0,0 +1,67 @@
|
||||
#
|
||||
# CmbNotificationListView
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from cambalache import getLogger
|
||||
from gi.repository import GObject, Gtk
|
||||
from .cmb_version_notification_view import CmbVersionNotificationView
|
||||
from .cmb_message_notification_view import CmbMessageNotificationView
|
||||
from .cmb_poll_notification_view import CmbPollNotificationView
|
||||
from .cmb_notification_list_row import CmbNotificationListRow
|
||||
from .cmb_notification import CmbNotificationCenter, CmbVersionNotification, CmbMessageNotification, CmbPollNotification
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_notification_list_view.ui")
|
||||
class CmbNotificationListView(Gtk.Box):
|
||||
__gtype_name__ = "CmbNotificationListView"
|
||||
|
||||
notification_center = GObject.Property(type=CmbNotificationCenter, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
list_box = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.connect("notify::notification-center", self.__on_notification_center_notify)
|
||||
|
||||
def __on_notification_center_notify(self, obj, pspec):
|
||||
self.list_box.bind_model(self.notification_center.store, self.__create_widget_func)
|
||||
GObject.Object.bind_property(
|
||||
self.notification_center.store,
|
||||
"n-items",
|
||||
self.list_box,
|
||||
"visible",
|
||||
GObject.BindingFlags.SYNC_CREATE,
|
||||
)
|
||||
|
||||
def __create_widget_func(self, item):
|
||||
if isinstance(item, CmbVersionNotification):
|
||||
view = CmbVersionNotificationView(notification=item)
|
||||
elif isinstance(item, CmbMessageNotification):
|
||||
view = CmbMessageNotificationView(notification=item)
|
||||
elif isinstance(item, CmbPollNotification):
|
||||
view = CmbPollNotificationView(notification=item)
|
||||
|
||||
return CmbNotificationListRow(view=view)
|
26
cambalache/cmb_notification_list_view.ui
Normal file
26
cambalache/cmb_notification_list_view.ui
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_notification_list_view.ui -->
|
||||
<requires lib="gtk" version="4.6"/>
|
||||
<template class="CmbNotificationListView" parent="GtkBox">
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="propagate-natural-height">True</property>
|
||||
<property name="propagate-natural-width">True</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="list_box">
|
||||
<property name="activate-on-single-click">False</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<property name="show-separators">True</property>
|
||||
<style>
|
||||
<class name="notifications"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@ -62,7 +62,6 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
self.__signals_dict = None
|
||||
self.__data = None
|
||||
self.__data_dict = None
|
||||
self.position_layout_property = None
|
||||
self.inline_property_id = None
|
||||
self.version_warning = None
|
||||
self.__is_template = False
|
||||
@ -207,10 +206,6 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
info=info,
|
||||
)
|
||||
|
||||
# Keep a reference to the position layout property
|
||||
if info.is_position:
|
||||
self.position_layout_property = prop
|
||||
|
||||
self.__layout.append(prop)
|
||||
|
||||
# Dictionary of properties
|
||||
@ -335,7 +330,7 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
|
||||
project.db.execute(
|
||||
"UPDATE object SET parent_id=?, position=? WHERE ui_id=? AND object_id=?;",
|
||||
(new_parent_id, new_position, ui_id, object_id)
|
||||
(new_parent_id, new_position or 0, ui_id, object_id)
|
||||
)
|
||||
|
||||
# Update children positions in old parent
|
||||
@ -463,11 +458,17 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
def remove_data(self, data):
|
||||
try:
|
||||
assert data.get_id_string() in self.data_dict
|
||||
|
||||
self.project.history_push(
|
||||
_("Remove {key} from {name}").format(key=data.info.key, name=self.display_name_type)
|
||||
)
|
||||
|
||||
self.project.db.execute(
|
||||
"DELETE FROM object_data WHERE ui_id=? AND object_id=? AND owner_id=? AND data_id=? AND id=?;",
|
||||
(self.ui_id, self.object_id, data.owner_id, data.data_id, data.id),
|
||||
)
|
||||
self.project.db.commit()
|
||||
self.project.history_pop()
|
||||
except Exception as e:
|
||||
logger.warning(f"{self} Error removing data {data}: {e}")
|
||||
return False
|
||||
@ -535,23 +536,6 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
# Set new position
|
||||
db.execute("UPDATE object SET position=? WHERE ui_id=? AND object_id=?;", (position, self.ui_id, child.object_id))
|
||||
|
||||
# Update position layout property (Example GtkBox position in Gtk3)
|
||||
if child.position_layout_property:
|
||||
db.execute(
|
||||
"""
|
||||
UPDATE object_layout_property AS olp SET value=o.position
|
||||
FROM object AS o
|
||||
WHERE
|
||||
o.ui_id=? AND
|
||||
o.parent_id=? AND
|
||||
olp.ui_id=o.ui_id AND
|
||||
olp.object_id=o.parent_id AND
|
||||
olp.child_id=o.object_id AND
|
||||
olp.property_id=?;
|
||||
""",
|
||||
(self.ui_id, self.object_id, child.position_layout_property.property_id)
|
||||
)
|
||||
|
||||
db.ignore_check_constraints = False
|
||||
|
||||
list_position = child.list_position
|
||||
@ -562,8 +546,10 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
self.items_changed(list_position, 0, 1)
|
||||
self.items_changed(old_list_position+1, 1, 0)
|
||||
else:
|
||||
if old_list_position != list_position:
|
||||
self.items_changed(old_list_position, 1, 0)
|
||||
self.items_changed(list_position, 0, 1)
|
||||
|
||||
self.project._ignore_selection = False
|
||||
|
||||
self.project.history_pop()
|
||||
@ -613,8 +599,11 @@ class CmbObject(CmbBaseObject, Gio.ListModel):
|
||||
display_name = _("{name} (template)").format(name=name)
|
||||
else:
|
||||
inline_prop = self.inline_property_id
|
||||
internal = self.internal
|
||||
if inline_prop:
|
||||
display_name = f"{type_id} <b>{inline_prop}</b> <i>{name}</i>"
|
||||
elif internal:
|
||||
display_name = f"{type_id} <b>{internal}</b> <i>{name}</i>"
|
||||
else:
|
||||
display_name = f"{type_id} <i>{name}</i>"
|
||||
|
||||
|
@ -27,7 +27,7 @@ from gi.repository import GObject
|
||||
|
||||
from .cmb_objects_base import CmbBaseObjectData
|
||||
from .cmb_type_info import CmbTypeDataInfo
|
||||
from cambalache import getLogger
|
||||
from cambalache import getLogger, _
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
@ -194,11 +194,17 @@ class CmbObjectData(CmbBaseObjectData):
|
||||
def remove_data(self, data):
|
||||
try:
|
||||
assert data in self.children
|
||||
|
||||
self.project.history_push(
|
||||
_("Remove {key} from {name}").format(key=data.info.key, name=self.object.display_name_type)
|
||||
)
|
||||
|
||||
self.project.db.execute(
|
||||
"DELETE FROM object_data WHERE ui_id=? AND object_id=? AND owner_id=? AND data_id=? AND id=?;",
|
||||
(self.ui_id, self.object_id, data.owner_id, data.data_id, data.id),
|
||||
)
|
||||
self.project.db.commit()
|
||||
self.project.history_pop()
|
||||
except Exception as e:
|
||||
logger.warning(f"{self} Error removing data {data}: {e}")
|
||||
return False
|
||||
|
@ -31,6 +31,12 @@ from .control import cmb_create_editor
|
||||
from cambalache import _
|
||||
|
||||
|
||||
# Everyone knows that debugging is twice as hard as writing a program in the first place.
|
||||
# So if you’re as clever as you can be when you write it, how will you ever debug it?
|
||||
# -- Brian Kernighan, 1974
|
||||
#
|
||||
# TODO: rewrite this!
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_object_data_editor.ui")
|
||||
class CmbObjectDataEditor(Gtk.Box):
|
||||
__gtype_name__ = "CmbObjectDataEditor"
|
||||
@ -69,7 +75,7 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
def __on_remove_clicked(self, button):
|
||||
if self.info:
|
||||
self.object.remove_data(self.__data)
|
||||
else:
|
||||
elif self.__data:
|
||||
self.__data.parent.remove_data(self.__data)
|
||||
|
||||
@GObject.Property(type=GObject.Object)
|
||||
@ -138,7 +144,6 @@ class CmbObjectDataEditor(Gtk.Box):
|
||||
self.__update_view()
|
||||
|
||||
def __on_data_removed(self, obj, data):
|
||||
if self.object and self.info:
|
||||
self.__remove_data_editor(data)
|
||||
|
||||
def __ensure_object_data(self, history_message):
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_object_data_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
@ -70,7 +70,6 @@
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="column-spacing">4</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<property name="vexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
@ -260,7 +260,7 @@ It has to be exposed by your application with GtkBuilder expose_object method."
|
||||
hexpand=True,
|
||||
object=obj,
|
||||
data=data,
|
||||
info=None if data else info.data[data_key],
|
||||
info=info.data[data_key],
|
||||
)
|
||||
|
||||
grid.attach(editor, 0, i, 2, 1)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# Cambalache Base Object wrappers
|
||||
#
|
||||
# Copyright (C) 2021-2022 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
|
||||
@ -22,6 +22,8 @@
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject
|
||||
from .cmb_base import CmbBase
|
||||
@ -81,9 +83,7 @@ class CmbBasePropertyInfo(CmbBase):
|
||||
disable_inline_object = GObject.Property(
|
||||
type=bool, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, default=False
|
||||
)
|
||||
is_position = GObject.Property(
|
||||
type=bool, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, default=False
|
||||
)
|
||||
deprecated = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
required = GObject.Property(
|
||||
type=bool, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, default=False
|
||||
)
|
||||
@ -113,7 +113,7 @@ class CmbBasePropertyInfo(CmbBase):
|
||||
deprecated_version,
|
||||
translatable,
|
||||
disable_inline_object,
|
||||
is_position,
|
||||
deprecated,
|
||||
required,
|
||||
workspace_default,
|
||||
original_owner_id,
|
||||
@ -134,7 +134,7 @@ class CmbBasePropertyInfo(CmbBase):
|
||||
deprecated_version=deprecated_version,
|
||||
translatable=translatable,
|
||||
disable_inline_object=disable_inline_object,
|
||||
is_position=is_position,
|
||||
deprecated=deprecated,
|
||||
required=required,
|
||||
workspace_default=workspace_default,
|
||||
original_owner_id=original_owner_id,
|
||||
@ -285,6 +285,30 @@ class CmbTypeChildInfo(CmbBase):
|
||||
)
|
||||
|
||||
|
||||
class CmbBaseTypeInternalChildInfo(CmbBase):
|
||||
__gtype_name__ = "CmbBaseTypeInternalChildInfo"
|
||||
|
||||
type_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
internal_child_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
internal_parent_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
internal_type = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
creation_property_id = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, project, type_id, internal_child_id, internal_parent_id, internal_type, creation_property_id):
|
||||
return cls(
|
||||
project=project,
|
||||
type_id=type_id,
|
||||
internal_child_id=internal_child_id,
|
||||
internal_parent_id=internal_parent_id,
|
||||
internal_type=internal_type,
|
||||
creation_property_id=creation_property_id,
|
||||
)
|
||||
|
||||
|
||||
class CmbBaseUI(CmbBase):
|
||||
__gtype_name__ = "CmbBaseUI"
|
||||
|
||||
@ -429,6 +453,97 @@ class CmbBaseCSS(CmbBase):
|
||||
self.db_set("UPDATE css SET is_global=? WHERE (css_id) IS (?);", (self.css_id,), value)
|
||||
|
||||
|
||||
class CmbBaseGResource(CmbBase):
|
||||
__gtype_name__ = "CmbBaseGResource"
|
||||
|
||||
gresource_id = GObject.Property(type=int, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
resource_type = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@classmethod
|
||||
def from_row(
|
||||
cls,
|
||||
project,
|
||||
gresource_id,
|
||||
resource_type,
|
||||
parent_id,
|
||||
position,
|
||||
gresources_filename,
|
||||
gresource_prefix,
|
||||
file_filename,
|
||||
file_compressed,
|
||||
file_preprocess,
|
||||
file_alias,
|
||||
):
|
||||
return cls(project=project, gresource_id=gresource_id)
|
||||
|
||||
@GObject.Property(type=int)
|
||||
def parent_id(self):
|
||||
return self.db_get("SELECT parent_id FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@parent_id.setter
|
||||
def _set_parent_id(self, value):
|
||||
self.db_set("UPDATE gresource SET parent_id=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=int)
|
||||
def position(self):
|
||||
return self.db_get("SELECT position FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@position.setter
|
||||
def _set_position(self, value):
|
||||
self.db_set("UPDATE gresource SET position=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def gresources_filename(self):
|
||||
return self.db_get("SELECT gresources_filename FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@gresources_filename.setter
|
||||
def _set_gresources_filename(self, value):
|
||||
self.db_set("UPDATE gresource SET gresources_filename=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def gresource_prefix(self):
|
||||
return self.db_get("SELECT gresource_prefix FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@gresource_prefix.setter
|
||||
def _set_gresource_prefix(self, value):
|
||||
self.db_set("UPDATE gresource SET gresource_prefix=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def file_filename(self):
|
||||
return self.db_get("SELECT file_filename FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@file_filename.setter
|
||||
def _set_file_filename(self, value):
|
||||
self.db_set("UPDATE gresource SET file_filename=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=bool, default=False)
|
||||
def file_compressed(self):
|
||||
return self.db_get("SELECT file_compressed FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@file_compressed.setter
|
||||
def _set_file_compressed(self, value):
|
||||
self.db_set("UPDATE gresource SET file_compressed=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def file_preprocess(self):
|
||||
return self.db_get("SELECT file_preprocess FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@file_preprocess.setter
|
||||
def _set_file_preprocess(self, value):
|
||||
self.db_set("UPDATE gresource SET file_preprocess=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def file_alias(self):
|
||||
return self.db_get("SELECT file_alias FROM gresource WHERE (gresource_id) IS (?);", (self.gresource_id,))
|
||||
|
||||
@file_alias.setter
|
||||
def _set_file_alias(self, value):
|
||||
self.db_set("UPDATE gresource SET file_alias=? WHERE (gresource_id) IS (?);", (self.gresource_id,), value)
|
||||
|
||||
|
||||
class CmbBaseProperty(CmbBase):
|
||||
__gtype_name__ = "CmbBaseProperty"
|
||||
|
||||
|
118
cambalache/cmb_path.py
Normal file
118
cambalache/cmb_path.py
Normal file
@ -0,0 +1,118 @@
|
||||
#
|
||||
# CmbPath
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gio
|
||||
|
||||
from .cmb_base import CmbBase
|
||||
from cambalache import _, getLogger
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class CmbPath(CmbBase, Gio.ListModel):
|
||||
__gtype_name__ = "CmbPath"
|
||||
|
||||
path_parent = GObject.Property(type=CmbBase, flags=GObject.ParamFlags.READWRITE)
|
||||
path = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# GListModel
|
||||
self.__items = []
|
||||
self.__path_items = {}
|
||||
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return f"CmbPath<{self.path}>"
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def display_name(self):
|
||||
return self.path or _("{n} unsaved files").format(n=self.n_items)
|
||||
|
||||
def get_path_item(self, directory):
|
||||
return self.__path_items.get(directory, None)
|
||||
|
||||
def add_item(self, item):
|
||||
if item in self.__items:
|
||||
return
|
||||
|
||||
display_name = item.display_name
|
||||
is_path = isinstance(item, CmbPath)
|
||||
|
||||
if is_path:
|
||||
self.__path_items[item.path] = item
|
||||
|
||||
i = 0
|
||||
for list_item in self.__items:
|
||||
if is_path:
|
||||
if not isinstance(list_item, CmbPath):
|
||||
break
|
||||
|
||||
if display_name < list_item.display_name:
|
||||
break
|
||||
elif not isinstance(list_item, CmbPath) and display_name < list_item.display_name:
|
||||
break
|
||||
|
||||
i += 1
|
||||
|
||||
item.path_parent = self
|
||||
self.__items.insert(i, item)
|
||||
self.items_changed(i, 0, 1)
|
||||
|
||||
if not self.path:
|
||||
self.notify("display-name")
|
||||
|
||||
def remove_item(self, item):
|
||||
if item not in self.__items:
|
||||
return
|
||||
|
||||
if isinstance(item, CmbPath) and item.path in self.__path_items:
|
||||
del self.__path_items[item.path]
|
||||
|
||||
item.path_parent = None
|
||||
i = self.__items.index(item)
|
||||
self.__items.pop(i)
|
||||
self.items_changed(i, 1, 0)
|
||||
|
||||
if not self.path:
|
||||
self.notify("display-name")
|
||||
|
||||
# GListModel iface
|
||||
@GObject.Property(type=int)
|
||||
def n_items(self):
|
||||
return len(self.__items)
|
||||
|
||||
def do_get_item(self, position):
|
||||
return self.__items[position] if position < len(self.__items) else None
|
||||
|
||||
def do_get_item_type(self):
|
||||
return CmbBase
|
||||
|
||||
def do_get_n_items(self):
|
||||
return self.n_items
|
||||
|
142
cambalache/cmb_poll_notification_view.py
Normal file
142
cambalache/cmb_poll_notification_view.py
Normal file
@ -0,0 +1,142 @@
|
||||
#
|
||||
# CmbPollNotificationView
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import datetime
|
||||
|
||||
from cambalache import _, getLogger
|
||||
from gi.repository import GObject, Gtk
|
||||
from . import utils
|
||||
from .cmb_notification import CmbPollNotification
|
||||
from .cmb_poll_option_check import CmbPollOptionCheck
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_poll_notification_view.ui")
|
||||
class CmbPollNotificationView(Gtk.Box):
|
||||
__gtype_name__ = "CmbPollNotificationView"
|
||||
|
||||
notification = GObject.Property(
|
||||
type=CmbPollNotification, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY
|
||||
)
|
||||
|
||||
# Poll
|
||||
title_label = Gtk.Template.Child()
|
||||
description_label = Gtk.Template.Child()
|
||||
option_box = Gtk.Template.Child()
|
||||
total_label = Gtk.Template.Child()
|
||||
end_date_label = Gtk.Template.Child()
|
||||
refresh_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__option_checks = []
|
||||
self.__updating = False
|
||||
super().__init__(**kwargs)
|
||||
|
||||
notification = self.notification
|
||||
poll = notification.poll
|
||||
active = utils.utcnow() < poll.end_date
|
||||
|
||||
self.title_label.props.label = f"<b>{poll.title}</b>"
|
||||
self.description_label.props.label = poll.description
|
||||
|
||||
close_msg = _("<small>• Closes on {date}</small>") if active else _("<small>• Closed on {date}</small>")
|
||||
end_date = datetime.datetime.fromtimestamp(poll.end_date)
|
||||
self.end_date_label.props.label = close_msg.format(date=end_date.strftime("%x"))
|
||||
self.end_date_label.props.tooltip_text = end_date.strftime("%c")
|
||||
|
||||
first_check = None
|
||||
n_option = 0
|
||||
for option in poll.options:
|
||||
button = CmbPollOptionCheck(option=option, sensitive=active)
|
||||
|
||||
if poll.allowed_votes == 1:
|
||||
if first_check is None:
|
||||
first_check = button
|
||||
else:
|
||||
button.set_group(first_check)
|
||||
|
||||
button.connect("toggled", self.__on_check_button_toggled, n_option)
|
||||
|
||||
self.__option_checks.append(button)
|
||||
self.option_box.append(button)
|
||||
n_option += 1
|
||||
|
||||
self.__update_results()
|
||||
notification.connect("notify", self.__on_poll_notify)
|
||||
|
||||
def __on_check_button_toggled(self, button, n_option):
|
||||
allowed_votes = self.notification.poll.allowed_votes
|
||||
|
||||
if self.__updating or (allowed_votes == 1 and not button.props.active):
|
||||
return
|
||||
|
||||
votes = []
|
||||
for i, check in enumerate(self.__option_checks):
|
||||
if check.props.active:
|
||||
votes.append(i)
|
||||
|
||||
if allowed_votes > 1:
|
||||
not_done = len(votes) < allowed_votes
|
||||
for i, check in enumerate(self.__option_checks):
|
||||
if not_done:
|
||||
check.set_sensitive(True)
|
||||
elif not check.props.active:
|
||||
check.set_sensitive(False)
|
||||
|
||||
self.notification.center.poll_vote(self.notification, votes)
|
||||
|
||||
def __on_poll_notify(self, notification, pspec):
|
||||
if pspec.name in ["my-votes", "results"]:
|
||||
self.__update_results()
|
||||
|
||||
def __update_results(self):
|
||||
notification = self.notification
|
||||
results = notification.results
|
||||
my_votes = notification.my_votes
|
||||
|
||||
if not results or not my_votes:
|
||||
self.total_label.props.label = ""
|
||||
for check in self.__option_checks:
|
||||
check.fraction = -1
|
||||
return
|
||||
|
||||
self.__updating = True
|
||||
|
||||
votes = results.votes
|
||||
total = results.total
|
||||
|
||||
for i, check in enumerate(self.__option_checks):
|
||||
check.set_active(i in my_votes)
|
||||
check.fraction = votes[i] / total if total else 0
|
||||
|
||||
self.total_label.props.label = _("<small>• {total} vote</small>").format(total=results.total)
|
||||
|
||||
self.__updating = False
|
||||
|
||||
@Gtk.Template.Callback("on_refresh_button_clicked")
|
||||
def __on_refresh_button_clicked(self, button):
|
||||
self.notification.center.poll_refresh_results(self.notification)
|
||||
|
64
cambalache/cmb_poll_notification_view.ui
Normal file
64
cambalache/cmb_poll_notification_view.ui
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_poll_notification_view.ui -->
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbPollNotificationView" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="description_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="option_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<property name="vexpand-set">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="refresh_button">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="label"><small>Refresh</small></property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="clicked" handler="on_refresh_button_clicked"/>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="compact"/>
|
||||
<class name="link"/>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="total_label">
|
||||
<property name="use-markup">True</property>
|
||||
<style>
|
||||
<class name="link"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="end_date_label">
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
76
cambalache/cmb_poll_option_check.py
Normal file
76
cambalache/cmb_poll_option_check.py
Normal file
@ -0,0 +1,76 @@
|
||||
#
|
||||
# CmbPollOptionCheck
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from cambalache import getLogger
|
||||
from gi.repository import GLib, GObject, Gtk
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_poll_option_check.ui")
|
||||
class CmbPollOptionCheck(Gtk.CheckButton):
|
||||
__gtype_name__ = "CmbPollOptionCheck"
|
||||
|
||||
label = Gtk.Template.Child()
|
||||
bar = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__fraction = None
|
||||
self.__tick_id = None
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def option(self):
|
||||
return self.label.props.label
|
||||
|
||||
@option.setter
|
||||
def _set_option(self, option):
|
||||
self.label.props.label = option
|
||||
|
||||
@GObject.Property(type=float)
|
||||
def fraction(self):
|
||||
return self.__fraction
|
||||
|
||||
@fraction.setter
|
||||
def _set_fraction(self, fraction):
|
||||
self.__fraction = fraction
|
||||
|
||||
if fraction < 0:
|
||||
self.bar.props.visible = False
|
||||
else:
|
||||
self.bar.props.visible = True
|
||||
if self.__tick_id is None:
|
||||
self.__tick_id = self.add_tick_callback(self.__update_fraction)
|
||||
|
||||
def __update_fraction(self, widget, frame_clock):
|
||||
if self.bar.props.fraction < self.__fraction:
|
||||
self.bar.props.fraction = min(self.__fraction, self.bar.props.fraction + 0.08)
|
||||
elif self.bar.props.fraction > self.__fraction:
|
||||
self.bar.props.fraction = max(self.__fraction, self.bar.props.fraction - 0.08)
|
||||
else:
|
||||
self.__tick_id = None
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
return GLib.SOURCE_CONTINUE
|
23
cambalache/cmb_poll_option_check.ui
Normal file
23
cambalache/cmb_poll_option_check.ui
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name r.ui -->
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="CmbPollOptionCheck" parent="GtkCheckButton">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="bar"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,9 @@ from gi.repository import GObject
|
||||
from .cmb_objects_base import CmbBaseProperty
|
||||
from .cmb_property_info import CmbPropertyInfo
|
||||
from . import utils
|
||||
from cambalache import _
|
||||
from cambalache import _, getLogger
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class CmbProperty(CmbBaseProperty):
|
||||
@ -64,15 +66,96 @@ class CmbProperty(CmbBaseProperty):
|
||||
|
||||
@value.setter
|
||||
def _set_value(self, value):
|
||||
self.__update_values(value, self.bind_property)
|
||||
self.__update_values(value, self.translatable, self.translation_context, self.translation_comments, self.bind_property)
|
||||
|
||||
@GObject.Property(type=bool, default=False)
|
||||
def translatable(self):
|
||||
return super().translatable
|
||||
|
||||
@translatable.setter
|
||||
def _set_translatable(self, value):
|
||||
self.__update_values(self.value, value, self.translation_context, self.translation_comments, self.bind_property)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def translation_context(self):
|
||||
return self.db_get(
|
||||
"SELECT translation_context FROM object_property WHERE (ui_id, object_id, owner_id, property_id) IS (?, ?, ?, ?);",
|
||||
(
|
||||
self.ui_id,
|
||||
self.object_id,
|
||||
self.owner_id,
|
||||
self.property_id,
|
||||
),
|
||||
)
|
||||
|
||||
@translation_context.setter
|
||||
def _set_translation_context(self, value):
|
||||
self.__update_values(self.value, self.translatable, value, self.translation_comments, self.bind_property)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def translation_comments(self):
|
||||
return self.db_get(
|
||||
"SELECT translation_comments FROM object_property WHERE (ui_id, object_id, owner_id, property_id) IS (?, ?, ?, ?);",
|
||||
(
|
||||
self.ui_id,
|
||||
self.object_id,
|
||||
self.owner_id,
|
||||
self.property_id,
|
||||
),
|
||||
)
|
||||
|
||||
@translation_comments.setter
|
||||
def _set_translation_comments(self, value):
|
||||
self.__update_values(self.value, self.translatable, self.translation_context, value, self.bind_property)
|
||||
|
||||
def reset(self):
|
||||
if self.info.internal_child:
|
||||
self.project.history_push(_("Unset {obj} {prop} {prop_type}").format(**self.__get_msgs()))
|
||||
|
||||
self.project.db.execute(
|
||||
"DELETE FROM object_property WHERE ui_id=? AND object_id=? AND owner_id=? AND property_id=?;",
|
||||
(self.ui_id, self.object_id, self.owner_id, self.property_id),
|
||||
)
|
||||
self.__update_internal_child()
|
||||
|
||||
def __update_values(self, value, bind_property):
|
||||
if self.info.internal_child:
|
||||
self.project.history_pop()
|
||||
|
||||
def __update_internal_child(self):
|
||||
internal_info = self.info.internal_child
|
||||
if internal_info and internal_info.internal_parent_id:
|
||||
logger.warning("Adding an internal child within an internal child automatically is not implemented")
|
||||
return
|
||||
elif internal_info is None:
|
||||
return
|
||||
|
||||
value = self.value
|
||||
child_id = self.db_get(
|
||||
"SELECT object_id FROM object WHERE ui_id=? AND parent_id=? AND internal=?",
|
||||
(self.ui_id, self.object_id, internal_info.internal_child_id)
|
||||
)
|
||||
|
||||
if value and not child_id:
|
||||
self.project.add_object(
|
||||
self.ui_id,
|
||||
internal_info.internal_type,
|
||||
parent_id=self.object_id,
|
||||
internal=internal_info.internal_child_id
|
||||
)
|
||||
elif child_id:
|
||||
internal_child = self.project.get_object_by_id(self.ui_id, child_id)
|
||||
if internal_child:
|
||||
self.project.remove_object(internal_child, allow_internal_removal=True)
|
||||
|
||||
def __get_msgs(self, value=None):
|
||||
return {
|
||||
"obj": self.object.display_name_type,
|
||||
"prop": self.property_id,
|
||||
"prop_type": _("property"),
|
||||
"value": str(value)
|
||||
}
|
||||
|
||||
def __update_values(self, value, translatable, translation_context, translation_comments, bind_property):
|
||||
c = self.project.db.cursor()
|
||||
|
||||
bind_source_id, bind_owner_id, bind_property_id = (None, None, None)
|
||||
@ -82,15 +165,22 @@ class CmbProperty(CmbBaseProperty):
|
||||
bind_property_id = bind_property.property_id
|
||||
|
||||
if (
|
||||
value is None or value == self.info.default_value or (self.info.is_object and value == 0)
|
||||
) and bind_property is None:
|
||||
(value is None or value == self.info.default_value or (self.info.is_object and value == 0)) and
|
||||
bind_property is None and
|
||||
not translatable and
|
||||
translation_context is None and
|
||||
translation_comments is None
|
||||
):
|
||||
self.reset()
|
||||
else:
|
||||
if (
|
||||
value is None
|
||||
and bind_source_id == self.bind_source_id
|
||||
and bind_owner_id == self.bind_owner_id
|
||||
and bind_property_id == self.bind_property_id
|
||||
value == self.value and
|
||||
translatable == self.translatable and
|
||||
translation_context == self.translation_context and
|
||||
translation_comments == self.translation_comments and
|
||||
bind_source_id == self.bind_source_id and
|
||||
bind_owner_id == self.bind_owner_id and
|
||||
bind_property_id == self.bind_property_id
|
||||
):
|
||||
return
|
||||
|
||||
@ -101,14 +191,23 @@ class CmbProperty(CmbBaseProperty):
|
||||
)
|
||||
|
||||
if count:
|
||||
if self.info.internal_child:
|
||||
self.project.history_push(_("Update {obj} {prop} {prop_type} to {value}").format(**self.__get_msgs(value)))
|
||||
|
||||
c.execute(
|
||||
"""
|
||||
UPDATE object_property
|
||||
SET value=?, bind_source_id=?, bind_owner_id=?, bind_property_id=?
|
||||
SET
|
||||
value=?,
|
||||
translatable=?, translation_context=?, translation_comments=?,
|
||||
bind_source_id=?, bind_owner_id=?, bind_property_id=?
|
||||
WHERE ui_id=? AND object_id=? AND owner_id=? AND property_id=?;
|
||||
""",
|
||||
(
|
||||
value,
|
||||
translatable,
|
||||
translation_context,
|
||||
translation_comments,
|
||||
bind_source_id,
|
||||
bind_owner_id,
|
||||
bind_property_id,
|
||||
@ -119,11 +218,19 @@ class CmbProperty(CmbBaseProperty):
|
||||
),
|
||||
)
|
||||
else:
|
||||
if self.info.internal_child:
|
||||
self.project.history_push(_("Set {obj} {prop} {prop_type} to {value}").format(**self.__get_msgs(value)))
|
||||
|
||||
c.execute(
|
||||
"""
|
||||
INSERT INTO object_property
|
||||
(ui_id, object_id, owner_id, property_id, value, bind_source_id, bind_owner_id, bind_property_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
||||
(
|
||||
ui_id, object_id, owner_id, property_id,
|
||||
value,
|
||||
translatable, translation_context, translation_comments,
|
||||
bind_source_id, bind_owner_id, bind_property_id
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
""",
|
||||
(
|
||||
self.ui_id,
|
||||
@ -131,12 +238,20 @@ class CmbProperty(CmbBaseProperty):
|
||||
self.owner_id,
|
||||
self.property_id,
|
||||
value,
|
||||
translatable,
|
||||
translation_context,
|
||||
translation_comments,
|
||||
bind_source_id,
|
||||
bind_owner_id,
|
||||
bind_property_id,
|
||||
),
|
||||
)
|
||||
|
||||
self.__update_internal_child()
|
||||
|
||||
if self.info.internal_child:
|
||||
self.project.history_pop()
|
||||
|
||||
if self._init is False:
|
||||
self.object._property_changed(self)
|
||||
|
||||
@ -163,7 +278,7 @@ class CmbProperty(CmbBaseProperty):
|
||||
|
||||
@bind_property.setter
|
||||
def _set_bind_property(self, bind_property):
|
||||
self.__update_values(self.value, bind_property)
|
||||
self.__update_values(self.value, self.translatable, self.translation_context, self.translation_comments, bind_property)
|
||||
self.project._object_property_binding_changed(self.object, self)
|
||||
|
||||
def _update_version_warning(self):
|
||||
|
@ -23,6 +23,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject
|
||||
from .cmb_objects_base import CmbBasePropertyInfo
|
||||
|
||||
from cambalache import getLogger
|
||||
@ -31,6 +32,8 @@ logger = getLogger(__name__)
|
||||
|
||||
|
||||
class CmbPropertyInfo(CmbBasePropertyInfo):
|
||||
internal_child = GObject.Property(type=GObject.GObject, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
@ -138,13 +138,17 @@ class CmbSignalEditor(Gtk.Box):
|
||||
if data_obj:
|
||||
signal.user_data = data_obj.object_id
|
||||
name = data_obj.name
|
||||
signal.swap = True
|
||||
else:
|
||||
signal.user_data = 0
|
||||
signal.swap = False
|
||||
self.treestore[iter_][Col.SWAP.value] = signal.swap
|
||||
name = ""
|
||||
|
||||
self.treestore[iter_][Col.USER_DATA.value] = name
|
||||
else:
|
||||
signal.user_data = 0
|
||||
signal.swap = False
|
||||
self.treestore[iter_][Col.USER_DATA.value] = ""
|
||||
|
||||
@Gtk.Template.Callback("on_swap_toggled")
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_signal_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
@ -37,9 +37,6 @@
|
||||
<property name="focusable">1</property>
|
||||
<property name="model">treestore</property>
|
||||
<property name="tooltip-column">9</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="signal_id_column">
|
||||
<property name="min-width">64</property>
|
||||
|
266
cambalache/cmb_tree_expander.py
Normal file
266
cambalache/cmb_tree_expander.py
Normal file
@ -0,0 +1,266 @@
|
||||
#
|
||||
# CmbTreeExpander
|
||||
#
|
||||
# Copyright (C) 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gdk, Gtk, Graphene
|
||||
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_css import CmbCSS
|
||||
from .cmb_path import CmbPath
|
||||
from cambalache import _
|
||||
|
||||
|
||||
class CmbTreeExpander(Gtk.TreeExpander):
|
||||
__gtype_name__ = "CmbTreeExpander"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.__project = None
|
||||
self.__drop_before = None
|
||||
|
||||
self.label = Gtk.Inscription(hexpand=True)
|
||||
self.set_child(self.label)
|
||||
|
||||
self.__parent = None
|
||||
self.__drag_source = None
|
||||
self.__drop_target = None
|
||||
|
||||
def update_bind(self):
|
||||
item = self.props.item
|
||||
|
||||
self.__parent = self.props.parent
|
||||
# Drag source
|
||||
self.__drag_source = Gtk.DragSource()
|
||||
self.__drag_source.connect("prepare", self.__on_drag_prepare)
|
||||
self.__drag_source.connect("drag-begin", self.__on_drag_begin)
|
||||
self.__parent.add_controller(self.__drag_source)
|
||||
|
||||
# Drop target
|
||||
self.__drop_target = Gtk.DropTarget.new(type=GObject.TYPE_NONE, actions=Gdk.DragAction.COPY)
|
||||
self.__drop_target.set_gtypes([CmbObject, CmbUI])
|
||||
self.__drop_target.connect("accept", self.__on_drop_accept)
|
||||
self.__drop_target.connect("motion", self.__on_drop_motion)
|
||||
self.__drop_target.connect("drop", self.__on_drop_drop)
|
||||
self.__parent.add_controller(self.__drop_target)
|
||||
|
||||
# Handle label
|
||||
self.__update_label(item)
|
||||
item.connect("notify::display-name", self.__on_item_display_name_notify)
|
||||
|
||||
self.__project = item.project
|
||||
|
||||
if isinstance(item, CmbCSS):
|
||||
self.props.hide_expander = True
|
||||
return
|
||||
elif isinstance(item, CmbPath):
|
||||
self.props.hide_expander = False
|
||||
self.add_css_class("cmb-path" if item.path else "cmb-unsaved-path")
|
||||
return
|
||||
|
||||
self.props.hide_expander = item.props.n_items == 0
|
||||
item.connect("notify::n-items", self.__on_item_n_items_notify)
|
||||
|
||||
def clear_bind(self):
|
||||
item = self.props.item
|
||||
|
||||
if self.__parent:
|
||||
self.__parent.remove_controller(self.__drag_source)
|
||||
self.__parent.remove_controller(self.__drop_target)
|
||||
self.__parent = None
|
||||
self.__drag_source = None
|
||||
self.__drop_target = None
|
||||
|
||||
self.remove_css_class("cmb-path")
|
||||
self.remove_css_class("cmb-unsaved-path")
|
||||
|
||||
item.disconnect_by_func(self.__on_item_display_name_notify)
|
||||
|
||||
if isinstance(item, CmbCSS) or isinstance(item, CmbPath):
|
||||
return
|
||||
|
||||
item.disconnect_by_func(self.__on_item_n_items_notify)
|
||||
|
||||
def __on_item_n_items_notify(self, item, pspec):
|
||||
self.props.hide_expander = item.props.n_items == 0
|
||||
|
||||
def __on_item_display_name_notify(self, item, pspec):
|
||||
self.__update_label(item)
|
||||
|
||||
def __update_label(self, item):
|
||||
self.label.set_markup(item.props.display_name or "")
|
||||
|
||||
# Drop target callbacks
|
||||
def __get_drop_before(self, widget, x, y):
|
||||
h = widget.get_height()
|
||||
|
||||
if y < h/4:
|
||||
return True
|
||||
|
||||
if y > h * 0.8:
|
||||
return False
|
||||
|
||||
return None
|
||||
|
||||
def __on_object_drop_accept(self, drop, item):
|
||||
origin_item = drop.get_drag()._item
|
||||
|
||||
if origin_item == item:
|
||||
return None
|
||||
|
||||
if not isinstance(item, CmbObject):
|
||||
return None
|
||||
|
||||
# Ignore if its the same parent
|
||||
if origin_item.parent_id == item.object_id:
|
||||
return None
|
||||
|
||||
return origin_item
|
||||
|
||||
def __on_drop_accept(self, target, drop):
|
||||
item = self.props.item
|
||||
origin_item = drop.get_drag()._item
|
||||
|
||||
if isinstance(item, CmbObject):
|
||||
origin_item = self.__on_object_drop_accept(drop, item)
|
||||
|
||||
self.__drop_before = None
|
||||
|
||||
if origin_item is None or item.parent is None:
|
||||
return False
|
||||
|
||||
return self.__project._check_can_add(origin_item.type_id, item.parent.type_id)
|
||||
elif isinstance(item, CmbUI):
|
||||
if origin_item == item:
|
||||
return False
|
||||
|
||||
# Ignore if its the same UI and item is already a toplevel
|
||||
if origin_item.ui_id == item.ui_id and origin_item.parent_id is None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __on_drop_motion(self, target, x, y):
|
||||
item = self.props.item
|
||||
|
||||
if isinstance(item, CmbObject):
|
||||
row_widget = target.get_widget()
|
||||
|
||||
drop_before = self.__get_drop_before(row_widget, x, y)
|
||||
|
||||
if self.__drop_before == drop_before:
|
||||
return Gdk.DragAction.COPY
|
||||
|
||||
row_widget.remove_css_class("drop-before")
|
||||
row_widget.remove_css_class("drop-after")
|
||||
|
||||
self.__drop_before = drop_before
|
||||
|
||||
if drop_before is not None:
|
||||
row_widget.add_css_class("drop-before" if drop_before else "drop-after")
|
||||
|
||||
return Gdk.DragAction.COPY
|
||||
|
||||
def __on_drop_drop(self, target, origin_item, x, y):
|
||||
row_widget = target.get_widget()
|
||||
item = self.props.item
|
||||
|
||||
if isinstance(item, CmbObject):
|
||||
drop_before = self.__get_drop_before(row_widget, x, y)
|
||||
|
||||
if drop_before is None:
|
||||
# TODO: handle dragging from one UI to another
|
||||
if origin_item.ui_id != item.ui_id:
|
||||
return
|
||||
|
||||
if origin_item.parent_id != item.object_id:
|
||||
self.__project.history_push(
|
||||
_("Move {name} to {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
)
|
||||
origin_item.parent_id = item.object_id
|
||||
self.__project.history_pop()
|
||||
|
||||
return
|
||||
|
||||
if origin_item.parent_id != item.parent_id:
|
||||
if drop_before:
|
||||
msg = _("Move {name} before {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
else:
|
||||
msg = _("Move {name} after {target}").format(name=origin_item.display_name, target=item.display_name)
|
||||
|
||||
self.__project.history_push(msg)
|
||||
|
||||
origin_item.parent_id = item.parent_id
|
||||
else:
|
||||
msg = None
|
||||
|
||||
parent = item.parent
|
||||
|
||||
origin_position = origin_item.position
|
||||
target_position = item.position
|
||||
|
||||
if origin_position > target_position:
|
||||
if drop_before:
|
||||
position = item.position
|
||||
else:
|
||||
position = item.position + 1
|
||||
else:
|
||||
if drop_before:
|
||||
position = item.position - 1
|
||||
else:
|
||||
position = item.position
|
||||
|
||||
parent.reorder_child(origin_item, position)
|
||||
|
||||
if msg:
|
||||
self.__project.history_pop()
|
||||
|
||||
self.__project.set_selection([origin_item])
|
||||
elif isinstance(item, CmbUI):
|
||||
if origin_item.ui_id == item.ui_id:
|
||||
self.__project.history_push(_("Move {name} as toplevel").format(name=origin_item.display_name))
|
||||
origin_item.parent_id = 0
|
||||
self.__project.history_pop()
|
||||
else:
|
||||
# TODO: Use copy/paste to move across UI files
|
||||
pass
|
||||
|
||||
# Drag Source callbacks
|
||||
def __on_drag_prepare(self, drag_source, x, y):
|
||||
item = self.props.item
|
||||
|
||||
# Only CmbObject start a drag
|
||||
if not isinstance(item, CmbObject):
|
||||
return None
|
||||
|
||||
self.__drag_point = Graphene.Point()
|
||||
self.__drag_point.x = x
|
||||
self.__drag_point.y = y
|
||||
return Gdk.ContentProvider.new_for_value(self.props.item)
|
||||
|
||||
def __on_drag_begin(self, drag_source, drag):
|
||||
drag._item = self.props.item
|
||||
valid, p = self.__parent.compute_point(self.label, self.__drag_point)
|
||||
if valid:
|
||||
drag_source.set_icon(Gtk.WidgetPaintable.new(self.label), p.x, p.y)
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_type_chooser.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.93.0 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_type_chooser_widget.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
|
@ -29,6 +29,7 @@ from .cmb_objects_base import (
|
||||
CmbBaseTypeInfo,
|
||||
CmbBaseTypeDataInfo,
|
||||
CmbBaseTypeDataArgInfo,
|
||||
CmbBaseTypeInternalChildInfo,
|
||||
CmbTypeChildInfo,
|
||||
CmbSignalInfo,
|
||||
)
|
||||
@ -59,6 +60,15 @@ class CmbTypeDataInfo(CmbBaseTypeDataInfo):
|
||||
return f"CmbTypeDataArgInfo<{self.owner_id}>::{self.key}"
|
||||
|
||||
|
||||
class CmbTypeInternalChildInfo(CmbBaseTypeInternalChildInfo):
|
||||
def __init__(self, **kwargs):
|
||||
self.children = {}
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return f"CmbTypeInternalChildInfo<{self.type_id}>::{self.internal_child_id}"
|
||||
|
||||
|
||||
class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
__gtype_name__ = "CmbTypeInfo"
|
||||
|
||||
@ -76,6 +86,7 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
self.properties = self.__init_properties_signals(CmbPropertyInfo, "property")
|
||||
self.signals = self.__init_properties_signals(CmbSignalInfo, "signal")
|
||||
self.data = self.__init_data()
|
||||
self.internal_children = self.__init_internal_children()
|
||||
self.child_constraint, self.child_type_shortcuts = self.__init_child_constraint()
|
||||
|
||||
if self.parent_id == "enum":
|
||||
@ -144,7 +155,7 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
|
||||
c = self.project.db.cursor()
|
||||
for row in c.execute(f"SELECT * FROM {table} WHERE owner_id=? ORDER BY {table}_id;", (self.type_id,)):
|
||||
retval[row[1]] = Klass.from_row(self, *row)
|
||||
retval[row[1]] = Klass.from_row(self.project, *row)
|
||||
|
||||
c.close()
|
||||
return retval
|
||||
@ -153,14 +164,14 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
args = {}
|
||||
children = {}
|
||||
parent_id = parent_id if parent_id is not None else 0
|
||||
retval = CmbTypeDataInfo.from_row(self, owner_id, data_id, parent_id, key, type_id, translatable)
|
||||
retval = CmbTypeDataInfo.from_row(self.project, owner_id, data_id, parent_id, key, type_id, translatable)
|
||||
|
||||
c = self.project.db.cursor()
|
||||
|
||||
# Collect Arguments
|
||||
for row in c.execute("SELECT * FROM type_data_arg WHERE owner_id=? AND data_id=?;", (owner_id, data_id)):
|
||||
_key = row[2]
|
||||
args[_key] = CmbTypeDataArgInfo.from_row(self, *row)
|
||||
args[_key] = CmbTypeDataArgInfo.from_row(self.project, *row)
|
||||
|
||||
# Recurse children
|
||||
for row in c.execute("SELECT * FROM type_data WHERE owner_id=? AND parent_id=?;", (owner_id, data_id)):
|
||||
@ -187,6 +198,52 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
c.close()
|
||||
return retval
|
||||
|
||||
def __type_get_internal_child(self, type_id, internal_child_id, internal_parent_id, internal_type, creation_property_id):
|
||||
retval = CmbTypeInternalChildInfo.from_row(
|
||||
self.project,
|
||||
type_id,
|
||||
internal_child_id,
|
||||
internal_parent_id,
|
||||
internal_type,
|
||||
creation_property_id
|
||||
)
|
||||
children = {}
|
||||
|
||||
c = self.project.db.cursor()
|
||||
|
||||
# Recurse children
|
||||
for row in c.execute(
|
||||
"SELECT * FROM type_internal_child WHERE type_id=? AND internal_parent_id=?;",
|
||||
(type_id, internal_child_id)
|
||||
):
|
||||
key = row[1]
|
||||
children[key] = self.__type_get_internal_child(*row)
|
||||
|
||||
c.close()
|
||||
|
||||
retval.children = children
|
||||
|
||||
# Internal child back reference in property
|
||||
if creation_property_id:
|
||||
if creation_property_id in self.properties:
|
||||
self.properties[creation_property_id].internal_child = retval
|
||||
|
||||
return retval
|
||||
|
||||
def __init_internal_children(self):
|
||||
retval = {}
|
||||
|
||||
c = self.project.db.cursor()
|
||||
for row in c.execute(
|
||||
"SELECT * FROM type_internal_child WHERE type_id=? AND internal_parent_id IS NULL ORDER BY internal_child_id;",
|
||||
(self.type_id,)
|
||||
):
|
||||
key = row[1]
|
||||
retval[key] = self.__type_get_internal_child(*row)
|
||||
|
||||
c.close()
|
||||
return retval
|
||||
|
||||
def __init_child_constraint(self):
|
||||
retval = {}
|
||||
shortcuts = []
|
||||
@ -274,7 +331,7 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
|
||||
return False
|
||||
|
||||
def enum_get_value_as_string(self, value):
|
||||
def enum_get_value_as_string(self, value, use_nick=True):
|
||||
if self.parent_id != "enum":
|
||||
return None
|
||||
|
||||
@ -283,7 +340,7 @@ class CmbTypeInfo(CmbBaseTypeInfo):
|
||||
|
||||
# Always use nick as value
|
||||
if value == enum_name or value == enum_nick or value == str(enum_value):
|
||||
return enum_nick
|
||||
return enum_nick if use_nick else enum_value
|
||||
|
||||
return None
|
||||
|
||||
|
@ -23,8 +23,10 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import os
|
||||
from gi.repository import GObject, Gio
|
||||
|
||||
from .cmb_path import CmbPath
|
||||
from .cmb_list_error import CmbListError
|
||||
from .cmb_objects_base import CmbBaseUI, CmbBaseObject
|
||||
from cambalache import getLogger, _
|
||||
@ -37,6 +39,8 @@ class CmbUI(CmbBaseUI, Gio.ListModel):
|
||||
"library-changed": (GObject.SignalFlags.RUN_FIRST, None, (str,)),
|
||||
}
|
||||
|
||||
path_parent = GObject.Property(type=CmbPath, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@ -61,6 +65,10 @@ class CmbUI(CmbBaseUI, Gio.ListModel):
|
||||
def __on_notify(self, obj, pspec):
|
||||
self.project._ui_changed(self, pspec.name)
|
||||
|
||||
# Update display name if one of the following properties changed
|
||||
if pspec.name in ["filename", "template-id"]:
|
||||
self.notify("display-name")
|
||||
|
||||
def list_libraries(self):
|
||||
retval = {}
|
||||
|
||||
@ -124,19 +132,21 @@ class CmbUI(CmbBaseUI, Gio.ListModel):
|
||||
|
||||
c.close()
|
||||
|
||||
@classmethod
|
||||
def get_display_name(cls, ui_id, filename):
|
||||
return os.path.basename(filename) if filename else _("Unnamed {ui_id}").format(ui_id=ui_id)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def display_name(self):
|
||||
if self.filename:
|
||||
return self.filename
|
||||
|
||||
filename = self.filename
|
||||
template_id = self.template_id
|
||||
|
||||
if template_id:
|
||||
if filename is None and template_id:
|
||||
template = self.project.get_object_by_id(self.ui_id, template_id)
|
||||
if template:
|
||||
return template.name
|
||||
|
||||
return _("Unnamed {ui_id}").format(ui_id=self.ui_id)
|
||||
return CmbUI.get_display_name(self.ui_id, filename)
|
||||
|
||||
def __get_infered_target(self, library_id):
|
||||
ui_id = self.ui_id
|
||||
@ -177,9 +187,6 @@ class CmbUI(CmbBaseUI, Gio.ListModel):
|
||||
|
||||
return target
|
||||
|
||||
def export(self):
|
||||
return self.project.export_ui(self)
|
||||
|
||||
# GListModel iface
|
||||
def do_get_item(self, position):
|
||||
ui_id = self.ui_id
|
||||
|
@ -23,8 +23,11 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from gi.repository import GObject, Gtk
|
||||
|
||||
from cambalache import _
|
||||
from .cmb_ui import CmbUI
|
||||
|
||||
|
||||
@ -32,12 +35,8 @@ from .cmb_ui import CmbUI
|
||||
class CmbUIEditor(Gtk.Grid):
|
||||
__gtype_name__ = "CmbUIEditor"
|
||||
|
||||
__gsignals__ = {
|
||||
"remove-ui": (GObject.SignalFlags.RUN_FIRST, None, (CmbUI,)),
|
||||
"export-ui": (GObject.SignalFlags.RUN_FIRST, None, (CmbUI,)),
|
||||
}
|
||||
|
||||
filename = Gtk.Template.Child()
|
||||
format = Gtk.Template.Child()
|
||||
template_id = Gtk.Template.Child()
|
||||
description = Gtk.Template.Child()
|
||||
copyright = Gtk.Template.Child()
|
||||
@ -59,9 +58,6 @@ class CmbUIEditor(Gtk.Grid):
|
||||
|
||||
@object.setter
|
||||
def _set_object(self, obj):
|
||||
if obj == self._object:
|
||||
return
|
||||
|
||||
for binding in self._bindings:
|
||||
binding.unbind()
|
||||
|
||||
@ -82,10 +78,17 @@ class CmbUIEditor(Gtk.Grid):
|
||||
|
||||
self.set_sensitive(True)
|
||||
self.template_id.object = obj
|
||||
self.filename.dirname = obj.project.dirname
|
||||
|
||||
# Set some default name
|
||||
self.filename.unnamed_filename = _("unnamed.ui")
|
||||
if not obj.filename and obj.template_id:
|
||||
template = obj.project.get_object_by_id(obj.ui_id, obj.template_id)
|
||||
if template:
|
||||
self.filename.unnamed_filename = f"{template.name}.ui".lower()
|
||||
|
||||
for field in self.fields:
|
||||
binding = GObject.Object.bind_property(
|
||||
obj,
|
||||
binding = obj.bind_property(
|
||||
field,
|
||||
getattr(self, field),
|
||||
"cmb-value",
|
||||
@ -93,15 +96,42 @@ class CmbUIEditor(Gtk.Grid):
|
||||
)
|
||||
self._bindings.append(binding)
|
||||
|
||||
@Gtk.Template.Callback("on_remove_button_clicked")
|
||||
def __on_remove_button_clicked(self, button):
|
||||
if self.object:
|
||||
self.emit("remove-ui", self.object)
|
||||
if obj.project.target_tk == "gtk-4.0":
|
||||
self.filename.mime_types = "application/x-gtk-builder;text/x-blueprint"
|
||||
|
||||
@Gtk.Template.Callback("on_export_button_clicked")
|
||||
def __on_export_button_clicked(self, button):
|
||||
if self.object:
|
||||
self.emit("export-ui", self.object)
|
||||
# filename -> format
|
||||
binding = obj.bind_property(
|
||||
"filename",
|
||||
self.format,
|
||||
"selected",
|
||||
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL,
|
||||
transform_to=self.__filename_to_format,
|
||||
transform_from=self.__format_to_filename,
|
||||
user_data=obj
|
||||
)
|
||||
self._bindings.append(binding)
|
||||
|
||||
self.format.show()
|
||||
self.format.set_sensitive(bool(obj.filename))
|
||||
else:
|
||||
self.filename.mime_types = "application/x-gtk-builder;application/x-glade"
|
||||
self.format.hide()
|
||||
|
||||
def __filename_to_format(self, binding, source_value, ui):
|
||||
if not source_value:
|
||||
self.format.props.sensitive = False
|
||||
return 0
|
||||
self.format.props.sensitive = True
|
||||
|
||||
return 1 if source_value.endswith(".blp") else 0
|
||||
|
||||
def __format_to_filename(self, binding, target_value, ui):
|
||||
if not ui.filename:
|
||||
self.format.props.sensitive = False
|
||||
return None
|
||||
self.format.props.sensitive = True
|
||||
|
||||
return os.path.splitext(ui.filename)[0] + (".blp" if target_value == 1 else ".ui")
|
||||
|
||||
|
||||
Gtk.WidgetClass.set_css_name(CmbUIEditor, "CmbUIEditor")
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.3 -->
|
||||
<!-- Created with Cambalache 0.97.1 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_ui_editor.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
@ -27,7 +27,7 @@
|
||||
<property name="label" translatable="yes">Description:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -37,7 +37,7 @@
|
||||
<property name="label" translatable="yes">Copyright:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -47,7 +47,7 @@
|
||||
<property name="label" translatable="yes">Authors:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -57,16 +57,13 @@
|
||||
<property name="label" translatable="yes">Domain:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">5</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="CmbEntry" id="filename">
|
||||
<property name="can-focus">True</property>
|
||||
<object class="CmbFileButton" id="filename">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="placeholder-text" translatable="yes"><file name relative to project></property>
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
@ -81,7 +78,7 @@
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">5</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -98,7 +95,7 @@
|
||||
<property name="min-content-height">96</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -115,7 +112,7 @@
|
||||
<property name="min-content-height">96</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">4</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -127,7 +124,7 @@
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -137,45 +134,7 @@
|
||||
<property name="label" translatable="yes">Template:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="focusable">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<signal name="clicked" handler="on_remove_button_clicked"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">user-trash-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="export_button">
|
||||
<property name="focusable">1</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">Export</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="tooltip-text" translatable="yes">Export</property>
|
||||
<signal name="clicked" handler="on_export_button_clicked"/>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="column-span">2</property>
|
||||
<property name="row">7</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -192,7 +151,7 @@
|
||||
<property name="min-content-height">96</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -202,7 +161,7 @@
|
||||
<property name="label" translatable="yes">Comment:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">6</property>
|
||||
<property name="row">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
@ -219,7 +178,34 @@
|
||||
<property name="min-content-height">96</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">6</property>
|
||||
<property name="row">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Format:</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="format">
|
||||
<property name="halign">start</property>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<property name="strings">Gtk Builder
|
||||
Blueprint</property>
|
||||
</object>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="column-span">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="row-span">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
57
cambalache/cmb_version_notification_view.py
Normal file
57
cambalache/cmb_version_notification_view.py
Normal file
@ -0,0 +1,57 @@
|
||||
#
|
||||
# CmbVersionNotificationView
|
||||
#
|
||||
# Copyright (C) 2025 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from cambalache import _, getLogger
|
||||
from gi.repository import GObject, Gtk
|
||||
from .cmb_notification import CmbVersionNotification
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/cmb_version_notification_view.ui")
|
||||
class CmbVersionNotificationView(Gtk.Box):
|
||||
__gtype_name__ = "CmbVersionNotificationView"
|
||||
|
||||
notification = GObject.Property(
|
||||
type=CmbVersionNotification, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY
|
||||
)
|
||||
|
||||
# Version
|
||||
version_label = Gtk.Template.Child()
|
||||
release_notes_label = Gtk.Template.Child()
|
||||
read_more_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
notification = self.notification
|
||||
self.version_label.props.label = _("<b>Version {version} is available</b>").format(version=notification.version)
|
||||
self.release_notes_label.props.label = notification.release_notes
|
||||
|
||||
if notification.read_more_url:
|
||||
self.read_more_button.props.uri = notification.read_more_url
|
||||
self.read_more_button.show()
|
||||
else:
|
||||
self.read_more_button.hide()
|
50
cambalache/cmb_version_notification_view.ui
Normal file
50
cambalache/cmb_version_notification_view.ui
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_version_notification_view.ui -->
|
||||
<requires lib="gtk" version="4.12"/>
|
||||
<template class="CmbVersionNotificationView" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="version_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="use-markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="release_notes_label">
|
||||
<property name="halign">start</property>
|
||||
<property name="lines">16</property>
|
||||
<property name="max-width-chars">32</property>
|
||||
<property name="use-markup">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<property name="valign">end</property>
|
||||
<child>
|
||||
<object class="GtkLinkButton" id="read_more_button">
|
||||
<property name="label" translatable="yes">Read more...</property>
|
||||
<property name="uri">https://blogs.gnome.org/xjuan/</property>
|
||||
<style>
|
||||
<class name="compact"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLinkButton" id="download_button">
|
||||
<property name="label" translatable="yes">Get it on Flathub</property>
|
||||
<property name="uri">https://flathub.org/apps/ar.xjuan.Cambalache</property>
|
||||
<style>
|
||||
<class name="compact"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@ -39,8 +39,9 @@ from . import config
|
||||
from .cmb_ui import CmbUI
|
||||
from .cmb_object import CmbObject
|
||||
from .cmb_context_menu import CmbContextMenu
|
||||
from cambalache.cmb_blueprint import cmb_blueprint_decompile
|
||||
from . import utils
|
||||
from cambalache import getLogger, _
|
||||
from cambalache import getLogger, _, N_
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
@ -167,7 +168,6 @@ class CmbMerengueProcess(GObject.Object):
|
||||
env = json.loads(os.environ.get("MERENGUE_DEV_ENV", "{}"))
|
||||
env = env | {
|
||||
"GDK_BACKEND": "wayland",
|
||||
"GSK_RENDERER": "cairo",
|
||||
"WAYLAND_DISPLAY": self.wayland_display,
|
||||
}
|
||||
|
||||
@ -219,6 +219,7 @@ class CmbMerengueProcess(GObject.Object):
|
||||
# Encode to binary first, before calculating lenght
|
||||
payload = payload.encode()
|
||||
cmd["payload_length"] = len(payload)
|
||||
logger.debug(f"write_command {command} {len(payload)}")
|
||||
|
||||
if args is not None:
|
||||
cmd["args"] = args
|
||||
@ -233,11 +234,18 @@ class CmbMerengueProcess(GObject.Object):
|
||||
def __socket_write_command(self, cmd, payload=None):
|
||||
# Send command in one line as json
|
||||
output_stream = self.__connection.props.output_stream
|
||||
output_stream.write(json.dumps(cmd).encode())
|
||||
output_stream.write(b"\n")
|
||||
|
||||
def write_data(data):
|
||||
total_bytes = len(data)
|
||||
total_sent = 0
|
||||
while total_sent < total_bytes:
|
||||
total_sent += output_stream.write(data[total_sent:])
|
||||
|
||||
write_data(json.dumps(cmd).encode())
|
||||
write_data(b"\n")
|
||||
|
||||
if payload is not None:
|
||||
output_stream.write(payload)
|
||||
write_data(payload)
|
||||
|
||||
# Flush
|
||||
output_stream.flush()
|
||||
@ -271,9 +279,8 @@ class CmbView(Gtk.Box):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__project = None
|
||||
self.__ui_id = 0
|
||||
self.__ui = None
|
||||
self.__theme = None
|
||||
self.__dark = False
|
||||
|
||||
self.menu = self.__create_context_menu()
|
||||
|
||||
@ -308,12 +315,17 @@ class CmbView(Gtk.Box):
|
||||
if os.path.exists(dirname):
|
||||
shutil.rmtree(dirname)
|
||||
|
||||
def _set_dark_mode(self, dark):
|
||||
self.__dark = dark
|
||||
bg_color = Gdk.RGBA()
|
||||
bg_color.parse("gray18" if dark else "white")
|
||||
def __set_dark_mode(self, dark):
|
||||
valid, bg_color = self.get_style_context().lookup_color('theme_bg_color')
|
||||
if valid:
|
||||
self.compositor.props.bg_color = bg_color
|
||||
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def _set_dark_mode(self, dark):
|
||||
# This needs to be called in an idle because theme_bg_color has not changed at this point
|
||||
GLib.idle_add(self.__set_dark_mode, dark)
|
||||
|
||||
def __merengue_command(self, command, payload=None, args=None):
|
||||
if self.__merengue.merengue_started:
|
||||
self.__merengue.write_command(command, payload, args)
|
||||
@ -325,14 +337,34 @@ class CmbView(Gtk.Box):
|
||||
return self.__project.db.tostring(ui_id, merengue=merengue)
|
||||
|
||||
def __update_view(self):
|
||||
if self.__project and self.__ui_id > 0:
|
||||
if self.__project and self.__ui:
|
||||
if self.stack.props.visible_child_name == "ui_xml":
|
||||
ui = self.__get_ui_xml(self.__ui_id)
|
||||
self.text_view.buffer.set_text(ui)
|
||||
ui_source = self.__get_ui_xml(self.__ui.ui_id)
|
||||
|
||||
if self.__ui.filename and self.__ui.filename.endswith(".blp"):
|
||||
try:
|
||||
ui_source = cmb_blueprint_decompile(ui_source)
|
||||
self.text_view.lang = "blueprint"
|
||||
except Exception as e:
|
||||
ui_source = _("Error exporting project")
|
||||
ui_source += "\n"
|
||||
ui_source += N_(
|
||||
"blueprintcompiler encounter the following error:",
|
||||
"blueprintcompiler encounter the following errors:",
|
||||
len(e.errors)
|
||||
)
|
||||
ui_source += "\n"
|
||||
ui_source += str(e)
|
||||
self.text_view.lang = ""
|
||||
# TODO: forward error to parent to show to user
|
||||
else:
|
||||
self.text_view.lang = "xml"
|
||||
|
||||
self.text_view.buffer.set_text(ui_source)
|
||||
return
|
||||
|
||||
self.text_view.buffer.set_text("")
|
||||
self.__ui_id = 0
|
||||
self.__ui = None
|
||||
|
||||
def __get_ui_dirname(self, ui_id):
|
||||
dirname = GLib.get_home_dir()
|
||||
@ -436,19 +468,23 @@ class CmbView(Gtk.Box):
|
||||
if len(selection) > 0:
|
||||
obj = selection[0]
|
||||
|
||||
if type(obj) not in [CmbUI, CmbObject]:
|
||||
if isinstance(obj, CmbUI):
|
||||
ui = obj
|
||||
elif isinstance(obj, CmbObject):
|
||||
ui = obj.ui
|
||||
else:
|
||||
return
|
||||
|
||||
ui_id = obj.ui_id
|
||||
|
||||
if self.__ui_id != ui_id:
|
||||
self.__ui_id = ui_id
|
||||
self.__merengue_update_ui(ui_id)
|
||||
if self.__ui != ui:
|
||||
self.__ui = ui
|
||||
self.__merengue_update_ui(ui.ui_id)
|
||||
|
||||
objects = self.__get_selection_objects(selection, ui_id)
|
||||
objects = self.__get_selection_objects(selection, ui.ui_id)
|
||||
self.__merengue_command("selection_changed", args={"ui_id": ui_id, "selection": objects})
|
||||
else:
|
||||
self.__ui_id = 0
|
||||
self.__ui = None
|
||||
self.__merengue_update_ui(0)
|
||||
|
||||
self.__update_view()
|
||||
@ -620,7 +656,7 @@ class CmbView(Gtk.Box):
|
||||
self.__merengue_last_exit = None
|
||||
return
|
||||
|
||||
self.__ui_id = 0
|
||||
self.__ui = None
|
||||
self.__merengue.start()
|
||||
|
||||
def __command_selection_changed(self, selection):
|
||||
@ -679,7 +715,7 @@ class CmbView(Gtk.Box):
|
||||
|
||||
self.__load_css_providers()
|
||||
|
||||
self.__ui_id = 0
|
||||
self.__ui = None
|
||||
self.__on_project_selection_changed(self.__project)
|
||||
elif command == "placeholder_selected":
|
||||
self.emit(
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.3 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_view.ui -->
|
||||
<!-- interface-copyright Juan Pablo Ugarte -->
|
||||
|
@ -25,6 +25,7 @@
|
||||
from .cmb_boolean_undefined import CmbBooleanUndefined
|
||||
from .cmb_child_type_combo_box import CmbChildTypeComboBox
|
||||
from .cmb_entry import CmbEntry
|
||||
from .cmb_file_button import CmbFileButton
|
||||
from .cmb_file_entry import CmbFileEntry
|
||||
from .cmb_icon_name_entry import CmbIconNameEntry
|
||||
from .cmb_pixbuf_entry import CmbPixbufEntry
|
||||
|
114
cambalache/control/cmb_file_button.py
Normal file
114
cambalache/control/cmb_file_button.py
Normal file
@ -0,0 +1,114 @@
|
||||
#
|
||||
# CmbFileButton
|
||||
#
|
||||
# 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
|
||||
# License as published by the Free Software Foundation;
|
||||
# version 2.1 of the License.
|
||||
#
|
||||
# library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# Authors:
|
||||
# Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from cambalache import _
|
||||
from gi.repository import GObject, Gio, Gtk
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/ar/xjuan/Cambalache/control/cmb_file_button.ui")
|
||||
class CmbFileButton(Gtk.Button):
|
||||
__gtype_name__ = "CmbFileButton"
|
||||
|
||||
dirname = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
dialog_title = GObject.Property(type=str, default=_("Select filename"), flags=GObject.ParamFlags.READWRITE)
|
||||
accept_label = GObject.Property(type=str, default=_("Select"), flags=GObject.ParamFlags.READWRITE)
|
||||
unnamed_filename = GObject.Property(type=str, flags=GObject.ParamFlags.READWRITE)
|
||||
use_open = GObject.Property(type=bool, default=False, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
label = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.__filename = None
|
||||
self.__filters = None
|
||||
|
||||
@Gtk.Template.Callback("on_button_clicked")
|
||||
def __on_button_clicked(self, button):
|
||||
dialog = Gtk.FileDialog(
|
||||
modal=True,
|
||||
filters=self.__filters,
|
||||
title=self.dialog_title,
|
||||
accept_label=self.accept_label
|
||||
)
|
||||
|
||||
if self.dirname is not None:
|
||||
if self.__filename:
|
||||
fullpath = os.path.join(self.dirname, self.__filename)
|
||||
|
||||
file = Gio.File.new_for_path(fullpath)
|
||||
dialog.set_initial_file(file)
|
||||
|
||||
# See which filter matches the file info and use it as default
|
||||
if file.query_exists(None):
|
||||
info = file.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, Gio.FileQueryInfoFlags.NONE, None)
|
||||
for filter in self.__filters:
|
||||
if filter.match(info):
|
||||
dialog.set_default_filter(filter)
|
||||
break
|
||||
else:
|
||||
dialog.set_initial_folder(Gio.File.new_for_path(self.dirname))
|
||||
if self.unnamed_filename:
|
||||
dialog.set_initial_name(self.unnamed_filename)
|
||||
|
||||
def dialog_callback(dialog, res):
|
||||
try:
|
||||
file = dialog.open_finish(res) if self.use_open else dialog.save_finish(res)
|
||||
self.cmb_value = os.path.relpath(file.get_path(), start=self.dirname)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if self.use_open:
|
||||
dialog.open(self.get_root(), None, dialog_callback)
|
||||
else:
|
||||
dialog.save(self.get_root(), None, dialog_callback)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def cmb_value(self):
|
||||
return self.__filename
|
||||
|
||||
@cmb_value.setter
|
||||
def _set_cmb_value(self, value):
|
||||
if value == self.__filename:
|
||||
return
|
||||
|
||||
self.__filename = value if value is not None else ""
|
||||
self.label.set_label(self.__filename)
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def mime_types(self):
|
||||
if self.__filters:
|
||||
return ";".join([f.props.mime_types for f in self.__filters])
|
||||
return ""
|
||||
|
||||
@mime_types.setter
|
||||
def _set_mime_types(self, value):
|
||||
if value:
|
||||
self.__filters = Gio.ListStore()
|
||||
for mime in value.split(';'):
|
||||
self.__filters.append(Gtk.FileFilter(mime_types=[mime]))
|
||||
else:
|
||||
self.__filters = None
|
34
cambalache/control/cmb_file_button.ui
Normal file
34
cambalache/control/cmb_file_button.ui
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_file_button.ui -->
|
||||
<requires lib="gtk" version="4.12"/>
|
||||
<template class="CmbFileButton" parent="GtkButton">
|
||||
<signal name="clicked" handler="on_button_clicked"/>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="file_icon">
|
||||
<property name="visible">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="ellipsize">start</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label">(None)</property>
|
||||
<property name="width-chars">8</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">folder-open-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@ -34,6 +34,7 @@ class CmbFlagsEntry(Gtk.Entry):
|
||||
id_column = GObject.Property(type=int, default=1, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
text_column = GObject.Property(type=int, default=1, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
value_column = GObject.Property(type=int, default=2, flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
separator = GObject.Property(type=str, default="|", flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.flags = {}
|
||||
@ -84,7 +85,7 @@ class CmbFlagsEntry(Gtk.Entry):
|
||||
for row in self.info.flags:
|
||||
flag_id = row[self.id_column]
|
||||
if self.flags.get(flag_id, False):
|
||||
retval = flag_id if retval is None else f"{retval} | {flag_id}"
|
||||
retval = flag_id if retval is None else f"{retval} {self.separator} {flag_id}"
|
||||
|
||||
return retval if retval is not None else ""
|
||||
|
||||
@ -104,7 +105,7 @@ class CmbFlagsEntry(Gtk.Entry):
|
||||
self._checks[check].props.active = False
|
||||
|
||||
if value:
|
||||
tokens = [t.strip() for t in value.split("|")]
|
||||
tokens = [t.strip() for t in value.split(self.separator)]
|
||||
|
||||
for row in self.info.flags:
|
||||
flag_id = row[self.id_column]
|
||||
|
@ -40,7 +40,8 @@ class CmbSourceView(GtkSource.View):
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def lang(self):
|
||||
return self.buffer.get_language()
|
||||
language = self.buffer.get_language()
|
||||
return language.get_id() if language else ""
|
||||
|
||||
@lang.setter
|
||||
def _set_lang(self, value):
|
||||
@ -49,7 +50,7 @@ class CmbSourceView(GtkSource.View):
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def text(self):
|
||||
return self.buffer.props.text
|
||||
return self.buffer.props.text if len(self.buffer.props.text) else None
|
||||
|
||||
@text.setter
|
||||
def _set_text(self, value):
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Created with Cambalache 0.91.1 -->
|
||||
<!-- Created with Cambalache 0.95.0 -->
|
||||
<interface>
|
||||
<!-- interface-name cmb_translatable_widget.ui -->
|
||||
<!-- interface-copyright Philipp Unger -->
|
||||
|
@ -4,22 +4,23 @@ moduledir = join_paths(modulesdir, 'cambalache', 'control')
|
||||
install_data([
|
||||
'cmb_boolean_undefined.py',
|
||||
'cmb_child_type_combo_box.py',
|
||||
'cmb_entry.py',
|
||||
'cmb_file_entry.py',
|
||||
'cmb_icon_name_entry.py',
|
||||
'cmb_pixbuf_entry.py',
|
||||
'cmb_spin_button.py',
|
||||
'cmb_text_buffer.py',
|
||||
'cmb_toplevel_chooser.py',
|
||||
'cmb_color_entry.py',
|
||||
'cmb_create_editor.py',
|
||||
'cmb_entry.py',
|
||||
'cmb_enum_combo_box.py',
|
||||
'cmb_file_button.py',
|
||||
'cmb_file_entry.py',
|
||||
'cmb_flags_entry.py',
|
||||
'cmb_icon_name_entry.py',
|
||||
'cmb_object_chooser.py',
|
||||
'cmb_object_list_editor.py',
|
||||
'cmb_pixbuf_entry.py',
|
||||
'cmb_source_view.py',
|
||||
'cmb_spin_button.py',
|
||||
'cmb_switch.py',
|
||||
'cmb_text_buffer.py',
|
||||
'cmb_text_view.py',
|
||||
'cmb_toplevel_chooser.py',
|
||||
'cmb_translatable_popover.py',
|
||||
'cmb_translatable_widget.py',
|
||||
'icon_naming_spec.py',
|
||||
|
@ -170,29 +170,19 @@ CREATE TABLE IF NOT EXISTS type_child_constraint (
|
||||
) WITHOUT ROWID;
|
||||
|
||||
|
||||
|
||||
/* Type Tree
|
||||
/* Type Internal Child
|
||||
*
|
||||
* VIEW of ancestors and ifaces by type
|
||||
*/
|
||||
CREATE VIEW IF NOT EXISTS type_tree AS
|
||||
WITH RECURSIVE ancestor(type_id, generation, parent_id) AS (
|
||||
SELECT type_id, 1, parent_id FROM type
|
||||
WHERE parent_id IS NOT NULL AND
|
||||
parent_id != 'interface' AND
|
||||
parent_id != 'enum' AND
|
||||
parent_id != 'flags'
|
||||
UNION ALL
|
||||
SELECT ancestor.type_id, generation + 1, type.parent_id
|
||||
FROM type JOIN ancestor ON type.type_id = ancestor.parent_id
|
||||
WHERE type.parent_id IS NOT NULL
|
||||
)
|
||||
SELECT * FROM ancestor
|
||||
UNION
|
||||
SELECT ancestor.type_id, 0, type_iface.iface_id
|
||||
FROM ancestor JOIN type_iface
|
||||
WHERE ancestor.type_id = type_iface.type_id
|
||||
ORDER BY type_id,generation;
|
||||
CREATE TABLE IF NOT EXISTS type_internal_child (
|
||||
type_id TEXT REFERENCES type ON UPDATE CASCADE,
|
||||
internal_child_id TEXT,
|
||||
internal_parent_id TEXT,
|
||||
internal_type TEXT REFERENCES type ON UPDATE CASCADE,
|
||||
creation_property_id TEXT,
|
||||
PRIMARY KEY(type_id, internal_child_id),
|
||||
FOREIGN KEY(type_id, internal_parent_id) REFERENCES type_internal_child(type_id, internal_child_id)
|
||||
FOREIGN KEY(type_id, creation_property_id) REFERENCES property(owner_id, property_id)
|
||||
) WITHOUT ROWID;
|
||||
|
||||
|
||||
/* Property
|
||||
@ -213,7 +203,7 @@ CREATE TABLE IF NOT EXISTS property (
|
||||
deprecated_version TEXT,
|
||||
translatable BOOLEAN CHECK (type_id IN (NULL, 'gchararray')),
|
||||
disable_inline_object BOOLEAN DEFAULT 0,
|
||||
is_position BOOLEAN DEFAULT 0,
|
||||
deprecated TEXT,
|
||||
required BOOLEAN DEFAULT 0,
|
||||
workspace_default TEXT,
|
||||
original_owner_id TEXT REFERENCES type ON UPDATE CASCADE,
|
||||
|
@ -41,7 +41,7 @@ CREATE TABLE history (
|
||||
command TEXT NOT NULL,
|
||||
range_id INTEGER REFERENCES history,
|
||||
table_name TEXT,
|
||||
column_name TEXT,
|
||||
columns JSON,
|
||||
message TEXT,
|
||||
table_pk JSON,
|
||||
new_values JSON,
|
||||
|
@ -113,6 +113,26 @@ CREATE TABLE css_ui (
|
||||
) WITHOUT ROWID;
|
||||
|
||||
|
||||
/* GResource
|
||||
*
|
||||
*/
|
||||
CREATE TABLE gresource (
|
||||
gresource_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
resource_type TEXT CHECK (resource_type IN ('gresources', 'gresource', 'file')),
|
||||
parent_id INTEGER REFERENCES gresource ON DELETE CASCADE,
|
||||
position INTEGER NOT NULL CHECK (position >= 0),
|
||||
|
||||
gresources_filename TEXT UNIQUE,
|
||||
|
||||
gresource_prefix TEXT UNIQUE,
|
||||
|
||||
file_filename TEXT,
|
||||
file_compressed BOOLEAN,
|
||||
file_preprocess TEXT,
|
||||
file_alias TEXT
|
||||
);
|
||||
|
||||
|
||||
/* Object
|
||||
*
|
||||
* TODO: check type_id is an object
|
||||
|
@ -23,14 +23,22 @@
|
||||
#
|
||||
|
||||
import os
|
||||
import gi
|
||||
import logging
|
||||
|
||||
gi.require_version('GIRepository', '3.0')
|
||||
from . import config
|
||||
from gi.repository import Gio
|
||||
from gi.repository import Gio, Gtk
|
||||
|
||||
resource = Gio.Resource.load(os.path.join(config.pkgdatadir, "merengue.gresource"))
|
||||
resource._register()
|
||||
|
||||
repository = gi.Repository.get_default()
|
||||
repository.prepend_search_path(config.privatecambalachedir)
|
||||
repository.prepend_library_path(config.privatecambalachedir)
|
||||
|
||||
gi.require_version("CambalachePrivate", "4.0" if Gtk.MAJOR_VERSION == 4 else "3.0")
|
||||
|
||||
|
||||
def getLogger(name):
|
||||
formatter = logging.Formatter("%(levelname)s:%(name)s %(message)s")
|
||||
@ -49,3 +57,4 @@ from .mrg_application import MrgApplication
|
||||
from .mrg_controller import MrgController
|
||||
from .mrg_placeholder import MrgPlaceholder
|
||||
from . import utils
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
VERSION = '@VERSION@'
|
||||
pkgdatadir = '@pkgdatadir@'
|
||||
merenguedir = '@merenguedir@'
|
||||
privatecambalachedir = '@privatecambalachedir@'
|
||||
|
@ -29,7 +29,7 @@ import gi
|
||||
import sys
|
||||
import signal
|
||||
|
||||
merenguedir = '@merenguedir@'
|
||||
merenguedir = "@merenguedir@"
|
||||
|
||||
sys.path.insert(1, merenguedir)
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
@ -43,9 +43,9 @@ if __name__ == "__main__":
|
||||
|
||||
version = sys.argv[1]
|
||||
command_socket = sys.argv[2]
|
||||
gi.require_version('Gdk', version)
|
||||
gi.require_version('Gtk', version)
|
||||
gi.require_version('CambalachePrivate', version)
|
||||
|
||||
gi.require_version("Gdk", version)
|
||||
gi.require_version("Gtk", version)
|
||||
|
||||
from merengue import MrgApplication
|
||||
app = MrgApplication(command_socket=command_socket)
|
||||
|
@ -12,6 +12,7 @@ conf.set('VERSION', meson.project_version())
|
||||
conf.set('PYTHON', python_bin.full_path())
|
||||
conf.set('pkgdatadir', pkgdatadir)
|
||||
conf.set('merenguedir', merenguedir)
|
||||
conf.set('privatecambalachedir', privatecambalachedir)
|
||||
|
||||
configure_file(
|
||||
input: 'config.py.in',
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
import os
|
||||
import gi
|
||||
import sys
|
||||
import json
|
||||
import importlib
|
||||
|
||||
@ -80,10 +79,6 @@ class MrgApplication(Gtk.Application):
|
||||
# Current UI ID
|
||||
self.ui_id = None
|
||||
|
||||
# The widget that got the last button press this is used to select
|
||||
# a widget on button release
|
||||
self.preselected_widget = None
|
||||
|
||||
self.settings = Gtk.Settings.get_default()
|
||||
|
||||
# Keep a reference to the default seat to easily ungrab the pointer
|
||||
@ -125,7 +120,6 @@ class MrgApplication(Gtk.Application):
|
||||
|
||||
def clear_all(self):
|
||||
self.ui_id = None
|
||||
self.preselected_widget = None
|
||||
|
||||
# Unset controllers objects
|
||||
for key in self.controllers:
|
||||
@ -304,7 +298,13 @@ class MrgApplication(Gtk.Application):
|
||||
self.set_property(property, value)
|
||||
|
||||
def add_css_provider(self, css_id, filename, priority, is_global, provider_for):
|
||||
css = MrgCssProvider(filename=filename, priority=priority, is_global=is_global, ui_id=self.ui_id if self.ui_id else 0)
|
||||
css = MrgCssProvider(
|
||||
filename=filename,
|
||||
priority=priority,
|
||||
is_global=is_global,
|
||||
provider_for=provider_for,
|
||||
ui_id=self.ui_id if self.ui_id else 0
|
||||
)
|
||||
|
||||
self.css_providers[css_id] = css
|
||||
|
||||
@ -327,7 +327,7 @@ class MrgApplication(Gtk.Application):
|
||||
css.set_property(field, value)
|
||||
|
||||
def run_command(self, command, args, payload):
|
||||
logger.debug(f"{command} {args}")
|
||||
logger.debug(f"{command} {args} payload={len(payload) if payload else -1}")
|
||||
|
||||
if command == "clear_all":
|
||||
self.clear_all()
|
||||
@ -388,7 +388,9 @@ class MrgApplication(Gtk.Application):
|
||||
|
||||
# Read payload
|
||||
if payload_length:
|
||||
payload = self.command_in.read(payload_length).decode()
|
||||
payload = self.command_in.read(payload_length)
|
||||
logger.debug(f"Payload read {payload_length=}, {len(payload)}")
|
||||
payload = payload.decode()
|
||||
|
||||
# Run command
|
||||
self.run_command(command, args, payload)
|
||||
|
@ -42,14 +42,15 @@ class MrgGtkLabel(MrgGtkWidget):
|
||||
|
||||
# Ensure a label so that it can be selected in the workspace
|
||||
if self.object.props.label == "":
|
||||
self.object.set_label("<label>")
|
||||
label = f"<label {self.object_id}>" if self.object.props.use_markup else f"<label {self.object_id}>"
|
||||
self.object.set_label(label)
|
||||
|
||||
def object_changed(self, old, new):
|
||||
super().object_changed(old, new)
|
||||
self.__init_label()
|
||||
|
||||
def set_object_property(self, name, value):
|
||||
if name == "label" and value == "":
|
||||
if (name == "label" and value == "") or name == "use-markup":
|
||||
self.__init_label()
|
||||
return
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
from gi.repository import GObject, Gdk, Gtk
|
||||
from gi.repository import GObject, Gdk, Gtk, CambalachePrivate
|
||||
|
||||
from .mrg_selection import MrgSelection
|
||||
from .mrg_gtk_widget import MrgGtkWidget
|
||||
@ -43,7 +43,7 @@ class MrgGtkMenu(MrgGtkWidget):
|
||||
if self.object is None:
|
||||
return
|
||||
|
||||
self.object.popup_at_widget(self.__button, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, None)
|
||||
self.object.popup_at_widget(self.object.get_attach_widget(), Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, None)
|
||||
|
||||
def object_changed(self, old, new):
|
||||
self.selection = None
|
||||
@ -54,6 +54,10 @@ class MrgGtkMenu(MrgGtkWidget):
|
||||
self.window = None
|
||||
return
|
||||
|
||||
self.selection = MrgSelection(app=self.app, container=self.object)
|
||||
if self.object.get_attach_widget() is not None:
|
||||
return
|
||||
|
||||
if self.window is None:
|
||||
self.__button = Gtk.MenuButton(
|
||||
visible=True, halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, receives_default=False
|
||||
@ -63,21 +67,19 @@ class MrgGtkMenu(MrgGtkWidget):
|
||||
self.__button.add(image)
|
||||
|
||||
self.window = Gtk.Window(title="Menu Preview Window", deletable=False, width_request=320, height_request=240)
|
||||
|
||||
self.window.set_default_size(640, 480)
|
||||
self.window.add(self.__button)
|
||||
|
||||
self.selection = MrgSelection(app=self.app, container=self.object)
|
||||
self.__button.set_popup(self.object)
|
||||
self.object.show_all()
|
||||
self.window.show_all()
|
||||
CambalachePrivate.widget_set_application_id(self.window, f"Casilda:{self.ui_id}.{self.object_id}")
|
||||
|
||||
def on_selected_changed(self):
|
||||
super().on_selected_changed()
|
||||
|
||||
if self.__button:
|
||||
self.__button.set_active(True)
|
||||
if self.selected:
|
||||
self.popup()
|
||||
else:
|
||||
self.object.popdown()
|
||||
|
||||
def show_child(self, child):
|
||||
if self.__button:
|
||||
self.__button.set_active(True)
|
||||
self.popup()
|
||||
|
@ -26,8 +26,6 @@ from gi.repository import GObject, Gtk
|
||||
|
||||
from merengue import utils, MrgPlaceholder
|
||||
|
||||
preselected_widget = None
|
||||
|
||||
|
||||
class FindInContainerData:
|
||||
def __init__(self, toplevel, x, y):
|
||||
@ -42,6 +40,7 @@ class MrgSelection(GObject.GObject):
|
||||
app = GObject.Property(type=GObject.GObject, flags=GObject.ParamFlags.READWRITE)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__selecting = False
|
||||
self._container = None
|
||||
self.gesture = None
|
||||
|
||||
@ -59,29 +58,14 @@ class MrgSelection(GObject.GObject):
|
||||
self.gesture = utils.gesture_click_new(self._container, propagation_phase=Gtk.PropagationPhase.CAPTURE)
|
||||
self.gesture.connect("pressed", self.__on_gesture_button_pressed)
|
||||
self.gesture.connect("released", self.__on_gesture_button_released)
|
||||
else:
|
||||
elif self.gesture:
|
||||
self.gesture.disconnect_by_func(self.__on_gesture_button_pressed)
|
||||
self.gesture.disconnect_by_func(self.__on_gesture_button_released)
|
||||
self.gesture = None
|
||||
|
||||
def __on_gesture_button_pressed(self, gesture, n_press, x, y):
|
||||
global preselected_widget
|
||||
|
||||
child = self.get_child_at_position(self._container, x, y)
|
||||
|
||||
if not self.is_widget_from_ui(child):
|
||||
return
|
||||
|
||||
# Pre select a widget on button press
|
||||
if preselected_widget != child:
|
||||
preselected_widget = child
|
||||
gesture.set_state(Gtk.EventSequenceState.CLAIMED)
|
||||
|
||||
def __on_gesture_button_released(self, gesture, n_press, x, y):
|
||||
global preselected_widget
|
||||
|
||||
child = self.get_child_at_position(self._container, x, y)
|
||||
if child != preselected_widget:
|
||||
return
|
||||
|
||||
if isinstance(child, MrgPlaceholder):
|
||||
controller = child.controller
|
||||
|
||||
@ -103,7 +87,15 @@ class MrgSelection(GObject.GObject):
|
||||
# Select widget on button release only if its preselected
|
||||
self.app.write_command("selection_changed", args={"selection": [object_id]})
|
||||
controller.selected = True
|
||||
|
||||
if not isinstance(child, Gtk.Window) and not isinstance(child, Gtk.HeaderBar):
|
||||
gesture.set_state(Gtk.EventSequenceState.CLAIMED)
|
||||
self.__selecting = True
|
||||
|
||||
def __on_gesture_button_released(self, gesture, n_press, x, y):
|
||||
if self.__selecting:
|
||||
gesture.set_state(Gtk.EventSequenceState.CLAIMED)
|
||||
self.__selecting = False
|
||||
|
||||
def is_widget_from_ui(self, obj):
|
||||
if isinstance(obj, MrgPlaceholder):
|
||||
@ -157,3 +149,4 @@ class MrgSelection(GObject.GObject):
|
||||
return widget
|
||||
|
||||
return None
|
||||
|
||||
|
@ -26,7 +26,7 @@ configure_file(
|
||||
install_data([
|
||||
'cmb_accessible_editor.py',
|
||||
'cmb_base.py',
|
||||
'cmb_column_view.py',
|
||||
'cmb_blueprint.py',
|
||||
'cmb_context_menu.py',
|
||||
'cmb_css.py',
|
||||
'cmb_css_editor.py',
|
||||
@ -35,20 +35,30 @@ install_data([
|
||||
'cmb_db_migration.py',
|
||||
'cmb_db_profile.py',
|
||||
'cmb_fragment_editor.py',
|
||||
'cmb_gresource.py',
|
||||
'cmb_gresource_editor.py',
|
||||
'cmb_layout_property.py',
|
||||
'cmb_library_info.py',
|
||||
'cmb_list_error.py',
|
||||
'cmb_list_store.py',
|
||||
'cmb_list_view.py',
|
||||
'cmb_message_notification_view.py',
|
||||
'cmb_notification.py',
|
||||
'cmb_notification_list_row.py',
|
||||
'cmb_notification_list_view.py',
|
||||
'cmb_object.py',
|
||||
'cmb_object_data.py',
|
||||
'cmb_object_data_editor.py',
|
||||
'cmb_object_editor.py',
|
||||
'cmb_objects_base.py',
|
||||
'cmb_path.py',
|
||||
'cmb_poll_notification_view.py',
|
||||
'cmb_poll_option_check.py',
|
||||
'cmb_project.py',
|
||||
'cmb_property.py',
|
||||
'cmb_property_info.py',
|
||||
'cmb_property_label.py',
|
||||
'cmb_signal_editor.py',
|
||||
'cmb_tree_expander.py',
|
||||
'cmb_type_chooser.py',
|
||||
'cmb_type_chooser_popover.py',
|
||||
'cmb_type_chooser_widget.py',
|
||||
@ -56,6 +66,7 @@ install_data([
|
||||
'cmb_ui.py',
|
||||
'cmb_ui_editor.py',
|
||||
'cmb_ui_requires_editor.py',
|
||||
'cmb_version_notification_view.py',
|
||||
'cmb_view.py',
|
||||
'constants.py',
|
||||
'utils.py',
|
||||
|
@ -15,6 +15,7 @@ foreach d : [['3', gtk3_dep], ['4', gtk4_dep]]
|
||||
sources,
|
||||
dependencies: dep,
|
||||
install: true,
|
||||
install_dir: privatecambalachedir,
|
||||
)
|
||||
|
||||
gnome.generate_gir(
|
||||
@ -27,5 +28,6 @@ foreach d : [['3', gtk3_dep], ['4', gtk4_dep]]
|
||||
symbol_prefix: 'cmb_private',
|
||||
header: 'cmb_private.h',
|
||||
install: true,
|
||||
install_dir_typelib: privatecambalachedir,
|
||||
)
|
||||
endforeach
|
||||
|
@ -23,6 +23,10 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-only
|
||||
#
|
||||
|
||||
import hashlib
|
||||
import datetime
|
||||
|
||||
from lxml import etree
|
||||
from gi.repository import Gdk, Gio
|
||||
|
||||
|
||||
@ -99,3 +103,101 @@ def content_type_guess(path):
|
||||
content_type, uncertain = Gio.content_type_guess(path, data)
|
||||
|
||||
return content_type
|
||||
|
||||
|
||||
def utcnow():
|
||||
return int(datetime.datetime.now(datetime.UTC).timestamp())
|
||||
|
||||
|
||||
# XML utilities
|
||||
def bool_from_string(value):
|
||||
if isinstance(value, str):
|
||||
return value.lower() in {"1", "t", "y", "true", "yes"} if value else False
|
||||
return bool(value)
|
||||
|
||||
|
||||
def xml_node_get(node, *args, errors=None):
|
||||
keys = node.keys()
|
||||
knowns = []
|
||||
retval = []
|
||||
|
||||
def get_key_val(node, attr):
|
||||
tokens = attr.split(":")
|
||||
key = tokens[0]
|
||||
val = node.get(key, None)
|
||||
|
||||
if len(tokens) > 1:
|
||||
t = tokens[1]
|
||||
if t == "bool":
|
||||
return (key, bool_from_string(val))
|
||||
elif t == "int":
|
||||
return (key, int(val))
|
||||
|
||||
return (key, val)
|
||||
|
||||
for attr in args:
|
||||
if isinstance(attr, list):
|
||||
for opt in attr:
|
||||
key, val = get_key_val(node, opt)
|
||||
retval.append(val)
|
||||
knowns.append(key)
|
||||
elif attr in keys:
|
||||
key, val = get_key_val(node, attr)
|
||||
retval.append(val)
|
||||
knowns.append(key)
|
||||
elif errors is not None:
|
||||
errors.append(("missing-attr", node, attr))
|
||||
|
||||
if errors is not None:
|
||||
unknown = list(set(keys) - set(knowns))
|
||||
for attr in unknown:
|
||||
errors.append(("unknown-attr", node, attr))
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def xml_node_get_comment(node):
|
||||
prev = node.getprevious()
|
||||
if prev is not None and prev.tag is etree.Comment:
|
||||
return prev.text if not prev.text.strip().startswith("interface-") else None
|
||||
return None
|
||||
|
||||
|
||||
def xml_node_set(node, attr, val):
|
||||
if val is not None:
|
||||
node.set(attr, str(val))
|
||||
|
||||
|
||||
# Duck typing Classes
|
||||
|
||||
|
||||
class FileHash():
|
||||
def __init__(self, fd=None):
|
||||
self.__fd = fd
|
||||
self.__hash = hashlib.sha256()
|
||||
|
||||
def close(self):
|
||||
if self.__fd:
|
||||
self.__fd.close()
|
||||
|
||||
def peek(self, size):
|
||||
return self.__fd.peek(size) if self.__fd else None
|
||||
|
||||
def read(self, size):
|
||||
if self.__fd:
|
||||
data = self.__fd.read(size)
|
||||
self.__hash.update(data)
|
||||
return data
|
||||
return None
|
||||
|
||||
def flush(self):
|
||||
if self.__fd:
|
||||
self.__fd.flush()
|
||||
|
||||
def write(self, data):
|
||||
self.__hash.update(data)
|
||||
if self.__fd:
|
||||
self.__fd.write(data)
|
||||
|
||||
def hexdigest(self):
|
||||
return self.__hash.hexdigest()
|
||||
|
@ -121,7 +121,7 @@
|
||||
("AtkRole","ATK_ROLE_INVALID","invalid",None,"Invalid role"),
|
||||
("AtkRole","ATK_ROLE_LABEL","label",28,"An object used to present an icon or short string in an interface"),
|
||||
("AtkRole","ATK_ROLE_LANDMARK","landmark",108,"A region of a web page intended as a navigational landmark. This is designed to allow Assistive Technologies to provide quick navigation among key regions within a document. (Since: 2.12)"),
|
||||
("AtkRole","ATK_ROLE_LAST_DEFINED","last-defined",128,"not a valid role, used for finding end of the enumeration"),
|
||||
("AtkRole","ATK_ROLE_LAST_DEFINED","last-defined",129,"not a valid role, used for finding end of the enumeration"),
|
||||
("AtkRole","ATK_ROLE_LAYERED_PANE","layered-pane",29,"A specialized pane that allows its children to be drawn in layers, providing a form of stacking order"),
|
||||
("AtkRole","ATK_ROLE_LEVEL_BAR","level-bar",101,"A bar that serves as a level indicator to, for instance, show the strength of a password or the state of a battery. (Since: 2.7.3)"),
|
||||
("AtkRole","ATK_ROLE_LINK","link",86,"The object is a hypertext anchor, i.e. a \"link\" in a hypertext document. Such objects are distinct from 'inline' content which may also use the Hypertext/Hyperlink interfaces to indicate the range/location within a text object where an inline or embedded object lies. (Since: 1.12.1)"),
|
||||
@ -168,6 +168,7 @@
|
||||
("AtkRole","ATK_ROLE_SUBSCRIPT","subscript",120,"An object that contains text that is displayed as a subscript. (Since: 2.16)"),
|
||||
("AtkRole","ATK_ROLE_SUGGESTION","suggestion",126,"A container for content that is called out as a proposed change from the current version of the document, such as by a reviewer of the content. This role should include either %ATK_ROLE_CONTENT_DELETION and/or %ATK_ROLE_CONTENT_INSERTION children, in any order, to indicate what the actual change is. (Since: 2.36)"),
|
||||
("AtkRole","ATK_ROLE_SUPERSCRIPT","superscript",121,"An object that contains text that is displayed as a superscript. (Since: 2.16)"),
|
||||
("AtkRole","ATK_ROLE_SWITCH","switch",128,"A switch that can be toggled on/off. (Since: 2.56)"),
|
||||
("AtkRole","ATK_ROLE_TABLE","table",54,"An object used to represent information in terms of rows and columns"),
|
||||
("AtkRole","ATK_ROLE_TABLE_CELL","table-cell",55,"A cell in a table"),
|
||||
("AtkRole","ATK_ROLE_TABLE_COLUMN_HEADER","table-column-header",56,"The header for a column of a table"),
|
||||
|
@ -382,8 +382,8 @@
|
||||
("GAppInfoCreateFlags","G_APP_INFO_CREATE_SUPPORTS_URIS","supports-uris",2,"Application supports URI arguments."),
|
||||
("GApplicationFlags","G_APPLICATION_ALLOW_REPLACEMENT","allow-replacement",128,"Allow another instance to take over the bus name. Since: 2.60"),
|
||||
("GApplicationFlags","G_APPLICATION_CAN_OVERRIDE_APP_ID","can-override-app-id",64,"Allow users to override the application ID from the command line with `--gapplication-app-id`. Since: 2.48"),
|
||||
("GApplicationFlags","G_APPLICATION_DEFAULT_FLAGS","default-flags",None,"Default flags. Since: 2.74"),
|
||||
("GApplicationFlags","G_APPLICATION_FLAGS_NONE","flags-none",None,"Default. Deprecated in 2.74, use %G_APPLICATION_DEFAULT_FLAGS instead"),
|
||||
("GApplicationFlags","G_APPLICATION_DEFAULT_FLAGS","default-flags",None,"Default flags."),
|
||||
("GApplicationFlags","G_APPLICATION_FLAGS_NONE","flags-none",None,"Default flags."),
|
||||
("GApplicationFlags","G_APPLICATION_HANDLES_COMMAND_LINE","handles-command-line",8,"This application handles command line arguments (in the primary instance). Note that this flag only affect the default implementation of local_command_line(). See g_application_run() for details."),
|
||||
("GApplicationFlags","G_APPLICATION_HANDLES_OPEN","handles-open",4,"This application handles opening files (in the primary instance). Note that this flag only affects the default implementation of local_command_line(), and has no effect if %G_APPLICATION_HANDLES_COMMAND_LINE is given. See g_application_run() for details."),
|
||||
("GApplicationFlags","G_APPLICATION_IS_LAUNCHER","is-launcher",2,"Don't try to become the primary instance."),
|
||||
|
@ -187,9 +187,17 @@
|
||||
</properties>
|
||||
</AdwPreferencesDialog>
|
||||
|
||||
<AdwWindow>
|
||||
<properties>
|
||||
<property original-owner-id="GtkWindow" id="titlebar" disabled="True"/>
|
||||
<property original-owner-id="GtkWindow" id="child" disabled="True"/>
|
||||
</properties>
|
||||
</AdwWindow>
|
||||
|
||||
<AdwApplicationWindow>
|
||||
<properties>
|
||||
<property original-owner-id="GtkWindow" id="titlebar" disabled="True"/>
|
||||
<property original-owner-id="GtkWindow" id="child" disabled="True"/>
|
||||
</properties>
|
||||
</AdwApplicationWindow>
|
||||
|
||||
|
@ -34,12 +34,6 @@
|
||||
</properties>
|
||||
</HdyHeaderBar>
|
||||
|
||||
<HdyHeaderBarLayoutChild>
|
||||
<properties>
|
||||
<property id="position" is-position="True"/>
|
||||
</properties>
|
||||
</HdyHeaderBarLayoutChild>
|
||||
|
||||
<HdyPreferencesGroup>
|
||||
<properties>
|
||||
<property id="description" translatable="True"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<!DOCTYPE cambalache-catalog SYSTEM "cambalache-catalog.dtd">
|
||||
<cambalache-catalog name="libadwaita" namespace="Adw" prefix="Adw" version="1" targets="1.0,1.1,1.2,1.3,1.4,1.5,1.6" depends="gtk-4.0">
|
||||
<cambalache-catalog name="libadwaita" namespace="Adw" prefix="Adw" version="1" targets="1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7" depends="gtk-4.0">
|
||||
<type>
|
||||
("AdwAboutDialog","AdwDialog","libadwaita","1.5",None,None,1,"container","toplevel",None),
|
||||
("AdwAboutWindow","AdwWindow","libadwaita","1.2","1.6",None,1,"container","toplevel",None),
|
||||
@ -14,6 +14,7 @@
|
||||
("AdwApplicationWindow","GtkApplicationWindow","libadwaita",None,None,None,1,"container","toplevel",None),
|
||||
("AdwAvatar","GtkWidget","libadwaita",None,None,None,1,"container","display",None),
|
||||
("AdwBanner","GtkWidget","libadwaita","1.3",None,None,1,"container","display",None),
|
||||
("AdwBannerButtonStyle","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwBin","GtkWidget","libadwaita",None,None,None,1,"container","layout",None),
|
||||
("AdwBottomSheet","GtkWidget","libadwaita","1.6",None,None,1,"container","layout",None),
|
||||
("AdwBreakpoint","GObject","libadwaita","1.4",None,None,1,None,None,None),
|
||||
@ -44,6 +45,9 @@
|
||||
("AdwFlapTransitionType","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwFoldThresholdPolicy","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwHeaderBar","GtkWidget","libadwaita",None,None,None,1,"container","layout",None),
|
||||
("AdwInlineViewSwitcher","GtkWidget","libadwaita","1.7",None,None,1,"container",None,None),
|
||||
("AdwInlineViewSwitcherDisplayMode","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwJustifyMode","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwLayout","GObject","libadwaita","1.6",None,None,1,"container","layout",None),
|
||||
("AdwLayoutSlot","GtkWidget","libadwaita","1.6",None,None,1,"container","layout",None),
|
||||
("AdwLeaflet","GtkWidget","libadwaita",None,"1.4",None,1,"container","layout",None),
|
||||
@ -57,6 +61,7 @@
|
||||
("AdwNavigationSplitView","GtkWidget","libadwaita","1.4",None,None,1,"container","layout",None),
|
||||
("AdwNavigationView","GtkWidget","libadwaita","1.4",None,None,1,"container","layout",None),
|
||||
("AdwOverlaySplitView","GtkWidget","libadwaita","1.4",None,None,1,"container","layout",None),
|
||||
("AdwPackDirection","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwPasswordEntryRow","AdwEntryRow","libadwaita","1.2",None,None,1,"container","control",None),
|
||||
("AdwPreferencesDialog","AdwDialog","libadwaita","1.5",None,None,1,"container","toplevel",None),
|
||||
("AdwPreferencesGroup","GtkWidget","libadwaita",None,None,None,1,"container","layout",None),
|
||||
@ -88,6 +93,8 @@
|
||||
("AdwToast","GObject","libadwaita",None,None,None,1,None,"layout",None),
|
||||
("AdwToastOverlay","GtkWidget","libadwaita",None,None,None,1,"container","layout",None),
|
||||
("AdwToastPriority","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwToggle","GObject","libadwaita","1.7",None,None,1,None,None,None),
|
||||
("AdwToggleGroup","GtkWidget","libadwaita","1.7",None,None,1,"container",None,None),
|
||||
("AdwToolbarStyle","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","GtkWidget","libadwaita","1.4",None,None,1,"container","layout",None),
|
||||
("AdwViewStack","GtkWidget","libadwaita",None,None,None,1,"container","layout",None),
|
||||
@ -98,12 +105,16 @@
|
||||
("AdwViewSwitcherPolicy","enum","libadwaita",None,None,None,None,None,None,None),
|
||||
("AdwViewSwitcherTitle","GtkWidget","libadwaita",None,"1.4",None,1,"container","display",None),
|
||||
("AdwWindow","GtkWindow","libadwaita",None,None,None,1,"container","toplevel",None),
|
||||
("AdwWindowTitle","GtkWidget","libadwaita",None,None,None,1,"container","display",None)
|
||||
("AdwWindowTitle","GtkWidget","libadwaita",None,None,None,1,"container","display",None),
|
||||
("AdwWrapBox","GtkWidget","libadwaita","1.7",None,None,1,"container",None,None),
|
||||
("AdwWrapLayout","GtkLayoutManager","libadwaita","1.7",None,None,1,"manager",None,None),
|
||||
("AdwWrapPolicy","enum","libadwaita",None,None,None,None,None,None,None)
|
||||
</type>
|
||||
<type_iface>
|
||||
("AdwAboutDialog","GtkAccessible"),
|
||||
("AdwAboutDialog","GtkBuildable"),
|
||||
("AdwAboutDialog","GtkConstraintTarget"),
|
||||
("AdwAboutDialog","GtkShortcutManager"),
|
||||
("AdwAboutWindow","GtkAccessible"),
|
||||
("AdwAboutWindow","GtkBuildable"),
|
||||
("AdwAboutWindow","GtkConstraintTarget"),
|
||||
@ -117,6 +128,7 @@
|
||||
("AdwAlertDialog","GtkAccessible"),
|
||||
("AdwAlertDialog","GtkBuildable"),
|
||||
("AdwAlertDialog","GtkConstraintTarget"),
|
||||
("AdwAlertDialog","GtkShortcutManager"),
|
||||
("AdwApplicationWindow","GtkAccessible"),
|
||||
("AdwApplicationWindow","GtkBuildable"),
|
||||
("AdwApplicationWindow","GtkConstraintTarget"),
|
||||
@ -178,6 +190,7 @@
|
||||
("AdwDialog","GtkAccessible"),
|
||||
("AdwDialog","GtkBuildable"),
|
||||
("AdwDialog","GtkConstraintTarget"),
|
||||
("AdwDialog","GtkShortcutManager"),
|
||||
("AdwEntryRow","GtkAccessible"),
|
||||
("AdwEntryRow","GtkActionable"),
|
||||
("AdwEntryRow","GtkBuildable"),
|
||||
@ -196,6 +209,10 @@
|
||||
("AdwHeaderBar","GtkAccessible"),
|
||||
("AdwHeaderBar","GtkBuildable"),
|
||||
("AdwHeaderBar","GtkConstraintTarget"),
|
||||
("AdwInlineViewSwitcher","GtkAccessible"),
|
||||
("AdwInlineViewSwitcher","GtkBuildable"),
|
||||
("AdwInlineViewSwitcher","GtkConstraintTarget"),
|
||||
("AdwInlineViewSwitcher","GtkOrientable"),
|
||||
("AdwLayout","GtkBuildable"),
|
||||
("AdwLayoutSlot","GtkAccessible"),
|
||||
("AdwLayoutSlot","GtkBuildable"),
|
||||
@ -236,6 +253,7 @@
|
||||
("AdwPreferencesDialog","GtkAccessible"),
|
||||
("AdwPreferencesDialog","GtkBuildable"),
|
||||
("AdwPreferencesDialog","GtkConstraintTarget"),
|
||||
("AdwPreferencesDialog","GtkShortcutManager"),
|
||||
("AdwPreferencesGroup","GtkAccessible"),
|
||||
("AdwPreferencesGroup","GtkBuildable"),
|
||||
("AdwPreferencesGroup","GtkConstraintTarget"),
|
||||
@ -294,6 +312,10 @@
|
||||
("AdwToastOverlay","GtkAccessible"),
|
||||
("AdwToastOverlay","GtkBuildable"),
|
||||
("AdwToastOverlay","GtkConstraintTarget"),
|
||||
("AdwToggleGroup","GtkAccessible"),
|
||||
("AdwToggleGroup","GtkBuildable"),
|
||||
("AdwToggleGroup","GtkConstraintTarget"),
|
||||
("AdwToggleGroup","GtkOrientable"),
|
||||
("AdwToolbarView","GtkAccessible"),
|
||||
("AdwToolbarView","GtkBuildable"),
|
||||
("AdwToolbarView","GtkConstraintTarget"),
|
||||
@ -320,7 +342,12 @@
|
||||
("AdwWindow","GtkShortcutManager"),
|
||||
("AdwWindowTitle","GtkAccessible"),
|
||||
("AdwWindowTitle","GtkBuildable"),
|
||||
("AdwWindowTitle","GtkConstraintTarget")
|
||||
("AdwWindowTitle","GtkConstraintTarget"),
|
||||
("AdwWrapBox","GtkAccessible"),
|
||||
("AdwWrapBox","GtkBuildable"),
|
||||
("AdwWrapBox","GtkConstraintTarget"),
|
||||
("AdwWrapBox","GtkOrientable"),
|
||||
("AdwWrapLayout","GtkOrientable")
|
||||
</type_iface>
|
||||
<type_enum>
|
||||
("AdwAccentColor","ADW_ACCENT_COLOR_BLUE","blue",None,"Use a blue color (`#3584e4`). This is the default value."),
|
||||
@ -336,6 +363,8 @@
|
||||
("AdwAnimationState","ADW_ANIMATION_IDLE","idle",None,"The animation hasn't started yet."),
|
||||
("AdwAnimationState","ADW_ANIMATION_PAUSED","paused",1,"The animation has been paused."),
|
||||
("AdwAnimationState","ADW_ANIMATION_PLAYING","playing",2,"The animation is currently playing."),
|
||||
("AdwBannerButtonStyle","ADW_BANNER_BUTTON_DEFAULT","default",None,"The default button style."),
|
||||
("AdwBannerButtonStyle","ADW_BANNER_BUTTON_SUGGESTED","suggested",1,"A button in the suggested action style."),
|
||||
("AdwBreakpointConditionLengthType","ADW_BREAKPOINT_CONDITION_MAX_HEIGHT","max-height",3,"true if the height is less than or equal to the condition value"),
|
||||
("AdwBreakpointConditionLengthType","ADW_BREAKPOINT_CONDITION_MAX_WIDTH","max-width",1,"true if the width is less than or equal to the condition value"),
|
||||
("AdwBreakpointConditionLengthType","ADW_BREAKPOINT_CONDITION_MIN_HEIGHT","min-height",2,"true if the height is greater than or equal to the condition value"),
|
||||
@ -352,12 +381,15 @@
|
||||
("AdwDialogPresentationMode","ADW_DIALOG_AUTO","auto",None,"Switch between `ADW_DIALOG_FLOATING` and `ADW_DIALOG_BOTTOM_SHEET` depending on available size."),
|
||||
("AdwDialogPresentationMode","ADW_DIALOG_BOTTOM_SHEET","bottom-sheet",2,"Present dialog as a bottom sheet."),
|
||||
("AdwDialogPresentationMode","ADW_DIALOG_FLOATING","floating",1,"Present dialog as a centered floating window."),
|
||||
("AdwEasing","ADW_EASE","ease",31,"Cubic bezier tweening, with control points in (0.25, 0.1) and (0.25, 1.0). Increases in velocity towards the middle of the animation, slowing back down at the end."),
|
||||
("AdwEasing","ADW_EASE_IN","ease-in",32,"Cubic bezier tweening, with control points in (0.42, 0.0) and (1.0, 1.0). Starts off slowly, with the speed of the animation increasing until complete."),
|
||||
("AdwEasing","ADW_EASE_IN_BACK","ease-in-back",25,"Overshooting cubic tweening, with backtracking on start."),
|
||||
("AdwEasing","ADW_EASE_IN_BOUNCE","ease-in-bounce",28,"Exponentially decaying parabolic (bounce) tweening, on start."),
|
||||
("AdwEasing","ADW_EASE_IN_CIRC","ease-in-circ",19,"Circular tweening."),
|
||||
("AdwEasing","ADW_EASE_IN_CUBIC","ease-in-cubic",4,"Cubic tweening."),
|
||||
("AdwEasing","ADW_EASE_IN_ELASTIC","ease-in-elastic",22,"Elastic tweening, with offshoot on start."),
|
||||
("AdwEasing","ADW_EASE_IN_EXPO","ease-in-expo",16,"Exponential tweening."),
|
||||
("AdwEasing","ADW_EASE_IN_OUT","ease-in-out",34,"Cubic bezier tweening, with control points in (0.42, 0.0) and (0.58, 1.0). Starts off slowly, speeds up in the middle, and then slows down again."),
|
||||
("AdwEasing","ADW_EASE_IN_OUT_BACK","ease-in-out-back",27,"Overshooting cubic tweening, with backtracking on both ends, combining `ADW_EASE_IN_BACK` and `ADW_EASE_OUT_BACK`."),
|
||||
("AdwEasing","ADW_EASE_IN_OUT_BOUNCE","ease-in-out-bounce",30,"Exponentially decaying parabolic (bounce) tweening, with bounce on both ends, combining `ADW_EASE_IN_BOUNCE` and `ADW_EASE_OUT_BOUNCE`."),
|
||||
("AdwEasing","ADW_EASE_IN_OUT_CIRC","ease-in-out-circ",21,"Circular tweening, combining `ADW_EASE_IN_CIRC` and `ADW_EASE_OUT_CIRC`."),
|
||||
@ -372,6 +404,7 @@
|
||||
("AdwEasing","ADW_EASE_IN_QUART","ease-in-quart",7,"Quartic tweening."),
|
||||
("AdwEasing","ADW_EASE_IN_QUINT","ease-in-quint",10,"Quintic tweening."),
|
||||
("AdwEasing","ADW_EASE_IN_SINE","ease-in-sine",13,"Sine wave tweening."),
|
||||
("AdwEasing","ADW_EASE_OUT","ease-out",33,"Cubic bezier tweening, with control points in (0.0, 0.0) and (0.58, 1.0). Starts quickly, slowing down the animation until complete."),
|
||||
("AdwEasing","ADW_EASE_OUT_BACK","ease-out-back",26,"Overshooting cubic tweening, with backtracking on end, inverse of `ADW_EASE_IN_BACK`."),
|
||||
("AdwEasing","ADW_EASE_OUT_BOUNCE","ease-out-bounce",29,"Exponentially decaying parabolic (bounce) tweening, with bounce on end, inverse of `ADW_EASE_IN_BOUNCE`."),
|
||||
("AdwEasing","ADW_EASE_OUT_CIRC","ease-out-circ",20,"Circular tweening, inverse of `ADW_EASE_IN_CIRC`."),
|
||||
@ -391,6 +424,12 @@
|
||||
("AdwFlapTransitionType","ADW_FLAP_TRANSITION_TYPE_UNDER","under",1,"The content slides over the flap. Only the content can be swiped."),
|
||||
("AdwFoldThresholdPolicy","ADW_FOLD_THRESHOLD_POLICY_MINIMUM","minimum",None,"Folding is based on the minimum size"),
|
||||
("AdwFoldThresholdPolicy","ADW_FOLD_THRESHOLD_POLICY_NATURAL","natural",1,"Folding is based on the natural size"),
|
||||
("AdwInlineViewSwitcherDisplayMode","ADW_INLINE_VIEW_SWITCHER_BOTH","both",2,"Toggles display both icons and labels."),
|
||||
("AdwInlineViewSwitcherDisplayMode","ADW_INLINE_VIEW_SWITCHER_ICONS","icons",1,"Toggles only display icons."),
|
||||
("AdwInlineViewSwitcherDisplayMode","ADW_INLINE_VIEW_SWITCHER_LABELS","labels",None,"Toggles only display labels."),
|
||||
("AdwJustifyMode","ADW_JUSTIFY_FILL","fill",1,"Stretch each child within the line, keeping consistent spacing, so that the line fills the entire length."),
|
||||
("AdwJustifyMode","ADW_JUSTIFY_NONE","none",None,"Don't justify children within a line."),
|
||||
("AdwJustifyMode","ADW_JUSTIFY_SPREAD","spread",2,"Increase spacing between children, moving the children so that the first and last child are aligned with the beginning and end of the line. If the line only contains a single widget, it will be stretched regardless."),
|
||||
("AdwLeafletTransitionType","ADW_LEAFLET_TRANSITION_TYPE_OVER","over",None,"Cover the old page or uncover the new page, sliding from or towards the end according to orientation, text direction and children order"),
|
||||
("AdwLeafletTransitionType","ADW_LEAFLET_TRANSITION_TYPE_SLIDE","slide",2,"Slide from left, right, up or down according to the orientation, text direction and the children order"),
|
||||
("AdwLeafletTransitionType","ADW_LEAFLET_TRANSITION_TYPE_UNDER","under",1,"Uncover the new page or cover the old page, sliding from or towards the start according to orientation, text direction and children order"),
|
||||
@ -399,6 +438,8 @@
|
||||
("AdwLengthUnit","ADW_LENGTH_UNIT_SP","sp",2,"scale independent pixels, changes with text scale factor"),
|
||||
("AdwNavigationDirection","ADW_NAVIGATION_DIRECTION_BACK","back",None,"Corresponds to start or top, depending on orientation and text direction"),
|
||||
("AdwNavigationDirection","ADW_NAVIGATION_DIRECTION_FORWARD","forward",1,"Corresponds to end or bottom, depending on orientation and text direction"),
|
||||
("AdwPackDirection","ADW_PACK_END_TO_START","end-to-start",1,"Pack children from right to left for LTR languages, or bottom to top vertically."),
|
||||
("AdwPackDirection","ADW_PACK_START_TO_END","start-to-end",None,"Pack children from left to right for LTR languages, or top to bottom vertically."),
|
||||
("AdwResponseAppearance","ADW_RESPONSE_DEFAULT","default",None,"the default appearance."),
|
||||
("AdwResponseAppearance","ADW_RESPONSE_DESTRUCTIVE","destructive",2,"used to draw attention to the potentially damaging consequences of using the response. This appearance acts as a warning to the user."),
|
||||
("AdwResponseAppearance","ADW_RESPONSE_SUGGESTED","suggested",1,"used to denote important responses such as the affirmative action."),
|
||||
@ -410,7 +451,9 @@
|
||||
("AdwToolbarStyle","ADW_TOOLBAR_RAISED","raised",1,"Opaque background with a persistent shadow"),
|
||||
("AdwToolbarStyle","ADW_TOOLBAR_RAISED_BORDER","raised-border",2,"Opaque background with a persistent border"),
|
||||
("AdwViewSwitcherPolicy","ADW_VIEW_SWITCHER_POLICY_NARROW","narrow",None,"Force the narrow mode"),
|
||||
("AdwViewSwitcherPolicy","ADW_VIEW_SWITCHER_POLICY_WIDE","wide",1,"Force the wide mode")
|
||||
("AdwViewSwitcherPolicy","ADW_VIEW_SWITCHER_POLICY_WIDE","wide",1,"Force the wide mode"),
|
||||
("AdwWrapPolicy","ADW_WRAP_MINIMUM","minimum",None,"Fit as many children into each line as possible, shrinking them down to their minimum size before wrapping to the next line."),
|
||||
("AdwWrapPolicy","ADW_WRAP_NATURAL","natural",1,"Wrap to the next line as soon as the previous line cannot fit any more children without shrinking them past their natural size.")
|
||||
</type_enum>
|
||||
<type_flags>
|
||||
("AdwTabViewShortcuts","ADW_TAB_VIEW_SHORTCUT_ALL_SHORTCUTS","all-shortcuts",4095,"All of the shortcuts"),
|
||||
@ -513,6 +556,8 @@
|
||||
("AdwAnimation","follow-enable-animations-setting","gboolean",None,None,None,"True",None,None,"1.3",None,None,None,None,None,None,None,None),
|
||||
("AdwAnimation","target","AdwAnimationTarget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwAnimation","widget","GtkWidget",1,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwApplicationWindow","adaptive-preview","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwApplicationWindow","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,"GtkWindow",1),
|
||||
("AdwApplicationWindow","content","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwApplicationWindow","titlebar","GtkWidget",1,None,None,None,None,None,"4.6",None,None,None,None,None,None,"GtkWindow",1),
|
||||
("AdwAvatar","icon-name","CmbIconName",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -520,6 +565,7 @@
|
||||
("AdwAvatar","size","gint",None,None,None,"-1","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("AdwAvatar","text","gchararray",None,None,None,"",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwBanner","button-label","gchararray",None,None,None,"",None,None,"1.3",None,None,None,None,None,None,None,None),
|
||||
("AdwBanner","button-style","AdwBannerButtonStyle",None,None,None,"default",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwBanner","revealed","gboolean",None,None,None,"False",None,None,"1.3",None,None,None,None,None,None,None,None),
|
||||
("AdwBanner","title","gchararray",None,None,None,"",None,None,"1.3",None,1,None,None,None,None,None,None),
|
||||
("AdwBanner","use-markup","gboolean",None,None,None,"True",None,None,"1.3",None,None,None,None,None,None,None,None),
|
||||
@ -532,6 +578,7 @@
|
||||
("AdwBottomSheet","full-width","gboolean",None,None,None,"True",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwBottomSheet","modal","gboolean",None,None,None,"True",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwBottomSheet","open","gboolean",None,None,None,"False",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwBottomSheet","reveal-bottom-bar","gboolean",None,None,None,"True",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwBottomSheet","sheet","GtkWidget",1,None,None,None,None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwBottomSheet","show-drag-handle","gboolean",None,None,None,"True",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwBreakpointBin","child","GtkWidget",1,None,None,None,None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
@ -615,6 +662,10 @@
|
||||
("AdwHeaderBar","show-start-title-buttons","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwHeaderBar","show-title","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwHeaderBar","title-widget","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwInlineViewSwitcher","can-shrink","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwInlineViewSwitcher","display-mode","AdwInlineViewSwitcherDisplayMode",None,None,None,"labels",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwInlineViewSwitcher","homogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwInlineViewSwitcher","stack","AdwViewStack",1,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwLayout","content","GtkWidget",1,1,None,None,None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwLayout","name","gchararray",None,None,None,None,None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwLayoutSlot","id","gchararray",None,1,None,None,None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
@ -649,10 +700,13 @@
|
||||
("AdwNavigationSplitView","min-sidebar-width","gdouble",None,None,None,"180.0","0.0","1.79769313486232e+308","1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationSplitView","show-content","gboolean",None,None,None,"False",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationSplitView","sidebar","AdwNavigationPage",1,None,None,None,None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationSplitView","sidebar-position","GtkPackType",None,None,None,"start",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationSplitView","sidebar-width-fraction","gdouble",None,None,None,"0.25","0.0","1.0","1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationSplitView","sidebar-width-unit","AdwLengthUnit",None,None,None,"sp",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationView","animate-transitions","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationView","hhomogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationView","pop-on-escape","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwNavigationView","vhomogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwOverlaySplitView","collapsed","gboolean",None,None,None,"False",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwOverlaySplitView","content","GtkWidget",1,None,None,None,None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwOverlaySplitView","enable-hide-gesture","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
@ -676,6 +730,7 @@
|
||||
("AdwPreferencesGroup","header-suffix","GtkWidget",1,None,None,None,None,None,"1.1",None,None,None,None,None,None,None,None),
|
||||
("AdwPreferencesGroup","separate-rows","gboolean",None,None,None,"False",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwPreferencesGroup","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("AdwPreferencesPage","banner","AdwBanner",1,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwPreferencesPage","description","gchararray",None,None,None,"",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwPreferencesPage","description-centered","gboolean",None,None,None,"False",None,None,"1.6",None,None,None,None,None,None,None,None),
|
||||
("AdwPreferencesPage","icon-name","CmbIconName",None,None,None,"",None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -795,6 +850,17 @@
|
||||
("AdwToast","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("AdwToast","use-markup","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwToastOverlay","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","child","GtkWidget",1,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","enabled","gboolean",None,None,None,"True",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","icon-name","gchararray",None,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","label","gchararray",None,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","name","gchararray",None,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","tooltip","gchararray",None,None,None,"",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggle","use-underline","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggleGroup","active","guint",None,None,None,"4294967295","0","4294967295","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggleGroup","active-name","gchararray",None,None,None,None,None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggleGroup","can-shrink","gboolean",None,None,None,"True",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToggleGroup","homogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","bottom-bar-style","AdwToolbarStyle",None,None,None,"flat",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","content","GtkWidget",1,None,None,None,None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","extend-content-to-bottom-edge","gboolean",None,None,None,"False",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
@ -802,7 +868,9 @@
|
||||
("AdwToolbarView","reveal-bottom-bars","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","reveal-top-bars","gboolean",None,None,None,"True",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwToolbarView","top-bar-style","AdwToolbarStyle",None,None,None,"flat",None,None,"1.4",None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","enable-transitions","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","hhomogeneous","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","transition-duration","guint",None,None,None,"200","0","4294967295","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","vhomogeneous","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","visible-child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwViewStack","visible-child-name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -823,9 +891,38 @@
|
||||
("AdwViewSwitcherTitle","subtitle","gchararray",None,None,None,"",None,None,None,"1.4",1,None,None,None,None,None,None),
|
||||
("AdwViewSwitcherTitle","title","gchararray",None,None,None,"",None,None,None,"1.4",1,None,None,None,None,None,None),
|
||||
("AdwViewSwitcherTitle","view-switcher-enabled","gboolean",None,None,None,"True",None,None,None,"1.4",None,None,None,None,None,None,None),
|
||||
("AdwWindow","adaptive-preview","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWindow","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,"GtkWindow",1),
|
||||
("AdwWindow","content","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("AdwWindow","titlebar","GtkWidget",1,None,None,None,None,None,"4.6",None,None,None,None,None,None,"GtkWindow",1),
|
||||
("AdwWindowTitle","subtitle","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("AdwWindowTitle","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None)
|
||||
("AdwWindowTitle","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("AdwWrapBox","align","gfloat",None,None,None,"0.0","0.0","1.0","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","child-spacing","gint",None,None,None,"0","0","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","child-spacing-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","justify","AdwJustifyMode",None,None,None,"none",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","justify-last-line","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","line-homogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","line-spacing","gint",None,None,None,"0","0","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","line-spacing-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","natural-line-length","gint",None,None,None,"-1","-1","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","natural-line-length-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","pack-direction","AdwPackDirection",None,None,None,"start-to-end",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","wrap-policy","AdwWrapPolicy",None,None,None,"natural",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapBox","wrap-reverse","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","align","gfloat",None,None,None,"0.0","0.0","1.0","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","child-spacing","gint",None,None,None,"0","0","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","child-spacing-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","justify","AdwJustifyMode",None,None,None,"none",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","justify-last-line","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","line-homogeneous","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","line-spacing","gint",None,None,None,"0","0","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","line-spacing-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","natural-line-length","gint",None,None,None,"-1","-1","2147483647","1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","natural-line-length-unit","AdwLengthUnit",None,None,None,"px",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","pack-direction","AdwPackDirection",None,None,None,"start-to-end",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","wrap-policy","AdwWrapPolicy",None,None,None,"natural",None,None,"1.7",None,None,None,None,None,None,None,None),
|
||||
("AdwWrapLayout","wrap-reverse","gboolean",None,None,None,"False",None,None,"1.7",None,None,None,None,None,None,None,None)
|
||||
</property>
|
||||
<signal>
|
||||
("AdwAboutDialog","activate-link","1.5",None,None),
|
||||
|
@ -204,7 +204,7 @@
|
||||
("HdyHeaderBar","title","gchararray",None,None,None,None,None,None,"1.0",None,1,None,None,None,None,None,None),
|
||||
("HdyHeaderBar","transition-duration","guint",None,None,None,"200","0","4294967295","1.0",None,None,None,None,None,None,None,None),
|
||||
("HdyHeaderBarLayoutChild","pack-type","GtkPackType",None,None,None,"start",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("HdyHeaderBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("HdyHeaderBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("HdyHeaderGroup","decorate-all","gboolean",None,None,None,"False",None,None,"1.0",None,None,None,None,None,None,None,None),
|
||||
("HdyKeypad","column-spacing","guint",None,None,None,"6","0","32767","1.0",None,None,None,None,None,None,None,None),
|
||||
("HdyKeypad","end-action","GtkWidget",1,None,None,None,None,None,"1.0",None,None,None,None,None,None,None,None),
|
||||
|
@ -46,6 +46,8 @@
|
||||
("WebKitUserScriptInjectionTime","enum","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitUserStyleLevel","enum","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebContext","GObject","webkit2gtk",None,None,None,1,None,None,None),
|
||||
("WebKitWebExtensionMatchPatternError","enum","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebExtensionMatchPatternOptions","flags","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebExtensionMode","enum","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebProcessTerminationReason","enum","webkit2gtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebView","WebKitWebViewBase","webkit2gtk",None,None,None,1,"container",None,"MrgDummyWebViewProxy"),
|
||||
@ -223,6 +225,10 @@
|
||||
("WebKitUserScriptInjectionTime","WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START","start",None,"Insert the code of the user script at the beginning of loaded documents. This is the default."),
|
||||
("WebKitUserStyleLevel","WEBKIT_USER_STYLE_LEVEL_AUTHOR","author",1,"The style sheet will be treated as if it was provided by the loaded documents. That means other user style sheets may still override it."),
|
||||
("WebKitUserStyleLevel","WEBKIT_USER_STYLE_LEVEL_USER","user",None,"The style sheet is an user style sheet, its contents always override other style sheets. This is the default."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_HOST","invalid-host",809,"The host component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_PATH","invalid-path",810,"The path component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_SCHEME","invalid-scheme",808,"The scheme component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_UNKNOWN","unknown",899,"An unknown error occured."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_MANIFESTV2","manifestv2",1,"For a ManifestV2 extension."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_MANIFESTV3","manifestv3",2,"For a ManifestV3 extension."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_NONE","none",None,"Not for an extension."),
|
||||
@ -259,6 +265,10 @@
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING","include-selection-highlighting",1,"Whether to include in the snapshot the highlight of the selected content."),
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_NONE","none",None,"Do not include any special options."),
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND","transparent-background",2,"Do not fill the background with white before rendering the snapshot. Since 2.8"),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_IGNORE_PATHS","ignore-paths",4,"The host components should be ignored while matching."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_IGNORE_SCHEMES","ignore-schemes",2,"The scheme components should be ignored while matching."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_MATCH_BIDIRECTIONALLY","match-bidirectionally",8,"Two patterns should be checked in either direction while matching (A matches B, or B matches A). Invalid for matching URLs."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_NONE","none",1,"No special matching options."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_ALL","all",16383,"All types."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_COOKIES","cookies",256,"Cookies."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT","device-id-hash-salt",512,"Hash salt used to generate the device ids used by webpages. Since 2.24"),
|
||||
@ -337,6 +347,7 @@
|
||||
("WebKitSettings","sans-serif-font-family","gchararray",None,None,None,"sans-serif",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","serif-font-family","gchararray",None,None,None,"serif",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","user-agent","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","webrtc-udp-ports-range","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","zoom-text-only","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitWebContext","local-storage-directory","gchararray",None,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitWebContext","process-swap-on-cross-site-navigation-enabled","gboolean",None,1,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
|
@ -45,6 +45,8 @@
|
||||
("WebKitUserScriptInjectionTime","enum","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitUserStyleLevel","enum","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebContext","GObject","webkitgtk",None,None,None,1,None,None,None),
|
||||
("WebKitWebExtensionMatchPatternError","enum","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebExtensionMatchPatternOptions","flags","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebExtensionMode","enum","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebProcessTerminationReason","enum","webkitgtk",None,None,None,None,None,None,None),
|
||||
("WebKitWebView","WebKitWebViewBase","webkitgtk",None,None,None,1,"container",None,"MrgDummyWebViewProxy"),
|
||||
@ -218,6 +220,10 @@
|
||||
("WebKitUserScriptInjectionTime","WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START","start",None,"Insert the code of the user script at the beginning of loaded documents. This is the default."),
|
||||
("WebKitUserStyleLevel","WEBKIT_USER_STYLE_LEVEL_AUTHOR","author",1,"The style sheet will be treated as if it was provided by the loaded documents. That means other user style sheets may still override it."),
|
||||
("WebKitUserStyleLevel","WEBKIT_USER_STYLE_LEVEL_USER","user",None,"The style sheet is an user style sheet, its contents always override other style sheets. This is the default."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_HOST","invalid-host",809,"The host component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_PATH","invalid-path",810,"The path component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_INVALID_SCHEME","invalid-scheme",808,"The scheme component was invalid."),
|
||||
("WebKitWebExtensionMatchPatternError","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_ERROR_UNKNOWN","unknown",899,"An unknown error occured."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_MANIFESTV2","manifestv2",1,"For a ManifestV2 extension."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_MANIFESTV3","manifestv3",2,"For a ManifestV3 extension."),
|
||||
("WebKitWebExtensionMode","WEBKIT_WEB_EXTENSION_MODE_NONE","none",None,"Not for an extension."),
|
||||
@ -254,6 +260,10 @@
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING","include-selection-highlighting",1,"Whether to include in the snapshot the highlight of the selected content."),
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_NONE","none",None,"Do not include any special options."),
|
||||
("WebKitSnapshotOptions","WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND","transparent-background",2,"Do not fill the background with white before rendering the snapshot. Since 2.8"),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_IGNORE_PATHS","ignore-paths",4,"The host components should be ignored while matching."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_IGNORE_SCHEMES","ignore-schemes",2,"The scheme components should be ignored while matching."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_MATCH_BIDIRECTIONALLY","match-bidirectionally",8,"Two patterns should be checked in either direction while matching (A matches B, or B matches A). Invalid for matching URLs."),
|
||||
("WebKitWebExtensionMatchPatternOptions","WEBKIT_WEB_EXTENSION_MATCH_PATTERN_OPTIONS_NONE","none",1,"No special matching options."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_ALL","all",4095,"All types."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_COOKIES","cookies",64,"Cookies."),
|
||||
("WebKitWebsiteDataTypes","WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT","device-id-hash-salt",128,"Hash salt used to generate the device ids used by webpages."),
|
||||
@ -324,6 +334,7 @@
|
||||
("WebKitSettings","sans-serif-font-family","gchararray",None,None,None,"sans-serif",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","serif-font-family","gchararray",None,None,None,"serif",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","user-agent","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","webrtc-udp-ports-range","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitSettings","zoom-text-only","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitWebContext","time-zone-override","gchararray",None,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("WebKitWebView","automation-presentation-type","WebKitAutomationBrowsingContextPresentation",None,1,None,"window",None,None,None,None,None,None,None,None,None,None,None),
|
||||
|
@ -24,6 +24,12 @@
|
||||
</properties>
|
||||
</GtkAccessible>
|
||||
|
||||
<GtkAssistant>
|
||||
<internal-children>
|
||||
<child name="action_area"/>
|
||||
</internal-children>
|
||||
</GtkAssistant>
|
||||
|
||||
<GtkAssistantPage>
|
||||
<properties>
|
||||
<property id="title" translatable="True"/>
|
||||
@ -80,54 +86,6 @@
|
||||
</properties>
|
||||
</GtkPrintJob>
|
||||
|
||||
<GtkBoxLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkBoxLayoutChild>
|
||||
|
||||
<GtkHeaderBarLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkHeaderBarLayoutChild>
|
||||
|
||||
<GtkNotebookLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkNotebookLayoutChild>
|
||||
|
||||
<GtkActionBarLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkActionBarLayoutChild>
|
||||
|
||||
<GtkPopoverMenuBarLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkPopoverMenuBarLayoutChild>
|
||||
|
||||
<GtkStackLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkStackLayoutChild>
|
||||
|
||||
<GtkToolItemGroupLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkToolItemGroupLayoutChild>
|
||||
|
||||
<GtkPopoverMenuLayoutChild>
|
||||
<properties>
|
||||
<property id="position" target="Gtk+-3.0" is-position="True"/>
|
||||
</properties>
|
||||
</GtkPopoverMenuLayoutChild>
|
||||
|
||||
<GtkGridLayoutChild>
|
||||
<properties target="Gtk+-3.0">
|
||||
<property id="left-attach" save-always="True"/>
|
||||
@ -145,6 +103,17 @@
|
||||
<action-widget response="gint">GtkWidget</action-widget>
|
||||
</action-widgets>
|
||||
</data>
|
||||
<children-types>
|
||||
<type>action</type>
|
||||
</children-types>
|
||||
<internal-children target="Gtk-4.0">
|
||||
<child name="action_area"/>
|
||||
</internal-children>
|
||||
<internal-children target="Gtk+-3.0">
|
||||
<child name="vbox">
|
||||
<child name="action_area"/>
|
||||
</child>
|
||||
</internal-children>
|
||||
</GtkDialog>
|
||||
|
||||
<GtkListStore>
|
||||
@ -246,7 +215,7 @@
|
||||
<GtkComboBoxText>
|
||||
<data>
|
||||
<items>
|
||||
<item id="gchararray">gchararray</item>
|
||||
<item id="gchararray" Cmb:translatable="True">gchararray</item>
|
||||
</items>
|
||||
</data>
|
||||
</GtkComboBoxText>
|
||||
@ -321,6 +290,9 @@
|
||||
<properties>
|
||||
<property id="tearoff-title" translatable="True"/>
|
||||
</properties>
|
||||
<internal-children>
|
||||
<child name="entry" type="GtkEntry" creation-property-id="has-entry"/>
|
||||
</internal-children>
|
||||
</GtkComboBox>
|
||||
|
||||
<GtkAppChooserButton>
|
||||
@ -384,6 +356,12 @@
|
||||
</properties>
|
||||
</GtkAction>
|
||||
|
||||
<GtkTreeView>
|
||||
<internal-children>
|
||||
<child name="selection" anarchist="True"/>
|
||||
</internal-children>
|
||||
</GtkTreeView>
|
||||
|
||||
<GtkTreeViewColumn>
|
||||
<properties>
|
||||
<property id="title" translatable="True"/>
|
||||
@ -566,6 +544,45 @@
|
||||
</data>
|
||||
</GtkFileFilter>
|
||||
|
||||
<GtkScaleButton>
|
||||
<internal-children>
|
||||
<child name="plus_button"/>
|
||||
<child name="minus_button"/>
|
||||
</internal-children>
|
||||
</GtkScaleButton>
|
||||
|
||||
<GtkInfoBar>
|
||||
<internal-children target="Gtk+-3.0">
|
||||
<child name="action_area"/>
|
||||
<child name="content_area"/>
|
||||
</internal-children>
|
||||
</GtkInfoBar>
|
||||
|
||||
<GtkColorSelectionDialog target="Gtk+-3.0">
|
||||
<internal-children>
|
||||
<child name="vbox">
|
||||
<child name="color_selection"/>
|
||||
</child>
|
||||
<child name="action_area">
|
||||
<child name="ok_button"/>
|
||||
<child name="cancel_button"/>
|
||||
<child name="help_button"/>
|
||||
</child>
|
||||
</internal-children>
|
||||
</GtkColorSelectionDialog>
|
||||
|
||||
<GtkFontSelectionDialog target="Gtk+-3.0">
|
||||
<internal-children>
|
||||
<child name="vbox">
|
||||
<child name="font_selection"/>
|
||||
</child>
|
||||
<child name="action_area">
|
||||
<child name="ok_button"/>
|
||||
<child name="cancel_button"/>
|
||||
<child name="apply_button"/>
|
||||
</child>
|
||||
</internal-children>
|
||||
</GtkFontSelectionDialog>
|
||||
</types>
|
||||
|
||||
<categories>
|
||||
@ -577,6 +594,8 @@
|
||||
<GtkDialog/>
|
||||
<GtkAboutDialog/>
|
||||
<GtkFileChooserDialog/>
|
||||
<GtkColorSelectionDialog/>
|
||||
<GtkFontSelectionDialog/>
|
||||
<GtkColorChooserDialog/>
|
||||
<GtkFontChooserDialog/>
|
||||
<GtkMessageDialog/>
|
||||
|
@ -246,7 +246,7 @@
|
||||
("GdkFrameClockPhase","GDK_FRAME_CLOCK_PHASE_UPDATE","update",4,"corresponds to GdkFrameClock::update."),
|
||||
("GdkGLAPI","GDK_GL_API_GL","gl",1,"The OpenGL API"),
|
||||
("GdkGLAPI","GDK_GL_API_GLES","gles",2,"The OpenGL ES API"),
|
||||
("GdkModifierType","GDK_ALT_MASK","alt-mask",8,"the fourth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier, but normally it is the Alt key)."),
|
||||
("GdkModifierType","GDK_ALT_MASK","alt-mask",8,"the fourth modifier key (it depends on the Windowing System configuration which key is interpreted as this modifier, but normally it is the <kbd>Alt</kbd> key)."),
|
||||
("GdkModifierType","GDK_BUTTON1_MASK","button1-mask",256,"the first mouse button."),
|
||||
("GdkModifierType","GDK_BUTTON2_MASK","button2-mask",512,"the second mouse button."),
|
||||
("GdkModifierType","GDK_BUTTON3_MASK","button3-mask",1024,"the third mouse button."),
|
||||
@ -254,7 +254,7 @@
|
||||
("GdkModifierType","GDK_BUTTON5_MASK","button5-mask",4096,"the fifth mouse button."),
|
||||
("GdkModifierType","GDK_CONTROL_MASK","control-mask",4,"the Control key."),
|
||||
("GdkModifierType","GDK_HYPER_MASK","hyper-mask",134217728,"the Hyper modifier."),
|
||||
("GdkModifierType","GDK_LOCK_MASK","lock-mask",2,"a Lock key (depending on the modifier mapping of the X server this may either be CapsLock or ShiftLock)."),
|
||||
("GdkModifierType","GDK_LOCK_MASK","lock-mask",2,"a Lock key (depending on the Windowing System configuration, this may either be <kbd>CapsLock</kbd> or <kbd>ShiftLock</kbd>)."),
|
||||
("GdkModifierType","GDK_META_MASK","meta-mask",268435456,"the Meta modifier. Maps to Command on macOS."),
|
||||
("GdkModifierType","GDK_NO_MODIFIER_MASK","no-modifier-mask",None,"No modifier."),
|
||||
("GdkModifierType","GDK_SHIFT_MASK","shift-mask",1,"the Shift key."),
|
||||
|
@ -79,7 +79,7 @@
|
||||
("GtkColorChooserDialog","GtkDialog","gtk+","3.4",None,None,1,"container","toplevel",None),
|
||||
("GtkColorChooserWidget","GtkBox","gtk+","3.4",None,None,1,"container","display",None),
|
||||
("GtkColorSelection","GtkBox","gtk+",None,None,None,1,"container",None,None),
|
||||
("GtkColorSelectionDialog","GtkDialog","gtk+",None,None,None,1,"container",None,None),
|
||||
("GtkColorSelectionDialog","GtkDialog","gtk+",None,None,None,1,"container","toplevel",None),
|
||||
("GtkComboBox","GtkBin","gtk+",None,None,None,1,"container","control",None),
|
||||
("GtkComboBoxText","GtkComboBox","gtk+",None,None,None,1,"container","control",None),
|
||||
("GtkContainer","GtkWidget","gtk+",None,None,1,1,"container",None,None),
|
||||
@ -130,7 +130,7 @@
|
||||
("GtkFontChooserLevel","flags","gtk+",None,None,None,None,None,None,None),
|
||||
("GtkFontChooserWidget","GtkBox","gtk+","3.2",None,None,1,"container","display",None),
|
||||
("GtkFontSelection","GtkBox","gtk+",None,"3.2",None,1,"container",None,None),
|
||||
("GtkFontSelectionDialog","GtkDialog","gtk+",None,"3.2",None,1,"container",None,None),
|
||||
("GtkFontSelectionDialog","GtkDialog","gtk+",None,"3.2",None,1,"container","toplevel",None),
|
||||
("GtkFrame","GtkBin","gtk+",None,None,None,1,"container","layout",None),
|
||||
("GtkGLArea","GtkWidget","gtk+","3.16",None,None,1,None,"display",None),
|
||||
("GtkGesture","GtkEventController","gtk+",None,None,1,1,None,None,None),
|
||||
@ -1371,7 +1371,7 @@
|
||||
</type_flags>
|
||||
<type_data>
|
||||
("GtkComboBoxText",1,None,"items",None,None),
|
||||
("GtkComboBoxText",2,1,"item","gchararray",None),
|
||||
("GtkComboBoxText",2,1,"item","gchararray",1),
|
||||
("GtkDialog",1,None,"action-widgets",None,None),
|
||||
("GtkDialog",2,1,"action-widget","GtkWidget",None),
|
||||
("GtkFileFilter",1,None,"mime-types",None,None),
|
||||
@ -1414,6 +1414,7 @@
|
||||
("GtkWidget",2,"name","gchararray")
|
||||
</type_data_arg>
|
||||
<type_child_type>
|
||||
("GtkDialog","action",None,None),
|
||||
("GtkExpander","label",1,None),
|
||||
("GtkFrame","label",1,None),
|
||||
("GtkMenuItem","submenu",None,None),
|
||||
@ -1425,6 +1426,29 @@
|
||||
("GtkTextTagTable","tag",None,None),
|
||||
("GtkWindow","titlebar",1,None)
|
||||
</type_child_type>
|
||||
<type_internal_child>
|
||||
("GtkAssistant","action_area",None,"GtkBox",None),
|
||||
("GtkColorSelectionDialog","action_area",None,"GtkButtonBox",None),
|
||||
("GtkColorSelectionDialog","cancel_button","action_area","GtkButton",None),
|
||||
("GtkColorSelectionDialog","color_selection","vbox","GtkColorSelection",None),
|
||||
("GtkColorSelectionDialog","help_button","action_area","GtkButton",None),
|
||||
("GtkColorSelectionDialog","ok_button","action_area","GtkButton",None),
|
||||
("GtkColorSelectionDialog","vbox",None,"GtkBox",None),
|
||||
("GtkComboBox","entry",None,"GtkEntry","has-entry"),
|
||||
("GtkDialog","action_area","vbox","GtkButtonBox",None),
|
||||
("GtkDialog","vbox",None,"GtkBox",None),
|
||||
("GtkFontSelectionDialog","action_area",None,"GtkButtonBox",None),
|
||||
("GtkFontSelectionDialog","apply_button","action_area","GtkButton",None),
|
||||
("GtkFontSelectionDialog","cancel_button","action_area","GtkButton",None),
|
||||
("GtkFontSelectionDialog","font_selection","vbox","GtkFontSelection",None),
|
||||
("GtkFontSelectionDialog","ok_button","action_area","GtkButton",None),
|
||||
("GtkFontSelectionDialog","vbox",None,"GtkBox",None),
|
||||
("GtkInfoBar","action_area",None,"GtkButtonBox",None),
|
||||
("GtkInfoBar","content_area",None,"GtkBox",None),
|
||||
("GtkScaleButton","minus_button",None,"GtkButton",None),
|
||||
("GtkScaleButton","plus_button",None,"GtkButton",None),
|
||||
("GtkTreeView","selection",None,"GtkTreeSelection",None)
|
||||
</type_internal_child>
|
||||
<property>
|
||||
("CmbAccessibleAction","cmb-a11y-action-activate","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
("CmbAccessibleAction","cmb-a11y-action-click","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
@ -1497,7 +1521,7 @@
|
||||
("GtkAction","visible-overflown","gboolean",None,None,None,"True",None,None,None,"3.10",None,None,None,None,None,None,None),
|
||||
("GtkAction","visible-vertical","gboolean",None,None,None,"True",None,None,None,"3.10",None,None,None,None,None,None,None),
|
||||
("GtkActionBarLayoutChild","pack-type","GtkPackType",None,None,None,"start",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkActionBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkActionBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkActionGroup","accel-group","GtkAccelGroup",1,None,None,None,None,None,None,"3.10",None,None,None,None,None,None,None),
|
||||
("GtkActionGroup","name","gchararray",None,1,None,None,None,None,None,"3.10",None,None,None,None,None,None,None),
|
||||
("GtkActionGroup","sensitive","gboolean",None,None,None,"True",None,None,None,"3.10",None,None,None,None,None,None,None),
|
||||
@ -1557,7 +1581,7 @@
|
||||
("GtkBoxLayoutChild","fill","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkBoxLayoutChild","pack-type","GtkPackType",None,None,None,"start",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkBoxLayoutChild","padding","guint",None,None,None,"0","0","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkBoxLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkBoxLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkBuilder","translation-domain","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkButton","always-show-image","gboolean",None,None,None,"False",None,None,"3.6",None,None,None,None,None,None,None,None),
|
||||
("GtkButton","can-focus","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
@ -1908,7 +1932,7 @@
|
||||
("GtkHeaderBar","subtitle","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkHeaderBar","title","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkHeaderBarLayoutChild","pack-type","GtkPackType",None,None,None,"start",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkHeaderBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkHeaderBarLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkIMContext","input-hints","GtkInputHints",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkIMContext","input-purpose","GtkInputPurpose",None,None,None,"free-form",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkIconView","activate-on-single-click","gboolean",None,None,None,"False",None,None,"3.8",None,None,None,None,None,None,None,None),
|
||||
@ -2061,7 +2085,7 @@
|
||||
("GtkNotebook","tab-pos","GtkPositionType",None,None,None,"top",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","detachable","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","menu-label","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","reorderable","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","tab-expand","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkNotebookLayoutChild","tab-fill","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -2102,7 +2126,7 @@
|
||||
("GtkPopover","relative-to","GtkWidget",1,None,None,None,None,None,"3.12",None,None,None,None,None,None,None,None),
|
||||
("GtkPopover","transitions-enabled","gboolean",None,None,None,"True",None,None,"3.16","3.22",None,None,None,None,None,None,None),
|
||||
("GtkPopoverMenu","visible-submenu","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkPopoverMenuLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkPopoverMenuLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkPopoverMenuLayoutChild","submenu","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkPrintOperation","allow-async","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkPrintOperation","current-page","gint",None,None,None,"-1","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
@ -2340,7 +2364,7 @@
|
||||
("GtkStackLayoutChild","icon-name","CmbIconName",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkStackLayoutChild","name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkStackLayoutChild","needs-attention","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkStackLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkStackLayoutChild","position","gint",None,None,None,"0","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkStackLayoutChild","title","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkStackSidebar","stack","GtkStack",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkStackSwitcher","icon-size","gint",None,None,None,"1","0","2147483647","3.20",None,None,None,None,None,None,None,None),
|
||||
@ -2503,7 +2527,7 @@
|
||||
("GtkToolItemGroupLayoutChild","fill","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolItemGroupLayoutChild","homogeneous","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolItemGroupLayoutChild","new-row","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolItemGroupLayoutChild","position","gint",None,None,None,"0","0","2147483647",None,None,None,None,1,None,None,None,None),
|
||||
("GtkToolItemGroupLayoutChild","position","gint",None,None,None,"0","0","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolPalette","icon-size","GtkIconSize",None,None,None,"small-toolbar",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolPalette","icon-size-set","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkToolPalette","toolbar-style","GtkToolbarStyle",None,None,None,"icons",None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -2714,6 +2738,7 @@
|
||||
("GtkEntry","paste-clipboard",None,None,None),
|
||||
("GtkEntry","populate-popup",None,None,None),
|
||||
("GtkEntry","preedit-changed",None,None,None),
|
||||
("GtkEntry","toggle-direction",None,None,None),
|
||||
("GtkEntry","toggle-overwrite",None,None,None),
|
||||
("GtkEntryBuffer","deleted-text",None,None,None),
|
||||
("GtkEntryBuffer","inserted-text",None,None,None),
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<!DOCTYPE cambalache-catalog SYSTEM "cambalache-catalog.dtd">
|
||||
<cambalache-catalog name="gtk" namespace="Gtk" prefix="Gtk" version="4.0" targets="4.0,4.10,4.12,4.14,4.16,4.2,4.4,4.6,4.8" depends="gdk-4.0,gsk-4.0">
|
||||
<cambalache-catalog name="gtk" namespace="Gtk" prefix="Gtk" version="4.0" targets="4.0,4.10,4.12,4.14,4.16,4.18,4.2,4.4,4.6,4.8" depends="gdk-4.0,gsk-4.0">
|
||||
<type>
|
||||
("CmbAccessibleList","gchararray","gtk",None,None,None,None,None,None,None),
|
||||
("CmbAccessibleProperty","interface","gtk",None,None,None,None,None,None,None),
|
||||
@ -337,15 +337,15 @@
|
||||
("GtkShortcutAction","GObject","gtk",None,None,1,1,None,None,None),
|
||||
("GtkShortcutActionFlags","flags","gtk",None,None,None,None,None,None,None),
|
||||
("GtkShortcutController","GtkEventController","gtk",None,None,None,1,"container",None,None),
|
||||
("GtkShortcutLabel","GtkWidget","gtk",None,None,None,1,"container",None,None),
|
||||
("GtkShortcutLabel","GtkWidget","gtk",None,"4.18",None,1,"container",None,None),
|
||||
("GtkShortcutManager","interface","gtk",None,None,None,None,None,None,None),
|
||||
("GtkShortcutScope","enum","gtk",None,None,None,None,None,None,None),
|
||||
("GtkShortcutTrigger","GObject","gtk",None,None,1,1,None,None,None),
|
||||
("GtkShortcutType","enum","gtk",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","GtkBox","gtk",None,None,None,1,"container",None,None),
|
||||
("GtkShortcutsSection","GtkBox","gtk",None,None,None,1,"container",None,None),
|
||||
("GtkShortcutsShortcut","GtkWidget","gtk",None,None,None,1,"container",None,None),
|
||||
("GtkShortcutsWindow","GtkWindow","gtk",None,None,None,None,"container",None,None),
|
||||
("GtkShortcutsGroup","GtkBox","gtk",None,"4.18",None,1,"container",None,None),
|
||||
("GtkShortcutsSection","GtkBox","gtk",None,"4.18",None,1,"container",None,None),
|
||||
("GtkShortcutsShortcut","GtkWidget","gtk",None,"4.18",None,1,"container",None,None),
|
||||
("GtkShortcutsWindow","GtkWindow","gtk",None,"4.18",None,None,"container",None,None),
|
||||
("GtkSignalAction","GtkShortcutAction","gtk",None,None,None,1,None,None,None),
|
||||
("GtkSignalListItemFactory","GtkListItemFactory","gtk",None,None,None,1,None,None,None),
|
||||
("GtkSingleSelection","GObject","gtk",None,None,None,1,None,None,None),
|
||||
@ -959,7 +959,7 @@
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_DESCRIPTION","description",1,"Defines a string value that describes or annotates the current element. Value type: string"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_HAS_POPUP","has-popup",2,"Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element."),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_HELP_TEXT","help-text",19,"Defines a string value that provides a description of non-standard keyboard interactions of the current element. Value type: string"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS","key-shortcuts",3,"Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. Value type: string"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS","key-shortcuts",3,"Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. Value type: string. The format of the value is a space-separated list of shortcuts, with each shortcut consisting of one or more modifiers (`Control`, `Alt` or `Shift`), followed by a non-modifier key, all separated by `+`. Examples: `F2`, `Alt-F`, `Control+Shift+N`"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_LABEL","label",4,"Defines a string value that labels the current element. Value type: string"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_LEVEL","level",5,"Defines the hierarchical level of an element within a structure. Value type: integer"),
|
||||
("GtkAccessibleProperty","GTK_ACCESSIBLE_PROPERTY_MODAL","modal",6,"Indicates whether an element is modal when displayed. Value type: boolean"),
|
||||
@ -980,12 +980,18 @@
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_COL_INDEX","col-index",2,"Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. Value type: integer"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT","col-index-text",3,"Defines a human readable text alternative of %GTK_ACCESSIBLE_RELATION_COL_INDEX. Value type: string"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_COL_SPAN","col-span",4,"Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. Value type: integer"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_CONTROLLED_BY","controlled-by",20,"Identifies the element (or elements) that the current element is controlled by. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_CONTROLS","controls",5,"Identifies the element (or elements) whose contents or presence are controlled by the current element. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_DESCRIBED_BY","described-by",6,"Identifies the element (or elements) that describes the object. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_DESCRIPTION_FOR","description-for",19,"Identifies the element (or elements) that are described by the current element. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_DETAILS","details",7,"Identifies the element (or elements) that provide additional information related to the object. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_DETAILS_FOR","details-for",21,"Identifies the element (or elements) for which the current element provides additional information. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE","error-message",8,"Identifies the element (or elements) that provide an error message for an object. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE_FOR","error-message-for",22,"Identifies the element (or elements) for which the current element provides an error message. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_FLOW_FROM","flow-from",23,"Identifies the previous element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_FLOW_TO","flow-to",9,"Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_LABELLED_BY","labelled-by",10,"Identifies the element (or elements) that labels the current element. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_LABEL_FOR","label-for",18,"Identifies the element (or elements) that are labeled by the current element. Value type: reference This relation is managed by GTK and should not be set from application code."),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_OWNS","owns",11,"Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between elements where the widget hierarchy cannot be used to represent the relationship. Value type: reference"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_POS_IN_SET","pos-in-set",12,"Defines an element's number or position in the current set of listitems or treeitems. Value type: integer"),
|
||||
("GtkAccessibleRelation","GTK_ACCESSIBLE_RELATION_ROW_COUNT","row-count",13,"Defines the total number of rows in a table, grid, or treegrid. Value type: integer"),
|
||||
@ -1232,12 +1238,12 @@
|
||||
("GtkFileChooserError","GTK_FILE_CHOOSER_ERROR_BAD_FILENAME","bad-filename",1,"Indicates a malformed filename."),
|
||||
("GtkFileChooserError","GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME","incomplete-hostname",3,"Indicates an incomplete hostname (e.g. \"http://foo\" without a slash after that)."),
|
||||
("GtkFileChooserError","GTK_FILE_CHOOSER_ERROR_NONEXISTENT","nonexistent",None,"Indicates that a file does not exist."),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_DIFFERENT","different",None,"The filter change cannot be described with any of the other enumeration values."),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_LESS_STRICT","less-strict",1,"The filter is less strict than it was before: All items that it used to return %TRUE for still return %TRUE, others now may, too."),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_MORE_STRICT","more-strict",2,"The filter is more strict than it was before: All items that it used to return %FALSE for still return %FALSE, others now may, too."),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_ALL","all",2,"The filter matches all items, gtk_filter_match() will alays return %TRUE."),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_NONE","none",1,"The filter does not match any item, gtk_filter_match() will always return %FALSE."),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_SOME","some",None,"The filter matches some items, gtk_filter_match() may return %TRUE or %FALSE"),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_DIFFERENT","different",None,"The filter change cannot be described with any of the other enumeration values"),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_LESS_STRICT","less-strict",1,"The filter is less strict than it was before: All items that it used to return true still return true, others now may, too."),
|
||||
("GtkFilterChange","GTK_FILTER_CHANGE_MORE_STRICT","more-strict",2,"The filter is more strict than it was before: All items that it used to return false still return false, others now may, too."),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_ALL","all",2,"The filter matches all items, [method@Gtk.Filter.match] will alays return true"),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_NONE","none",1,"The filter does not match any item, [method@Gtk.Filter.match] will always return false"),
|
||||
("GtkFilterMatch","GTK_FILTER_MATCH_SOME","some",None,"The filter matches some items, [method@Gtk.Filter.match] may return true or false"),
|
||||
("GtkFontLevel","GTK_FONT_LEVEL_FACE","face",1,"Select a font face (i.e. a family and a style)"),
|
||||
("GtkFontLevel","GTK_FONT_LEVEL_FAMILY","family",None,"Select a font family"),
|
||||
("GtkFontLevel","GTK_FONT_LEVEL_FEATURES","features",3,"Select a font and font features"),
|
||||
@ -1396,7 +1402,7 @@
|
||||
("GtkPrintStatus","GTK_PRINT_STATUS_PRINTING","printing",6,"The printer is processing the print job."),
|
||||
("GtkPrintStatus","GTK_PRINT_STATUS_SENDING_DATA","sending-data",3,"The print job is being sent off to the printer."),
|
||||
("GtkPropagationLimit","GTK_LIMIT_NONE","none",None,"Events are handled regardless of what their target is."),
|
||||
("GtkPropagationLimit","GTK_LIMIT_SAME_NATIVE","same-native",1,"Events are only handled if their target is in the same [iface@Native] as the event controllers widget. Note that some event types have two targets (origin and destination)."),
|
||||
("GtkPropagationLimit","GTK_LIMIT_SAME_NATIVE","same-native",1,"Events are only handled if their target is in the same [iface@Native] (or widget with [property@Gtk.Widget:limit-events] set) as the event controllers widget. Note that some event types have two targets (origin and destination)."),
|
||||
("GtkPropagationPhase","GTK_PHASE_BUBBLE","bubble",2,"Events are delivered in the bubble phase. The bubble phase happens after the capture phase, and before the default handlers are run. This phase runs from the event widget, up to the toplevel."),
|
||||
("GtkPropagationPhase","GTK_PHASE_CAPTURE","capture",1,"Events are delivered in the capture phase. The capture phase happens before the bubble phase, runs from the toplevel down to the event widget. This option should only be used on containers that might possibly handle events before their children do."),
|
||||
("GtkPropagationPhase","GTK_PHASE_NONE","none",None,"Events are not delivered."),
|
||||
@ -1521,9 +1527,9 @@
|
||||
("GtkStackTransitionType","GTK_STACK_TRANSITION_TYPE_UNDER_LEFT","under-left",14,"Uncover the new page by sliding to the left"),
|
||||
("GtkStackTransitionType","GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT","under-right",15,"Uncover the new page by sliding to the right"),
|
||||
("GtkStackTransitionType","GTK_STACK_TRANSITION_TYPE_UNDER_UP","under-up",12,"Uncover the new page by sliding up"),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_EXACT","exact",None,"The search string and text must match exactly."),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_PREFIX","prefix",2,"The text must begin with the search string."),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_SUBSTRING","substring",1,"The search string must be contained as a substring inside the text."),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_EXACT","exact",None,"The search string and text must match exactly"),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_PREFIX","prefix",2,"The text must begin with the search string"),
|
||||
("GtkStringFilterMatchMode","GTK_STRING_FILTER_MATCH_MODE_SUBSTRING","substring",1,"The search string must be contained as a substring inside the text"),
|
||||
("GtkSymbolicColor","GTK_SYMBOLIC_COLOR_ERROR","error",1,"Indication color for errors"),
|
||||
("GtkSymbolicColor","GTK_SYMBOLIC_COLOR_FOREGROUND","foreground",None,"The default foreground color"),
|
||||
("GtkSymbolicColor","GTK_SYMBOLIC_COLOR_SUCCESS","success",3,"Indication color for success"),
|
||||
@ -1581,8 +1587,9 @@
|
||||
("GtkCellRendererState","GTK_CELL_RENDERER_SORTED","sorted",8,"The cell is in a sorted row"),
|
||||
("GtkDebugFlags","GTK_DEBUG_A11Y","a11y",131072,"Information about accessibility state changes"),
|
||||
("GtkDebugFlags","GTK_DEBUG_ACTIONS","actions",4096,"Information about actions and menu models"),
|
||||
("GtkDebugFlags","GTK_DEBUG_BUILDER","builder",128,"Trace GtkBuilder operation"),
|
||||
("GtkDebugFlags","GTK_DEBUG_BUILDER","builder",2097152,"Trace GtkBuilder operation"),
|
||||
("GtkDebugFlags","GTK_DEBUG_BUILDER_OBJECTS","builder-objects",65536,"Log unused GtkBuilder objects"),
|
||||
("GtkDebugFlags","GTK_DEBUG_BUILDER_TRACE","builder-trace",128,None),
|
||||
("GtkDebugFlags","GTK_DEBUG_CONSTRAINTS","constraints",32768,"Information from the constraints solver"),
|
||||
("GtkDebugFlags","GTK_DEBUG_CSS","css",1048576,"Information about deprecated CSS features."),
|
||||
("GtkDebugFlags","GTK_DEBUG_GEOMETRY","geometry",16,"Information about size allocation"),
|
||||
@ -1615,6 +1622,7 @@
|
||||
("GtkFontChooserLevel","GTK_FONT_CHOOSER_LEVEL_VARIATIONS","variations",4,"Allow changing OpenType font variation axes"),
|
||||
("GtkIconLookupFlags","GTK_ICON_LOOKUP_FORCE_REGULAR","force-regular",1,"Try to always load regular icons, even when symbolic icon names are given"),
|
||||
("GtkIconLookupFlags","GTK_ICON_LOOKUP_FORCE_SYMBOLIC","force-symbolic",2,"Try to always load symbolic icons, even when regular icon names are given"),
|
||||
("GtkIconLookupFlags","GTK_ICON_LOOKUP_NONE","none",None,"Perform a regular lookup."),
|
||||
("GtkIconLookupFlags","GTK_ICON_LOOKUP_PRELOAD","preload",4,"Starts loading the texture in the background so it is ready when later needed."),
|
||||
("GtkInputHints","GTK_INPUT_HINT_EMOJI","emoji",512,"Suggest offering Emoji support"),
|
||||
("GtkInputHints","GTK_INPUT_HINT_INHIBIT_OSK","inhibit-osk",128,"Suggest to not show an onscreen keyboard (e.g for a calculator that already has all the keys)."),
|
||||
@ -1680,7 +1688,7 @@
|
||||
</type_flags>
|
||||
<type_data>
|
||||
("GtkComboBoxText",1,None,"items",None,None),
|
||||
("GtkComboBoxText",2,1,"item","gchararray",None),
|
||||
("GtkComboBoxText",2,1,"item","gchararray",1),
|
||||
("GtkDialog",1,None,"action-widgets",None,None),
|
||||
("GtkDialog",2,1,"action-widget","GtkWidget",None),
|
||||
("GtkFileFilter",1,None,"mime-types",None,None),
|
||||
@ -1733,6 +1741,7 @@
|
||||
("GtkCenterBox","center",1,None),
|
||||
("GtkCenterBox","end",1,None),
|
||||
("GtkCenterBox","start",1,None),
|
||||
("GtkDialog","action",None,None),
|
||||
("GtkExpander","label",1,None),
|
||||
("GtkFrame","label",1,None),
|
||||
("GtkHeaderBar","end",None,None),
|
||||
@ -1748,6 +1757,14 @@
|
||||
<type_child_constraint>
|
||||
("GtkStack","GtkStackPage",1,1)
|
||||
</type_child_constraint>
|
||||
<type_internal_child>
|
||||
("GtkAssistant","action_area",None,"GtkBox",None),
|
||||
("GtkComboBox","entry",None,"GtkEntry","has-entry"),
|
||||
("GtkDialog","action_area",None,"GtkBox",None),
|
||||
("GtkScaleButton","minus_button",None,"GtkButton",None),
|
||||
("GtkScaleButton","plus_button",None,"GtkButton",None),
|
||||
("GtkTreeView","selection",None,"GtkTreeSelection",None)
|
||||
</type_internal_child>
|
||||
<property>
|
||||
("CmbAccessibleProperty","cmb-a11y-property-autocomplete","GtkAccessibleAutocomplete",None,None,None,"none",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("CmbAccessibleProperty","cmb-a11y-property-description","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
@ -2246,6 +2263,8 @@
|
||||
("GtkFontChooser","level","GtkFontChooserLevel",None,None,None,"style | size",None,None,None,"4.10",None,None,None,None,None,None,None),
|
||||
("GtkFontChooser","preview-text","gchararray",None,None,None,"The quick brown fox jumps over the lazy dog.",None,None,None,"4.10",None,None,None,None,None,None,None),
|
||||
("GtkFontChooser","show-preview-entry","gboolean",None,None,None,"True",None,None,None,"4.10",None,None,None,None,None,None,None),
|
||||
("GtkFontChooserDialog","default-height","gint",None,None,None,"500","-1","2147483647",None,None,None,None,None,None,None,"GtkWindow",None),
|
||||
("GtkFontChooserDialog","default-width","gint",None,None,None,"400","-1","2147483647",None,None,None,None,None,None,None,"GtkWindow",None),
|
||||
("GtkFontChooserDialog","title","gchararray",None,None,None,"Select Font",None,None,None,None,None,None,None,None,None,"GtkWindow",None),
|
||||
("GtkFontChooserDialog","use-header-bar","gint",None,1,None,"1","-1","1",None,"4.10",None,None,None,None,None,"GtkDialog",None),
|
||||
("GtkFontChooserWidget","css-name","gchararray",None,1,None,"fontchooser",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
@ -2313,6 +2332,7 @@
|
||||
("GtkHeaderBar","decoration-layout","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkHeaderBar","show-title-buttons","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkHeaderBar","title-widget","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkHeaderBar","use-native-controls","gboolean",None,None,None,"False",None,None,"4.18",None,None,None,None,None,None,None,None),
|
||||
("GtkIMContext","input-hints","GtkInputHints",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkIMContext","input-purpose","GtkInputPurpose",None,None,None,"free-form",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkIconPaintable","file","GFile",None,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -2410,6 +2430,7 @@
|
||||
("GtkListBox","focusable","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkListBox","selection-mode","GtkSelectionMode",None,None,None,"single",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkListBox","show-separators","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkListBox","tab-behavior","GtkListTabBehavior",None,None,None,"all",None,None,"4.18",None,None,None,None,None,None,None,None),
|
||||
("GtkListBoxRow","accessible-role","GtkAccessibleRole",None,None,None,"list-item",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkListBoxRow","activatable","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkListBoxRow","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -2725,42 +2746,42 @@
|
||||
("GtkShortcutController","mnemonic-modifiers","GdkModifierType",None,None,None,"alt-mask",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutController","model","GListModel",1,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutController","scope","GtkShortcutScope",None,None,None,"local",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutLabel","accelerator","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutLabel","accelerator","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutLabel","accessible-role","GtkAccessibleRole",None,None,None,"group",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkShortcutLabel","css-name","gchararray",None,1,None,"shortcut",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkShortcutLabel","disabled-text","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","accel-size-group","GtkSizeGroup",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutLabel","disabled-text","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","accel-size-group","GtkSizeGroup",1,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","accessible-role","GtkAccessibleRole",None,None,None,"group",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkShortcutsGroup","css-name","gchararray",None,1,None,"shortcuts-group",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkShortcutsGroup","orientation","GtkOrientation",None,None,None,"vertical",None,None,None,None,None,None,None,None,None,"GtkOrientable",None),
|
||||
("GtkShortcutsGroup","spacing","gint",None,None,None,"10","0","2147483647",None,None,None,None,None,None,None,"GtkBox",None),
|
||||
("GtkShortcutsGroup","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","title-size-group","GtkSizeGroup",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","view","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","title","gchararray",None,None,None,"",None,None,None,"4.18",1,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","title-size-group","GtkSizeGroup",1,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsGroup","view","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","css-name","gchararray",None,1,None,"shortcuts-section",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkShortcutsSection","max-height","guint",None,None,None,"15","0","4294967295",None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","max-height","guint",None,None,None,"15","0","4294967295",None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","orientation","GtkOrientation",None,None,None,"vertical",None,None,None,None,None,None,None,None,None,"GtkOrientable",None),
|
||||
("GtkShortcutsSection","section-name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","section-name","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","spacing","gint",None,None,None,"22","0","2147483647",None,None,None,None,None,None,None,"GtkBox",None),
|
||||
("GtkShortcutsSection","title","gchararray",None,None,None,None,None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","view-name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","accel-size-group","GtkSizeGroup",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","accelerator","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","title","gchararray",None,None,None,None,None,None,None,"4.18",1,None,None,None,None,None,None),
|
||||
("GtkShortcutsSection","view-name","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","accel-size-group","GtkSizeGroup",1,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","accelerator","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","accessible-role","GtkAccessibleRole",None,None,None,"label",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkShortcutsShortcut","action-name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","action-name","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","css-name","gchararray",None,1,None,"shortcut",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkShortcutsShortcut","direction","GtkTextDirection",None,None,None,"none",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","direction","GtkTextDirection",None,None,None,"none",None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","focusable","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkShortcutsShortcut","icon-set","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","shortcut-type","GtkShortcutType",None,None,None,"accelerator",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","subtitle","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","subtitle-set","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","title","gchararray",None,None,None,"",None,None,None,None,1,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","title-size-group","GtkSizeGroup",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","icon-set","gboolean",None,None,None,"False",None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","shortcut-type","GtkShortcutType",None,None,None,"accelerator",None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","subtitle","gchararray",None,None,None,"",None,None,None,"4.18",1,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","subtitle-set","gboolean",None,None,None,"False",None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","title","gchararray",None,None,None,"",None,None,None,"4.18",1,None,None,None,None,None,None),
|
||||
("GtkShortcutsShortcut","title-size-group","GtkSizeGroup",1,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsWindow","accessible-role","GtkAccessibleRole",None,None,None,"generic",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkShortcutsWindow","resizable","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,"GtkWindow",None),
|
||||
("GtkShortcutsWindow","section-name","gchararray",None,None,None,"internal-search",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsWindow","view-name","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkShortcutsWindow","section-name","gchararray",None,None,None,"internal-search",None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkShortcutsWindow","view-name","gchararray",None,None,None,None,None,None,None,"4.18",None,None,None,None,None,None,None),
|
||||
("GtkSignalAction","signal-name","gchararray",None,1,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkSingleSelection","autoselect","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkSingleSelection","can-unselect","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
@ -3034,6 +3055,7 @@
|
||||
("GtkWidget","hexpand","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","hexpand-set","gboolean",None,None,None,"False",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","layout-manager","GtkLayoutManager",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","limit-events","gboolean",None,None,None,"False",None,None,"4.18",None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","margin-bottom","gint",None,None,None,"0","0","32767",None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","margin-end","gint",None,None,None,"0","0","32767",None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","margin-start","gint",None,None,None,"0","0","32767",None,None,None,None,None,None,None,None,None),
|
||||
@ -3051,7 +3073,7 @@
|
||||
("GtkWidget","visible","gboolean",None,None,None,"True",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidget","width-request","gint",None,None,None,"-1","-1","2147483647",None,None,None,None,None,None,None,None,None),
|
||||
("GtkWidgetPaintable","widget","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWindow","accessible-role","GtkAccessibleRole",None,None,None,"application",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkWindow","accessible-role","GtkAccessibleRole",None,None,None,"window",None,None,None,None,None,None,None,None,None,"GtkAccessible",None),
|
||||
("GtkWindow","application","GtkApplication",1,None,None,None,None,None,None,None,None,1,None,None,None,None,None),
|
||||
("GtkWindow","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWindow","css-name","gchararray",None,1,None,"window",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
@ -3082,6 +3104,7 @@
|
||||
("GtkWindowControls","css-name","gchararray",None,1,None,"windowcontrols",None,None,None,None,None,None,None,None,None,"GtkWidget",None),
|
||||
("GtkWindowControls","decoration-layout","gchararray",None,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWindowControls","side","GtkPackType",None,None,None,"start",None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWindowControls","use-native-controls","gboolean",None,None,None,"False",None,None,"4.18",None,None,None,None,None,None,None,None),
|
||||
("GtkWindowHandle","child","GtkWidget",1,None,None,None,None,None,None,None,None,None,None,None,None,None,None),
|
||||
("GtkWindowHandle","css-name","gchararray",None,1,None,"windowhandle",None,None,None,None,None,None,None,None,None,"GtkWidget",None)
|
||||
</property>
|
||||
@ -3327,9 +3350,9 @@
|
||||
("GtkSearchEntry","stop-search",None,None,None),
|
||||
("GtkSectionModel","sections-changed","4.12",None,None),
|
||||
("GtkSelectionModel","selection-changed",None,None,None),
|
||||
("GtkShortcutsSection","change-current-page",None,None,None),
|
||||
("GtkShortcutsWindow","close",None,None,None),
|
||||
("GtkShortcutsWindow","search",None,None,None),
|
||||
("GtkShortcutsSection","change-current-page",None,"4.18",None),
|
||||
("GtkShortcutsWindow","close",None,"4.18",None),
|
||||
("GtkShortcutsWindow","search",None,"4.18",None),
|
||||
("GtkSignalListItemFactory","bind",None,None,None),
|
||||
("GtkSignalListItemFactory","setup",None,None,None),
|
||||
("GtkSignalListItemFactory","teardown",None,None,None),
|
||||
|
@ -1,18 +1,22 @@
|
||||
install_data([
|
||||
'atk/atk-1.0.xml',
|
||||
'glib/gobject-2.0.xml',
|
||||
'glib/gio-2.0.xml',
|
||||
'gdkpixbuf/gdkpixbuf-2.0.xml',
|
||||
'pango/pango-1.0.xml',
|
||||
'gtk/gdk-3.0.xml',
|
||||
'gtk/gdk-4.0.xml',
|
||||
'gtk/gsk-4.0.xml',
|
||||
'gtk/gtk-4.0.xml',
|
||||
'gtk/gtk+-3.0.xml',
|
||||
'gnome/webkit2gtk-4.1.xml',
|
||||
'gnome/webkitgtk-6.0.xml',
|
||||
'gnome/libhandy-1.xml',
|
||||
'gnome/libadwaita-1.xml'
|
||||
],
|
||||
install_dir: catalogsdir)
|
||||
|
||||
foreach data: [
|
||||
[gtk3_dep, ['atk/atk-1.0.xml', 'gtk/gdk-3.0.xml', 'gtk/gtk+-3.0.xml']],
|
||||
[handy_dep, ['gnome/libhandy-1.xml']],
|
||||
[webkit_dep, ['gnome/webkitgtk-6.0.xml']],
|
||||
[webkit2_dep, ['gnome/webkit2gtk-4.1.xml']],
|
||||
]
|
||||
if data[0].found()
|
||||
install_data(data[1], install_dir: catalogsdir)
|
||||
endif
|
||||
endforeach
|
@ -301,17 +301,19 @@
|
||||
("PangoWeight","PANGO_WEIGHT_ULTRAHEAVY","ultraheavy",1000,"the ultraheavy weight (= 1000) Since: 1.24"),
|
||||
("PangoWeight","PANGO_WEIGHT_ULTRALIGHT","ultralight",200,"the ultralight weight (= 200)"),
|
||||
("PangoWrapMode","PANGO_WRAP_CHAR","char",1,"wrap lines at character boundaries."),
|
||||
("PangoWrapMode","PANGO_WRAP_NONE","none",3,"do not wrap."),
|
||||
("PangoWrapMode","PANGO_WRAP_WORD","word",None,"wrap lines at word boundaries."),
|
||||
("PangoWrapMode","PANGO_WRAP_WORD_CHAR","word-char",2,"wrap lines at word boundaries, but fall back to character boundaries if there is not enough space for a full word.")
|
||||
</type_enum>
|
||||
<type_flags>
|
||||
("PangoFontMask","PANGO_FONT_MASK_FAMILY","family",1,"the font family is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_GRAVITY","gravity",64,"the font gravity is specified (Since: 1.16.)"),
|
||||
("PangoFontMask","PANGO_FONT_MASK_FEATURES","features",256,"OpenType font features are specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_GRAVITY","gravity",64,"The font gravity is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_SIZE","size",32,"the font size is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_STRETCH","stretch",16,"the font stretch is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_STYLE","style",2,"the font style is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_VARIANT","variant",4,"the font variant is specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_VARIATIONS","variations",128,"OpenType font variations are specified (Since: 1.42)"),
|
||||
("PangoFontMask","PANGO_FONT_MASK_VARIATIONS","variations",128,"OpenType font variations are specified."),
|
||||
("PangoFontMask","PANGO_FONT_MASK_WEIGHT","weight",8,"the font weight is specified."),
|
||||
("PangoLayoutDeserializeFlags","PANGO_LAYOUT_DESERIALIZE_CONTEXT","context",1,"Apply context information from the serialization to the `PangoContext`"),
|
||||
("PangoLayoutDeserializeFlags","PANGO_LAYOUT_DESERIALIZE_DEFAULT","default",None,"Default behavior"),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user