GPS: port to GTK4

This commit is contained in:
Stéphane Cerveau 2021-11-23 18:04:57 +01:00
parent b36fd0aebe
commit 25b2d1f8bf
6 changed files with 307 additions and 664 deletions

207
Cargo.lock generated
View file

@ -8,30 +8,6 @@ version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "atk"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a83b21d2aa75e464db56225e1bda2dd5993311ba1095acaa8fa03d1ae67026ba"
dependencies = [
"atk-sys",
"bitflags",
"glib 0.14.8",
"libc",
]
[[package]]
name = "atk-sys"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "badcf670157c84bb8b1cf6b5f70b650fed78da2033c9eed84c4e49b11cbe83ea"
dependencies = [
"glib-sys 0.14.0",
"gobject-sys 0.14.0",
"libc",
"system-deps 3.2.0",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -77,6 +53,15 @@ dependencies = [
"smallvec",
]
[[package]]
name = "cfg-expr"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edae0b9625d1fce32f7d64b71784d9b1bf8469ec1a9c417e44aaf16a9cbd7571"
dependencies = [
"smallvec",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -167,22 +152,6 @@ dependencies = [
"slab",
]
[[package]]
name = "gdk"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d749dcfc00d8de0d7c3a289e04a04293eb5ba3d8a4e64d64911d481fa9933b"
dependencies = [
"bitflags",
"cairo-rs",
"gdk-pixbuf",
"gdk-sys",
"gio",
"glib 0.14.8",
"libc",
"pango",
]
[[package]]
name = "gdk-pixbuf"
version = "0.14.0"
@ -209,20 +178,36 @@ dependencies = [
]
[[package]]
name = "gdk-sys"
version = "0.14.0"
name = "gdk4"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e091b3d3d6696949ac3b3fb3c62090e5bfd7bd6850bef5c3c5ea701de1b1f1e"
checksum = "f97a162c17214d1bf981af3f683156a0b1667dd1927057c4f0a68513251ecf0f"
dependencies = [
"bitflags",
"cairo-rs",
"gdk-pixbuf",
"gdk4-sys",
"gio",
"glib 0.14.8",
"libc",
"pango",
]
[[package]]
name = "gdk4-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9498f4e06969fb96a4e4234dfe1d308a3ac6b120b3c6d93e3ec5c77fe88bc6d5"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys",
"glib-sys 0.14.0",
"gobject-sys 0.14.0",
"graphene-sys",
"libc",
"pango-sys",
"pkg-config",
"system-deps 3.2.0",
"system-deps 5.0.0",
]
[[package]]
@ -366,13 +351,68 @@ dependencies = [
"system-deps 3.2.0",
]
[[package]]
name = "graphene-rs"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3380f132530ef9eb9e0a2bac180e30390aa5e49892d20294f822a974117a563"
dependencies = [
"glib 0.14.8",
"graphene-sys",
"libc",
]
[[package]]
name = "graphene-sys"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a9ac7450b3aa80792513a3c029920a2ede419de13fb5169a4e51b07a5685332"
dependencies = [
"glib-sys 0.14.0",
"libc",
"pkg-config",
"system-deps 3.2.0",
]
[[package]]
name = "gsk4"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff59ca46c4fc5087fd7a0c3770a71ea4b6e94f8c24c12e2c2e8538f9f6fd764"
dependencies = [
"bitflags",
"cairo-rs",
"gdk4",
"glib 0.14.8",
"graphene-rs",
"gsk4-sys",
"libc",
"pango",
]
[[package]]
name = "gsk4-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aa53ce70234da02f9954339d988d5ab853d746a8f47a4ae17735ff873545b5"
dependencies = [
"cairo-sys-rs",
"gdk4-sys",
"glib-sys 0.14.0",
"gobject-sys 0.14.0",
"graphene-sys",
"libc",
"pango-sys",
"system-deps 5.0.0",
]
[[package]]
name = "gst_pipeline_studio"
version = "0.1.0"
dependencies = [
"anyhow",
"gstreamer",
"gtk",
"gtk4",
]
[[package]]
@ -412,54 +452,37 @@ dependencies = [
]
[[package]]
name = "gtk"
version = "0.14.3"
name = "gtk4"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb51122dd3317e9327ec1e4faa151d1fa0d95664cd8fb8dcfacf4d4d29ac70c"
checksum = "58a04f421d1485ba4739e723199f5828bca05ab4e622ed39a96a342b6b1a6a3d"
dependencies = [
"atk",
"bitflags",
"cairo-rs",
"field-offset",
"futures-channel",
"gdk",
"gdk-pixbuf",
"gdk4",
"gio",
"glib 0.14.8",
"gtk-sys",
"gtk3-macros",
"graphene-rs",
"gsk4",
"gtk4-macros",
"gtk4-sys",
"libc",
"once_cell",
"pango",
"pkg-config",
]
[[package]]
name = "gtk-sys"
version = "0.14.0"
name = "gtk4-macros"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c14c8d3da0545785a7c5a120345b3abb534010fb8ae0f2ef3f47c027fba303e"
dependencies = [
"atk-sys",
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk-sys",
"gio-sys",
"glib-sys 0.14.0",
"gobject-sys 0.14.0",
"libc",
"pango-sys",
"system-deps 3.2.0",
]
[[package]]
name = "gtk3-macros"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21de1da96dc117443fb03c2e270b2d34b7de98d0a79a19bbb689476173745b79"
checksum = "5068d4354af02454f44687adc613100aa98ae11e273cdcac84f89dc08be2b4a1"
dependencies = [
"anyhow",
"heck",
"itertools 0.10.1",
"proc-macro-crate 1.1.0",
"proc-macro-error",
"proc-macro2",
@ -467,6 +490,25 @@ dependencies = [
"syn",
]
[[package]]
name = "gtk4-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e20a64c8f0ddcff8902ff04c130747f2fb7834a43530f75d03d6c71335733b49"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk4-sys",
"gio-sys",
"glib-sys 0.14.0",
"gobject-sys 0.14.0",
"graphene-sys",
"gsk4-sys",
"libc",
"pango-sys",
"system-deps 5.0.0",
]
[[package]]
name = "heck"
version = "0.3.3"
@ -802,7 +844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6"
dependencies = [
"anyhow",
"cfg-expr",
"cfg-expr 0.8.1",
"heck",
"itertools 0.10.1",
"pkg-config",
@ -813,6 +855,19 @@ dependencies = [
"version-compare 0.0.11",
]
[[package]]
name = "system-deps"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e"
dependencies = [
"cfg-expr 0.9.0",
"heck",
"pkg-config",
"toml",
"version-compare 0.0.11",
]
[[package]]
name = "thiserror"
version = "1.0.30"

View file

@ -6,6 +6,6 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
gtk = "0.14.3"
gtk = { version = "0.3", package = "gtk4" }
anyhow = "1"
gstreamer = "0.16"

View file

@ -13,13 +13,13 @@ Check https://rustup.rs for alternative installation options.
### Ubuntu/Debian/etc
```sh
apt install libgtk-3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
apt install libgtk-4-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
```
### Fedora/RedHat/SuSE/etc
```sh
dnf install gtk3-devel gstreamer1-devel gstreamer1-plugins-base-devel
dnf install gtk4-devel gstreamer1-devel gstreamer1-plugins-base-devel
```
## Getting started

View file

@ -17,11 +17,11 @@
//
// SPDX-License-Identifier: GPL-3.0-only
use gtk::cairo::Context;
use gtk::glib;
use gtk::prelude::*;
use gtk::{gio, glib};
use gtk::{
AboutDialog, AccelFlags, AccelGroup, ApplicationWindow, Builder, Button, DrawingArea, EventBox,
FileChooserDialog, MenuItem, ResponseType, Viewport, WindowPosition,
AboutDialog, Application, ApplicationWindow, Builder, Button, DrawingArea, FileChooserDialog,
ResponseType, Statusbar, Viewport,
};
use std::cell::RefCell;
use std::rc::{Rc, Weak};
@ -79,8 +79,7 @@ impl GPSApp {
let builder = Builder::from_string(glade_src);
let window: ApplicationWindow = builder.object("mainwindow").expect("Couldn't get window");
window.set_application(Some(application));
window.set_title("GstPipelineStudio");
window.set_position(WindowPosition::Center);
window.set_title(Some("GstPipelineStudio"));
window.set_size_request(800, 600);
let pipeline = Pipeline::new().expect("Unable to initialize the pipeline");
let drawing_area = DrawingArea::new();
@ -109,10 +108,11 @@ impl GPSApp {
// When the application is activated show the UI. This happens when the first process is
// started, and in the first process whenever a second process is started
let app_weak = app.downgrade();
application.connect_activate(move |_| {
application.connect_activate(glib::clone!(@weak application => move |_| {
let app = upgrade_weak!(app_weak);
app.build_ui();
});
app.build_ui(&application);
}));
let app_container = RefCell::new(Some(app));
application.connect_shutdown(move |_| {
@ -124,58 +124,74 @@ impl GPSApp {
});
}
pub fn build_ui(&self) {
let view_port: Viewport = self
.builder
.object("drawing_area")
.expect("Couldn't get window");
let event_box = EventBox::new();
event_box.add(&self.drawing_area);
view_port.add(&event_box);
pub fn build_ui(&self, application: &Application) {
let app_weak = self.downgrade();
self.drawing_area.connect_draw(move |w, c| {
let app = upgrade_weak!(app_weak, gtk::Inhibit(false));
println!("w: {} c:{}", w, c);
let drawing_area = gtk::DrawingArea::builder()
.content_height(24)
.content_width(24)
.build();
drawing_area.set_draw_func(move |_, c, width, height| {
let app = upgrade_weak!(app_weak);
println!("w: {} h: {} c:{}", width, height, c);
let mut graph = app.graph.borrow_mut();
let elements = graph.elements();
draw_elements(&elements, c);
gtk::Inhibit(false)
});
let app_weak = self.downgrade();
event_box.connect_button_release_event(move |_w, evt| {
let app = upgrade_weak!(app_weak, gtk::Inhibit(false));
let mut element: Element = Default::default();
element.position.0 = evt.position().0;
element.position.1 = evt.position().1;
app.add_new_element(element);
app.drawing_area.queue_draw();
gtk::Inhibit(false)
c.paint().expect("Invalid cairo surface state");
});
let drawing_area_window: Viewport = self
.builder
.object("drawing_area")
.expect("Couldn't get window");
drawing_area_window.set_child(Some(&drawing_area));
// let app_weak = self.downgrade();
// event_box.connect_button_release_event(move |_w, evt| {
// let app = upgrade_weak!(app_weak, gtk::Inhibit(false));
// let mut element: Element = Default::default();
// element.position.0 = evt.position().0;
// element.position.1 = evt.position().1;
// app.add_new_element(element);
// app.drawing_area.queue_draw();
// gtk::Inhibit(false)
// });
let window = &self.window;
window.show_all();
window.show();
let status_bar: Statusbar = self
.builder
.object("status_bar")
.expect("Couldn't get window");
status_bar.push(status_bar.context_id("Description"), "GPS is ready");
let action = gio::SimpleAction::new("quit", None);
action.connect_activate({
let app = application.downgrade();
move |_, _| {
let app = app.upgrade().unwrap();
app.quit();
}
});
application.add_action(&action);
application.set_accels_for_action("app.quit", &["<primary>q"]);
let action = gio::SimpleAction::new("new-window", None);
application.add_action(&action);
application.set_accels_for_action("app.new-window", &["<primary>n"]);
let quit: MenuItem = self
.builder
.object("menu-quit")
.expect("Couldn't get window");
let about: MenuItem = self
.builder
.object("menu-about")
.expect("Couldn't get window");
let about_dialog: AboutDialog = self
.builder
.object("dialog-about")
.expect("Couldn't get window");
about.connect_activate(move |_| {
about_dialog.connect_delete_event(|dialog, _| {
dialog.hide();
gtk::Inhibit(true)
});
about_dialog.show_all();
let action = gio::SimpleAction::new("about", None);
action.connect_activate({
move |_, _| {
about_dialog.show();
}
});
application.add_action(&action);
application.set_accels_for_action("app.about", &["<primary>a"]);
// Create a dialog to select GStreamer elements.
let add_button: Button = self
@ -204,29 +220,16 @@ impl GPSApp {
("Open", ResponseType::Ok),
("Cancel", ResponseType::Cancel)
]);
open_dialog.set_select_multiple(true);
open_dialog.connect_response(|open_dialog, response| {
if response == ResponseType::Ok {
let files = open_dialog.filenames();
println!("Files: {:?}", files);
let file = open_dialog.file().expect("Couldn't get file");
println!("Files: {:?}", file);
}
open_dialog.close();
});
open_dialog.show_all();
open_dialog.show();
}));
let accel_group = AccelGroup::new();
window.add_accel_group(&accel_group);
quit.connect_activate(glib::clone!(@weak window => move |_| {
window.close();
}));
// `Primary` is `Ctrl` on Windows and Linux, and `command` on macOS
// It isn't available directly through `gdk::ModifierType`, since it has
// different values on different platforms.
let (key, modifier) = gtk::accelerator_parse("<Primary>Q");
quit.add_accelerator("activate", &accel_group, key, modifier, AccelFlags::VISIBLE);
}
// Downgrade to a weak reference

View file

@ -1,590 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<requires lib="gtk" version="4.0"/>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes" comments="Primary menu entry that opens a new window.">_New Window</attribute>
<attribute name="action">app.new-window</attribute>
<attribute name="accel">&lt;primary&gt;n</attribute>
</item>
<item>
<attribute name="label" translatable="yes" comments="Primary menu entry that opens the About dialog.">_About GstPipelineStudio</attribute>
<attribute name="action">app.about</attribute>
</item>
<item>
<attribute name="label" translatable="yes" comments="Primary menu entry that quit app">_Quit GstPipelineStudio</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
<object class="GtkAboutDialog" id="dialog-about">
<property name="can-focus">False</property>
<property name="type-hint">dialog</property>
<property name="program-name">GstPipelineStudio</property>
<property name="authors">Stéphane Cerveau</property>
<property name="logo-icon-name">image-missing</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkFileChooserDialog" id="dialog-open-file">
<property name="can-focus">False</property>
<property name="type-hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<property name="hide-on-close">True</property>
</object>
<object class="GtkDialog" id="dialog-plugin-list">
<property name="can-focus">False</property>
<property name="transient-for">mainwindow</property>
<property name="default-width">320</property>
<property name="default-height">260</property>
<property name="type-hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<property name="hide-on-close">True</property>
<child>
<object class="GtkBox" id="v_box">
<property name="orientation">horizontal</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="treeview-plugin-list">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTextView" id="textview-plugin-list">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="editable">False</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
<object class="GtkTreeView" id="treeview-plugin-list"/>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled2_window">
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkTextView" id="textview-plugin-list"/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkApplicationWindow" id="mainwindow">
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="title" translatable="yes">GstPipelineStudio</property>
<property name="default-width">800</property>
<property name="default-height">600</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header-bar">
<property name="hexpand">0</property>
<property name="show-title-buttons">True</property>
<child type="start">
<object class="GtkButton">
<property name="action-name">win.open</property>
<property name="label">Open</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">1</property>
<child>
<object class="GtkStatusbar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">end</property>
<property name="margin-left">10</property>
<property name="margin-right">10</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkMenuBar" id="menu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem" id="menu-new-graph">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menu-open-graph">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menu-save-graph">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menu-save-as-graph">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menu-quit">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Graph</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem" id="menu-add-element">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menu-open-uri">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-media-play</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-media-pause</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-media-stop</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem" id="menu-about">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="vexpand">False</property>
<property name="vexpand">0</property>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">start</property>
<object class="GtkBox">
<child>
<object class="GtkButton" id="button-add-plugin">
<property name="hexpand">1</property>
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<property name="receives-default">1</property>
<property name="icon-name">list-add</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-open-file">
<property name="hexpand">1</property>
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<property name="receives-default">1</property>
<property name="icon-name">document-open-symbolic</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-play">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="always-show-image">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-media-play</property>
</object>
</child>
<property name="hexpand">1</property>
<property name="receives-default">1</property>
<property name="icon-name">media-playback-start-symbolic</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-pause">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="always-show-image">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-media-pause</property>
</object>
</child>
<property name="hexpand">1</property>
<property name="receives-default">1</property>
<property name="icon-name">media-playback-pause-symbolic</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-stop">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="always-show-image">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-media-stop</property>
</object>
</child>
<property name="hexpand">1</property>
<property name="receives-default">1</property>
<property name="icon-name">media-playback-stop-symbolic</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-clear</property>
</object>
</child>
<object class="GtkButton" id="button-clear">
<property name="hexpand">1</property>
<property name="receives-default">1</property>
<property name="label">clear</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScale">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="draw-value">1</property>
<property name="round-digits">1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkScrolledWindow" id="drawing_area-window">
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="GtkViewport" id="drawing_area">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="GtkTreeView">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">column</property>
</object>
</child>
</object>
</child>
</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="valign">end</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
<property name="child">
<object class="GtkTreeView"/>
</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="status_bar">
</object>
</child>
</object>
</child>
</object>
</interface>

View file

@ -20,15 +20,11 @@ use crate::app::GPSApp;
use crate::graph::Element;
use crate::pipeline::ElementInfo;
use crate::pipeline::Pipeline;
use gtk::prelude::*;
use gtk::TextBuffer;
use gtk::{
glib::{self, clone},
prelude::*,
};
use gtk::{gio, glib};
use gtk::{
CellRendererText, Dialog, ListStore, TextView, TreeView, TreeViewColumn, WindowPosition,
};
use gtk::{CellRendererText, Dialog, ListStore, TextView, TreeView, TreeViewColumn};
fn create_and_fill_model(elements: &[ElementInfo]) -> ListStore {
// Creation of a model with two rows.
@ -41,6 +37,7 @@ fn create_and_fill_model(elements: &[ElementInfo]) -> ListStore {
&[(0, &(i as u32 + 1)), (1, &entry.name.as_ref().unwrap())],
);
}
model
}
@ -60,37 +57,35 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
.object("dialog-plugin-list")
.expect("Couldn't get window");
dialog.set_title("Plugin list");
dialog.set_position(WindowPosition::Center);
dialog.set_title(Some("Plugin list"));
dialog.set_default_size(640, 480);
let tree: TreeView = app
.builder
.object("treeview-plugin-list")
.expect("Couldn't get window");
let text_view: TextView = app
.builder
.object("textview-plugin-list")
.expect("Couldn't get window");
let text_buffer: TextBuffer = text_view
.buffer()
.expect("Couldn't get buffer from text_view");
let text_buffer: TextBuffer = text_view.buffer();
let tree: TreeView = app
.builder
.object("treeview-plugin-list")
.expect("Couldn't get window");
if tree.n_columns() < 2 {
append_column(&tree, 0);
append_column(&tree, 1);
}
tree.set_search_column(1);
let model = create_and_fill_model(elements);
// Setting the model into the view.
tree.set_model(Some(&model));
// The closure responds to selection changes by connection to "::cursor-changed" signal,
// that gets emitted when the cursor moves (focus changes).
tree.connect_cursor_changed(clone!(@weak dialog, @weak text_buffer => move |tree_view| {
tree.connect_cursor_changed(glib::clone!(@weak dialog, @weak text_buffer => move |tree_view| {
let selection = tree_view.selection();
if let Some((model, iter)) = selection.selected() {
let element_name = model
.value(&iter, 1)
.get(&iter, 1)
.get::<String>()
.expect("Treeview selection, column 1");
let description = Pipeline::element_description(&element_name).expect("Unable to get element list from GStreamer");
@ -101,7 +96,7 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
}));
let app_weak = app.downgrade();
tree.connect_row_activated(
clone!(@weak dialog => move |tree_view, _tree_path, _tree_column| {
glib::clone!(@weak dialog => move |tree_view, _tree_path, _tree_column| {
let app = upgrade_weak!(app_weak);
let selection = tree_view.selection();
if let Some((model, iter)) = selection.selected() {
@ -110,7 +105,7 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
//
let element = Element {
name: model
.value(&iter, 1)
.get(&iter, 1)
.get::<String>()
.expect("Treeview selection, column 1"),
position: (100.0,100.0),
@ -118,7 +113,7 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
};
let element_name = model
.value(&iter, 1)
.get(&iter, 1)
.get::<String>()
.expect("Treeview selection, column 1");
app.add_new_element(element);
@ -128,9 +123,5 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
}),
);
dialog.connect_delete_event(|dialog, _| {
dialog.hide();
gtk::Inhibit(true)
});
dialog.show_all();
dialog.show();
}