init: vm manager list view
This commit is contained in:
@@ -41,6 +41,8 @@ cd ..
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- The use the GTK Builder instead of templates.
|
||||||
|
|
||||||
## Look into virt-manager it uses python + spice-gtk
|
## Look into virt-manager it uses python + spice-gtk
|
||||||
|
|
||||||
Look into `virtManager/details/viewers.py` to see how spice-gtk is being used
|
Look into `virtManager/details/viewers.py` to see how spice-gtk is being used
|
||||||
@@ -68,6 +70,7 @@ import the glade file through GTK template
|
|||||||
- Also look into [PyGObject](https://pygobject.readthedocs.io/en/latest/guide/gtk_template.html) to know more about threading and async etc.
|
- 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-3.0)
|
- [GI Python API](https://lazka.github.io/pgi-docs/#Gtk-3.0)
|
||||||
- https://developer.gnome.org/documentation/tutorials/application.html
|
- https://developer.gnome.org/documentation/tutorials/application.html
|
||||||
|
- [GTK3 Python] https://github.com/sam-m888/python-gtk3-tutorial/tree/master
|
||||||
|
|
||||||
## My gripes with GTK
|
## My gripes with GTK
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!-- Generated with glade 3.40.0 -->
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk+" version="3.24"/>
|
|
||||||
<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>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="help_button">
|
|
||||||
<property name="label" translatable="yes">May I help you?</property>
|
|
||||||
<property name="name">asdasd</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>
|
|
||||||
<property name="image-position">top</property>
|
|
||||||
<signal name="clicked" handler="onButtonPressed" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="x">21</property>
|
|
||||||
<property name="y">21</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="coffee_label">
|
|
||||||
<property name="width-request">100</property>
|
|
||||||
<property name="height-request">80</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Get me some coffe! </property>
|
|
||||||
<property name="width-chars">0</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="x">178</property>
|
|
||||||
<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>
|
|
||||||
</template>
|
|
||||||
</interface>
|
|
||||||
@@ -8,98 +8,63 @@ import gi
|
|||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gio, Gtk
|
from gi.repository import Gio, Gtk
|
||||||
|
|
||||||
glade_dir = Path(__file__).parent
|
|
||||||
|
vms = [
|
||||||
|
("clan://clan.lol", True, "/home/user/my-clan"),
|
||||||
|
("clan://lassul.lol", False, "/home/user/my-clan"),
|
||||||
|
("clan://mic.lol", False, "/home/user/my-clan"),
|
||||||
|
]
|
||||||
|
class MainWindow(Gtk.Window):
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
# Initialize the main window
|
||||||
|
self.set_title("Clan VM Manager")
|
||||||
|
self.connect("delete-event", Gtk.main_quit)
|
||||||
|
|
||||||
|
# Some styling
|
||||||
|
self.set_border_width(10)
|
||||||
|
# self.set_default_size(500,300)
|
||||||
|
|
||||||
|
# Add a notebook layout
|
||||||
|
# https://python-gtk-3-tutorial.readthedocs.io/en/latest/layout.html#notebook
|
||||||
|
self.notebook = Gtk.Notebook()
|
||||||
|
self.add(self.notebook)
|
||||||
|
|
||||||
|
vms_store = Gtk.ListStore(str,bool,str)
|
||||||
|
for vm in vms:
|
||||||
|
vms_store.append(list(vm))
|
||||||
|
|
||||||
|
self.machine_tree_view = Gtk.TreeView(vms_store)
|
||||||
|
for idx, title in enumerate(["Url", "Autostart", "Path"]):
|
||||||
|
renderer = Gtk.CellRendererText()
|
||||||
|
col = Gtk.TreeViewColumn(title, renderer, text=idx)
|
||||||
|
col.set_sort_column_id(idx)
|
||||||
|
self.machine_tree_view.append_column(col)
|
||||||
|
|
||||||
|
|
||||||
#
|
self.machine_page = Gtk.Box()
|
||||||
# 1. our .glade file (may contain paths)
|
self.machine_page.set_border_width(10)
|
||||||
#
|
self.machine_page.add(self.machine_tree_view)
|
||||||
@Gtk.Template.from_file(glade_dir / "app.glade")
|
self.notebook.append_page(self.machine_page, Gtk.Label(label="Overview"))
|
||||||
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'
|
self.join_page = Gtk.Box()
|
||||||
back_button: Gtk.Button = Gtk.Template.Child()
|
self.join_page.set_border_width(10)
|
||||||
|
self.join_page.add(Gtk.Label(label="Add/Join another clan"))
|
||||||
@Gtk.Template.Callback()
|
self.notebook.append_page(
|
||||||
def onDestroy(self, _):
|
self.join_page, Gtk.Label(label="Add/Join")
|
||||||
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
|
# Must be called AFTER all components were added
|
||||||
self.window2 = SecondWindow(application=self)
|
self.show_all()
|
||||||
# Add the second window to the application
|
|
||||||
self.add_window(self.window2)
|
def on_button_click(self,widget):
|
||||||
|
print(f"{self} {widget}")
|
||||||
|
|
||||||
|
|
||||||
def start_app(args: argparse.Namespace) -> None:
|
def start_app(args: argparse.Namespace) -> None:
|
||||||
app = Application()
|
MainWindow()
|
||||||
app.run()
|
Gtk.main()
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?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>
|
|
||||||
Reference in New Issue
Block a user