forked from clan/clan-core
Added basic GTK window handling
This commit is contained in:
parent
bb7f92f9aa
commit
6df833d59b
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,6 +10,7 @@ result*
|
||||
/pkgs/clan-cli/clan_cli/webui/assets
|
||||
/machines
|
||||
nixos.qcow2
|
||||
**/*.glade~
|
||||
|
||||
# python
|
||||
__pycache__
|
||||
|
61
pkgs/clan-vm-manager/README.md
Normal file
61
pkgs/clan-vm-manager/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
## Developing GTK3 Applications
|
||||
|
||||
Here we will document on how to develop GTK3 application UI in python. First we want to setup
|
||||
an example code base to look into. In this case gnome-music.
|
||||
|
||||
## Setup gnome-music as code reference
|
||||
|
||||
gnome-music does not use glade
|
||||
|
||||
Clone gnome-music and check out the tag v40.0
|
||||
[gnome-music](https://github.com/GNOME/gnome-music/tree/40.0)
|
||||
|
||||
```bash
|
||||
git clone git@github.com:GNOME/gnome-music.git && cd gnome-music && git checkout 40.0
|
||||
```
|
||||
|
||||
Checkout nixpkgs version `468cb5980b56d348979488a74a9b5de638400160` for the correct gnome-music devshell then execute:
|
||||
|
||||
```bash
|
||||
|
||||
nix develop /home/username/Projects/nixpkgs#gnome.gnome-music
|
||||
```
|
||||
|
||||
Look into the file `gnome-music.in` which bootstraps the application.
|
||||
|
||||
## Setup gnu-cash as reference
|
||||
|
||||
Gnucash uses glade with complex UI
|
||||
Setup gnucash
|
||||
|
||||
```bash
|
||||
git clone git@github.com:Gnucash/gnucash.git
|
||||
git checkout ed4921271c863c7f6e0c800e206b25ac6e9ba4da
|
||||
|
||||
cd nixpkgs
|
||||
git checkout 015739d7bffa7da4e923978040a2f7cba6af3270
|
||||
nix develop /home/username/Projects/nixpkgs#gnucash
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cd ..
|
||||
make
|
||||
```
|
||||
|
||||
### Glade
|
||||
|
||||
Make sure to check the 'composit' box in glade in the GtkApplicationWindow to be able to
|
||||
import the glade file through GTK template
|
||||
|
||||
## Links
|
||||
|
||||
- Another python glade project [syncthing-gtk](https://github.com/kozec/syncthing-gtk)
|
||||
|
||||
- Other python glade project [linuxcnc](https://github.com/podarok/linuxcnc/tree/master)
|
||||
|
||||
- Install [Glade UI Toolbuilder](https://gitlab.gnome.org/GNOME/glade)
|
||||
|
||||
- To understand GTK3 Components look into the [Python GTK3 Tutorial](https://python-gtk-3-tutorial.readthedocs.io/en/latest/search.html?q=ApplicationWindow&check_keywords=yes&area=default)
|
||||
|
||||
- Also look into [PyGObject](https://pygobject.readthedocs.io/en/latest/guide/gtk_template.html) to know more about threading and async etc.
|
||||
- [GI Python API](https://lazka.github.io/pgi-docs/#Gtk-4.0/classes/ApplicationWindow.html#Gtk.ApplicationWindow)
|
||||
- https://developer.gnome.org/documentation/tutorials/application.html
|
@ -2,8 +2,9 @@
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkApplicationWindow" id="main-window">
|
||||
<template class="main-window" parent="GtkApplicationWindow">
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="destroy" handler="onDestroy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkFixed">
|
||||
<property name="name">asdasd</property>
|
||||
@ -19,7 +20,7 @@
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="image-position">top</property>
|
||||
<signal name="clicked" handler="on_help_button_clicked" object="coffee_label" swapped="no"/>
|
||||
<signal name="clicked" handler="onButtonPressed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">21</property>
|
||||
@ -40,10 +41,25 @@
|
||||
<property name="y">120</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="next_button">
|
||||
<property name="label" translatable="yes">Next</property>
|
||||
<property name="width-request">79</property>
|
||||
<property name="height-request">39</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<signal name="clicked" handler="onNextButtonPressed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">355</property>
|
||||
<property name="y">190</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="asdasd"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</template>
|
||||
</interface>
|
||||
|
@ -1,19 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse # noqa
|
||||
from pathlib import Path # noqa
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
import gi # noqa
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0") # noqa
|
||||
from gi.repository import Gtk # noqa
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gio, Gtk
|
||||
|
||||
glade_dir = Path(__file__).parent
|
||||
|
||||
|
||||
#
|
||||
# 1. our .glade file (may contain paths)
|
||||
#
|
||||
@Gtk.Template.from_file(glade_dir / "app.glade")
|
||||
class AppWindow(Gtk.ApplicationWindow):
|
||||
#
|
||||
# 2. the GtkApplicationWindow class
|
||||
#
|
||||
__gtype_name__ = "main-window"
|
||||
|
||||
#
|
||||
# 3. the Button name we saved above
|
||||
#
|
||||
help_button: Gtk.Button = Gtk.Template.Child()
|
||||
next_button: Gtk.Button = Gtk.Template.Child()
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def onDestroy(self, _):
|
||||
Gio.Application.quit(self.get_application())
|
||||
|
||||
#
|
||||
# 4. the signal handler name we saved above
|
||||
#
|
||||
@Gtk.Template.Callback()
|
||||
def onButtonPressed(self, widget, **_kwargs):
|
||||
assert self.help_button == widget
|
||||
print(widget.get_label())
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def onNextButtonPressed(self, widget, **_kwargs):
|
||||
assert self.next_button == widget
|
||||
# Hide the first window
|
||||
self.hide()
|
||||
|
||||
# Show the second window
|
||||
self.get_application().window2.show_all()
|
||||
|
||||
|
||||
# Decorate the second window class with the template
|
||||
@Gtk.Template.from_file(glade_dir / "second.glade")
|
||||
class SecondWindow(Gtk.ApplicationWindow):
|
||||
#
|
||||
# the GtkApplicationWindow class
|
||||
#
|
||||
__gtype_name__ = "second-window"
|
||||
|
||||
# import the button from the template with name 'back_button'
|
||||
back_button: Gtk.Button = Gtk.Template.Child()
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def onDestroy(self, _):
|
||||
Gio.Application.quit(self.get_application())
|
||||
|
||||
#
|
||||
# 'onBackButtonPressed' is the name of the signal handler we saved in glade
|
||||
#
|
||||
@Gtk.Template.Callback()
|
||||
def onBackButtonPressed(self, widget, **_kwargs):
|
||||
assert self.back_button == widget
|
||||
# Hide the second window
|
||||
self.hide()
|
||||
# Show the first window
|
||||
self.get_application().window1.show_all()
|
||||
|
||||
|
||||
class Application(Gtk.Application):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(
|
||||
*args,
|
||||
application_id="clan.lol.Gtk1",
|
||||
flags=Gio.ApplicationFlags.FLAGS_NONE,
|
||||
**kwargs,
|
||||
)
|
||||
self.window = None
|
||||
|
||||
def do_activate(self):
|
||||
# Load the first window from the template
|
||||
self.window1 = AppWindow(application=self)
|
||||
# Add the first window to the application
|
||||
self.add_window(self.window1)
|
||||
# Show the first window
|
||||
self.window1.show_all()
|
||||
|
||||
# Load the second window from the template
|
||||
self.window2 = SecondWindow(application=self)
|
||||
# Add the second window to the application
|
||||
self.add_window(self.window2)
|
||||
|
||||
|
||||
def start_app(args: argparse.Namespace) -> None:
|
||||
builder = Gtk.Builder()
|
||||
glade_file = Path(__file__).parent / "app.glade"
|
||||
builder.add_from_file(str(glade_file))
|
||||
window = builder.get_object("main-window")
|
||||
window.show_all()
|
||||
|
||||
Gtk.main()
|
||||
app = Application()
|
||||
app.run()
|
||||
|
44
pkgs/clan-vm-manager/clan_vm_manager/second.glade
Normal file
44
pkgs/clan-vm-manager/clan_vm_manager/second.glade
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<template class="second-window" parent="GtkApplicationWindow">
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="destroy" handler="onDestroy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkFixed">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="back_button">
|
||||
<property name="label" translatable="yes">go back</property>
|
||||
<property name="width-request">100</property>
|
||||
<property name="height-request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<signal name="clicked" handler="onBackButtonPressed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">348</property>
|
||||
<property name="y">201</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">button</property>
|
||||
<property name="width-request">100</property>
|
||||
<property name="height-request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">71</property>
|
||||
<property name="y">53</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@ -25,4 +25,4 @@ ignore_missing_imports = true
|
||||
line-length = 88
|
||||
|
||||
select = ["E", "F", "I", "N"]
|
||||
ignore = ["E501", "E402"]
|
||||
ignore = ["E501", "E402", "N802"]
|
||||
|
Loading…
Reference in New Issue
Block a user