UI: Add QR scan results
Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
This commit is contained in:
parent
92202b9084
commit
93b607955f
8 changed files with 157 additions and 17 deletions
|
@ -78,9 +78,13 @@ public class EyeNeko.Elements.QrScaner : Gst.Base.Transform {
|
||||||
image.set_data ((void[]) img, () => {}); // Don't free data
|
image.set_data ((void[]) img, () => {}); // Don't free data
|
||||||
scaner.scan_image (image);
|
scaner.scan_image (image);
|
||||||
for (unowned var sym = image.first_symbol (); sym != null; sym = sym.next ()) {
|
for (unowned var sym = image.first_symbol (); sym != null; sym = sym.next ()) {
|
||||||
var data = sym.get_data ();
|
unowned var data = sym.get_data ();
|
||||||
if (qr_codes.add (data))
|
if (qr_codes.add (data)) {
|
||||||
new_qr (data);
|
GLib.Idle.add (() => { // HACK it fixes GTK crash
|
||||||
|
new_qr (data);
|
||||||
|
return false;
|
||||||
|
}, Priority.DEFAULT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Gst.FlowReturn.OK;
|
return Gst.FlowReturn.OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<file preprocess="xml-stripblanks">window.ui</file>
|
<file preprocess="xml-stripblanks">window.ui</file>
|
||||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/caps-row.ui</file>
|
<file preprocess="xml-stripblanks">ui/caps-row.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">ui/qr-row.ui</file>
|
||||||
<file>style.css</file>
|
<file>style.css</file>
|
||||||
<file>shaders/ccm.glsl</file>
|
<file>shaders/ccm.glsl</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
|
|
|
@ -13,6 +13,7 @@ eyeneko_sources = [
|
||||||
'elements/qr_scaner.vala',
|
'elements/qr_scaner.vala',
|
||||||
'ui/preferences.vala',
|
'ui/preferences.vala',
|
||||||
'ui/caps-row.vala',
|
'ui/caps-row.vala',
|
||||||
|
'ui/qr-row.vala',
|
||||||
'logic/friendly-caps.vala',
|
'logic/friendly-caps.vala',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ blueprints = custom_target(
|
||||||
input: files(
|
input: files(
|
||||||
'gtk/help-overlay.blp',
|
'gtk/help-overlay.blp',
|
||||||
'ui/caps-row.blp',
|
'ui/caps-row.blp',
|
||||||
|
'ui/qr-row.blp',
|
||||||
'window.blp',
|
'window.blp',
|
||||||
),
|
),
|
||||||
output: '.',
|
output: '.',
|
||||||
|
|
|
@ -65,3 +65,15 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-list {
|
||||||
|
background: none;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-list > row {
|
||||||
|
margin: 6px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: alpha(var(--view-fg-color), 0.1);
|
||||||
|
}
|
||||||
|
|
40
src/ui/qr-row.blp
Normal file
40
src/ui/qr-row.blp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $EyeNekoUiQRRow: Box {
|
||||||
|
styles [
|
||||||
|
"qr-row",
|
||||||
|
]
|
||||||
|
|
||||||
|
spacing: 12;
|
||||||
|
halign: fill;
|
||||||
|
hexpand: true;
|
||||||
|
|
||||||
|
Label data {
|
||||||
|
styles [
|
||||||
|
"qr-data",
|
||||||
|
]
|
||||||
|
|
||||||
|
use-markup: false;
|
||||||
|
wrap: true;
|
||||||
|
wrap-mode: word_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
Separator {
|
||||||
|
styles [
|
||||||
|
"spacer",
|
||||||
|
]
|
||||||
|
|
||||||
|
halign: fill;
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button copy {
|
||||||
|
valign: center;
|
||||||
|
|
||||||
|
styles [
|
||||||
|
"flat",
|
||||||
|
]
|
||||||
|
|
||||||
|
icon-name: "edit-copy-symbolic";
|
||||||
|
}
|
||||||
|
}
|
17
src/ui/qr-row.vala
Normal file
17
src/ui/qr-row.vala
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[GtkTemplate(ui = "/io/gitlab/nekocwd/eyeneko/ui/qr-row.ui")]
|
||||||
|
public class EyeNeko.Ui.QRRow : Gtk.Box {
|
||||||
|
[GtkChild]
|
||||||
|
private unowned Gtk.Label data;
|
||||||
|
[GtkChild]
|
||||||
|
private unowned Gtk.Button copy;
|
||||||
|
|
||||||
|
public void set_qr(string qr) {
|
||||||
|
data.label = qr;
|
||||||
|
}
|
||||||
|
|
||||||
|
construct {
|
||||||
|
copy.clicked.connect(() => {
|
||||||
|
data.get_clipboard().set_text(data.label);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -135,6 +135,39 @@ Adw.ToolbarView toolbar {
|
||||||
// content: TODO :)
|
// content: TODO :)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Adw.Dialog qr_dialog {
|
||||||
|
follows-content-size: true;
|
||||||
|
title: _("Scaned QRs");
|
||||||
|
|
||||||
|
Adw.ToolbarView {
|
||||||
|
styles [
|
||||||
|
"flat",
|
||||||
|
]
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {}
|
||||||
|
|
||||||
|
content: ScrolledWindow {
|
||||||
|
propagate-natural-height: true;
|
||||||
|
propagate-natural-width: true;
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
styles [
|
||||||
|
"qr-list",
|
||||||
|
]
|
||||||
|
|
||||||
|
show-separators: true;
|
||||||
|
|
||||||
|
factory: SignalListItemFactory qr_factory {};
|
||||||
|
|
||||||
|
model: NoSelection {
|
||||||
|
model: StringList qr_list {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
menu primary_menu {
|
menu primary_menu {
|
||||||
section {
|
section {
|
||||||
item {
|
item {
|
||||||
|
|
|
@ -34,7 +34,12 @@ public class EyeNeko.Window : Adw.ApplicationWindow {
|
||||||
private unowned Gtk.Button capture_btn;
|
private unowned Gtk.Button capture_btn;
|
||||||
[GtkChild]
|
[GtkChild]
|
||||||
private unowned Adw.ToggleGroup camera_mode;
|
private unowned Adw.ToggleGroup camera_mode;
|
||||||
|
[GtkChild]
|
||||||
|
private unowned Gtk.SignalListItemFactory qr_factory;
|
||||||
|
[GtkChild]
|
||||||
|
private unowned Gtk.StringList qr_list;
|
||||||
|
[GtkChild]
|
||||||
|
private unowned Adw.Dialog qr_dialog;
|
||||||
|
|
||||||
public string camera_path { get; set; default = "Unknown"; }
|
public string camera_path { get; set; default = "Unknown"; }
|
||||||
public string current_caps { get; set; default = "Unknown"; }
|
public string current_caps { get; set; default = "Unknown"; }
|
||||||
|
@ -103,32 +108,58 @@ public class EyeNeko.Window : Adw.ApplicationWindow {
|
||||||
video_caps_btn.set_popover (popover);
|
video_caps_btn.set_popover (popover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setup_qr_scaner () {
|
||||||
|
qr_factory.setup.connect ((mdl) => {
|
||||||
|
var item = (Gtk.ListItem) mdl;
|
||||||
|
item.child = new QRRow ();
|
||||||
|
});
|
||||||
|
qr_factory.bind.connect ((mdl) => {
|
||||||
|
var item = (Gtk.ListItem) mdl;
|
||||||
|
var row = (QRRow) item.child;
|
||||||
|
var data = (Gtk.StringObject) item.item;
|
||||||
|
row.set_qr (data.string);
|
||||||
|
});
|
||||||
|
Gstreamer.instance.qr_scaner.new_qr.connect ((qr) => {
|
||||||
|
qr_list.append (qr);
|
||||||
|
qr_dialog.present (this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public Window (Gtk.Application app) {
|
public Window (Gtk.Application app) {
|
||||||
Object (application: app);
|
Object (application: app);
|
||||||
overlay.add_overlay (toolbar);
|
overlay.add_overlay (toolbar);
|
||||||
|
|
||||||
Gstreamer.instance.bind_property ("viewfinder-paintable", viewfinder, "paintable", BindingFlags.SYNC_CREATE);
|
Gstreamer.instance.bind_property ("viewfinder-paintable", viewfinder, "paintable", BindingFlags.SYNC_CREATE);
|
||||||
capture_btn.clicked.connect (() => {
|
capture_btn.clicked.connect (() => {
|
||||||
if (Gstreamer.instance.camera_mode == Gstreamer.CameraMode.VIDEO && !Gstreamer.instance.ready) {
|
switch (Gstreamer.instance.camera_mode) {
|
||||||
Gstreamer.instance.stop_capture ();
|
case Gstreamer.CameraMode.QR:
|
||||||
} else {
|
qr_dialog.present (this);
|
||||||
Gstreamer.instance.start_capture ();
|
break;
|
||||||
|
case Gstreamer.CameraMode.VIDEO:
|
||||||
|
if (Gstreamer.instance.ready)
|
||||||
|
Gstreamer.instance.start_capture ();
|
||||||
|
else
|
||||||
|
Gstreamer.instance.stop_capture ();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Gstreamer.instance.start_capture ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setup_video_source_changer ();
|
||||||
|
setup_caps_changer ();
|
||||||
|
setup_qr_scaner ();
|
||||||
|
|
||||||
|
close_request.connect (() => {
|
||||||
|
Gstreamer.instance.start_stream_from (null);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
camera_mode.bind_property ("active-name", Gstreamer.instance, "camera-mode", BindingFlags.SYNC_CREATE, (b, s, ref d) => {
|
camera_mode.bind_property ("active-name", Gstreamer.instance, "camera-mode", BindingFlags.SYNC_CREATE, (b, s, ref d) => {
|
||||||
d = Gstreamer.CameraMode.parse (s.get_string ());
|
d = Gstreamer.CameraMode.parse (s.get_string ());
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
camera_mode.active_name = Env.get_variable_or ("CAM_M", "photo");
|
camera_mode.active_name = Env.get_variable_or ("CAM_M", "photo");
|
||||||
|
|
||||||
setup_video_source_changer ();
|
|
||||||
setup_caps_changer ();
|
|
||||||
close_request.connect (() => {
|
|
||||||
Gstreamer.instance.start_stream_from (null);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
Gstreamer.instance.qr_scaner.new_qr.connect ((qr) => message ("QR scaned %s", qr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue