Select printer feature added.
This commit is contained in:
parent
4bd58e1763
commit
abed9853f9
|
@ -23,6 +23,10 @@ has port => (
|
||||||
required => 1,
|
required => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
has name => (
|
||||||
|
is => 'ro',
|
||||||
|
);
|
||||||
|
|
||||||
has _guts_device => ( is => 'rw' );
|
has _guts_device => ( is => 'rw' );
|
||||||
|
|
||||||
has _tempdir => ( is => 'rw', );
|
has _tempdir => ( is => 'rw', );
|
||||||
|
@ -95,6 +99,9 @@ sub serialize($self) {
|
||||||
my $hash = {};
|
my $hash = {};
|
||||||
$hash->{address} = $self->address;
|
$hash->{address} = $self->address;
|
||||||
$hash->{port} = $self->port;
|
$hash->{port} = $self->port;
|
||||||
|
if (defined $self->name) {
|
||||||
|
$hash->{name} = $self->name;
|
||||||
|
}
|
||||||
$hash->{type} = 'bluetooth';
|
$hash->{type} = 'bluetooth';
|
||||||
return $hash;
|
return $hash;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,15 +28,30 @@ sub _build__guts_device($self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub image( $self, $image ) {
|
sub image( $self, $image ) {
|
||||||
$self->_guts_device->printer->image($image);
|
eval {
|
||||||
|
$self->_guts_device->printer->image($image);
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
die 'Unable to write to file does ' . $self->output_file . " exist?, error: $@.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub lf($self) {
|
sub lf($self) {
|
||||||
$self->_guts_device->printer->lf;
|
eval {
|
||||||
|
$self->_guts_device->printer->lf;
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
die 'Unable to write to file does ' . $self->output_file . " exist?, error: $@.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print($self) {
|
sub print($self) {
|
||||||
$self->_guts_device->printer->print;
|
eval {
|
||||||
|
$self->_guts_device->printer->print;
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
die 'Unable to write to file, does ' . $self->output_file . " exist?, error: $@.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub serialize($self) {
|
sub serialize($self) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ use Capture::Tiny qw/capture/;
|
||||||
use Exd::Printer;
|
use Exd::Printer;
|
||||||
use Exd::DeviceToBluetooth;
|
use Exd::DeviceToBluetooth;
|
||||||
use Exd::DeviceToImage;
|
use Exd::DeviceToImage;
|
||||||
|
use Exd::Gui::PrinterConfigure;
|
||||||
|
|
||||||
use JSON;
|
use JSON;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ Glib::Object::Introspection->setup(
|
||||||
|
|
||||||
has _app => ( is => 'rw', );
|
has _app => ( is => 'rw', );
|
||||||
|
|
||||||
has _win => ( is => 'rw', );
|
has window => ( is => 'rw', );
|
||||||
has _scroll_log_upper => ( is => 'rw', );
|
has _scroll_log_upper => ( is => 'rw', );
|
||||||
|
|
||||||
has _execute_log => ( is => 'rw', );
|
has _execute_log => ( is => 'rw', );
|
||||||
|
@ -59,6 +60,7 @@ has _read_from_script => ( is => 'rw' );
|
||||||
has _read_from_parent => ( is => 'rw' );
|
has _read_from_parent => ( is => 'rw' );
|
||||||
has _write_to_parent => ( is => 'rw' );
|
has _write_to_parent => ( is => 'rw' );
|
||||||
has _write_to_script => ( is => 'rw' );
|
has _write_to_script => ( is => 'rw' );
|
||||||
|
has device => (is => 'rw');
|
||||||
|
|
||||||
sub _tempdir_previews($self) {
|
sub _tempdir_previews($self) {
|
||||||
if ( !defined $self->_tempdir_previews_guts ) {
|
if ( !defined $self->_tempdir_previews_guts ) {
|
||||||
|
@ -106,10 +108,8 @@ sub _run_script( $self, $device = undef, $verbose = 1 ) {
|
||||||
my $end_iter = $buffer->get_end_iter;
|
my $end_iter = $buffer->get_end_iter;
|
||||||
my $script = $buffer->get_text( $begin_iter, $end_iter, 0 );
|
my $script = $buffer->get_text( $begin_iter, $end_iter, 0 );
|
||||||
if ( !defined $device ) {
|
if ( !defined $device ) {
|
||||||
$device = Exd::DeviceToBluetooth->new(
|
$self->add_to_log('You have to select a printer.');
|
||||||
address => '5A:4A:AE:8C:E9:D2',
|
return;
|
||||||
port => 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
local $| = 1;
|
local $| = 1;
|
||||||
my $fh = $self->_write_to_script;
|
my $fh = $self->_write_to_script;
|
||||||
|
@ -146,7 +146,7 @@ sub _daemon_script_runner($self) {
|
||||||
my $data = JSON::from_json($line);
|
my $data = JSON::from_json($line);
|
||||||
my ( $script, $device, $verbose ) =
|
my ( $script, $device, $verbose ) =
|
||||||
$data->@{ 'script', 'device', 'verbose' };
|
$data->@{ 'script', 'device', 'verbose' };
|
||||||
$device = $self->_device_hash_to_object($device);
|
$device = $self->device_hash_to_object($device);
|
||||||
if ( $last_pid
|
if ( $last_pid
|
||||||
&& $last_device->isa('Exd::DeviceToImage')
|
&& $last_device->isa('Exd::DeviceToImage')
|
||||||
&& !$verbose )
|
&& !$verbose )
|
||||||
|
@ -173,7 +173,7 @@ sub _daemon_script_runner($self) {
|
||||||
close $write_to_parent;
|
close $write_to_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _device_hash_to_object( $self, $device_hash ) {
|
sub device_hash_to_object( $self, $device_hash ) {
|
||||||
my $type = delete $device_hash->{type};
|
my $type = delete $device_hash->{type};
|
||||||
my %dispatch_table = (
|
my %dispatch_table = (
|
||||||
image => sub {
|
image => sub {
|
||||||
|
@ -225,13 +225,8 @@ sub _on_run_script( $self, $script, $device, $write_to_parent, $verbose = 1 ) {
|
||||||
sub _monitor_run($self) {
|
sub _monitor_run($self) {
|
||||||
my @fhs = $self->_select->can_read(0);
|
my @fhs = $self->_select->can_read(0);
|
||||||
for my $fh (@fhs) {
|
for my $fh (@fhs) {
|
||||||
my $execute_log = $self->_execute_log;
|
|
||||||
my $buffer = $execute_log->get_buffer;
|
|
||||||
my $begin_iter = $buffer->get_iter_at_offset(0);
|
|
||||||
my $end_iter = $buffer->get_end_iter;
|
|
||||||
|
|
||||||
my $text = '';
|
|
||||||
$fh->blocking(0);
|
$fh->blocking(0);
|
||||||
|
my $text = '';
|
||||||
while (my $line = <$fh>) {
|
while (my $line = <$fh>) {
|
||||||
if (!defined $line) {
|
if (!defined $line) {
|
||||||
next;
|
next;
|
||||||
|
@ -239,10 +234,18 @@ sub _monitor_run($self) {
|
||||||
$text .= $line;
|
$text .= $line;
|
||||||
}
|
}
|
||||||
return if $text =~ /^\s*$/;
|
return if $text =~ /^\s*$/;
|
||||||
$buffer->insert( $end_iter, $text, -1 );
|
$self->add_to_log($text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub add_to_log($self, $text) {
|
||||||
|
my $execute_log = $self->_execute_log;
|
||||||
|
my $buffer = $execute_log->get_buffer;
|
||||||
|
my $end_iter = $buffer->get_end_iter;
|
||||||
|
|
||||||
|
$buffer->insert( $end_iter, $text, -1 );
|
||||||
|
}
|
||||||
|
|
||||||
sub _build__select($self) {
|
sub _build__select($self) {
|
||||||
return IO::Select->new;
|
return IO::Select->new;
|
||||||
}
|
}
|
||||||
|
@ -333,11 +336,18 @@ sub _activate($self) {
|
||||||
);
|
);
|
||||||
my $app = $self->_app;
|
my $app = $self->_app;
|
||||||
my $win = Gtk4::ApplicationWindow->new($app);
|
my $win = Gtk4::ApplicationWindow->new($app);
|
||||||
$self->_win($win);
|
$self->window($win);
|
||||||
my $box_vertical = Gtk4::Box->new( 'vertical', 10 );
|
my $box_vertical = Gtk4::Box->new( 'vertical', 10 );
|
||||||
my $execute_log = Gtk4::TextView->new;
|
my $execute_log = Gtk4::TextView->new;
|
||||||
my $run_button = Gtk4::Button->new_with_label('Run');
|
my $run_button = Gtk4::Button->new_with_label('Run');
|
||||||
my $preview_button = Gtk4::Button->new_with_label('Preview');
|
my $preview_button = Gtk4::Button->new_with_label('Preview');
|
||||||
|
my $select_printer = Gtk4::Button->new_with_label('Select Printer');
|
||||||
|
$select_printer->signal_connect(
|
||||||
|
'clicked',
|
||||||
|
sub {
|
||||||
|
Exd::Gui::PrinterConfigure->new(app => $self)->start;
|
||||||
|
}
|
||||||
|
);
|
||||||
$preview_button->signal_connect(
|
$preview_button->signal_connect(
|
||||||
'clicked',
|
'clicked',
|
||||||
sub {
|
sub {
|
||||||
|
@ -348,7 +358,7 @@ sub _activate($self) {
|
||||||
|
|
||||||
$run_button->signal_connect(
|
$run_button->signal_connect(
|
||||||
clicked => sub {
|
clicked => sub {
|
||||||
$self->_run_script( undef, 1 );
|
$self->_run_script( $self->device, 1 );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -366,6 +376,7 @@ sub _activate($self) {
|
||||||
my $box_buttons = Gtk4::Box->new( 'horizontal', 10 );
|
my $box_buttons = Gtk4::Box->new( 'horizontal', 10 );
|
||||||
$box_buttons->append($run_button);
|
$box_buttons->append($run_button);
|
||||||
$box_buttons->append($preview_button);
|
$box_buttons->append($preview_button);
|
||||||
|
$box_buttons->append($select_printer);
|
||||||
$self->_populate_editor_and_preview($box_vertical);
|
$self->_populate_editor_and_preview($box_vertical);
|
||||||
$box_vertical->append($box_buttons);
|
$box_vertical->append($box_buttons);
|
||||||
my $execute_log_window = Gtk4::ScrolledWindow->new;
|
my $execute_log_window = Gtk4::ScrolledWindow->new;
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
package Exd::Gui::PrinterConfigure;
|
||||||
|
|
||||||
|
use v5.40.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Moo;
|
||||||
|
use Glib;
|
||||||
|
use Glib::IO;
|
||||||
|
use Glib::Object::Introspection;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
use Net::Bluetooth qw//;
|
||||||
|
|
||||||
|
has app => (is => 'ro', required => 1);
|
||||||
|
has _pid_daemon => (is => 'rw');
|
||||||
|
has _read_from_daemon => (is => 'rw');
|
||||||
|
has _write_to_app => (is => 'rw');
|
||||||
|
has _select => ( is => 'lazy', );
|
||||||
|
has _window => ( is => 'rw' );
|
||||||
|
has _bluetooth_printers => ( is => 'rw', default => sub { [] } );
|
||||||
|
has _usb_printers => ( is => 'rw', default => sub { [] });
|
||||||
|
|
||||||
|
my $cache;
|
||||||
|
|
||||||
|
sub _build__select($self) {
|
||||||
|
return IO::Select->new;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _read_bluetooth_printers($self) {
|
||||||
|
my @fhs = $self->_select->can_read(0);
|
||||||
|
if (scalar @fhs == 0) {
|
||||||
|
}
|
||||||
|
for my $fh (@fhs) {
|
||||||
|
$fh->blocking(0);
|
||||||
|
while (my $line = <$fh>) {
|
||||||
|
my @return = map {$self->app->device_hash_to_object($_)} @{JSON::from_json($line)};
|
||||||
|
$self->_bluetooth_printers(\@return);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _usb_printer_print_to_box($self, $device, $box) {
|
||||||
|
my $window = $self->_window;
|
||||||
|
my $button = Gtk4::Button->new_with_label($device->output_file);
|
||||||
|
$button->signal_connect('clicked', sub {
|
||||||
|
$self->app->device($device);
|
||||||
|
$window->close;
|
||||||
|
});
|
||||||
|
$box->append($button);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _bluetoth_printer_print_to_box($self, $device, $box) {
|
||||||
|
my $window = $self->_window;
|
||||||
|
my $button = Gtk4::Button->new_with_label($device->name.':'.$device->address);
|
||||||
|
$button->signal_connect('clicked', sub {
|
||||||
|
$self->app->device($device);
|
||||||
|
$window->close;
|
||||||
|
});
|
||||||
|
$box->append($button);
|
||||||
|
}
|
||||||
|
sub _read_usb_printers($self) {
|
||||||
|
my @printers = map { Exd::DeviceToRawFile->new(output_file => $_) } glob '/dev/usb/lp*';
|
||||||
|
$self->_usb_printers(\@printers);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start($self) {
|
||||||
|
$self->_start_daemon_bluetooth_search;
|
||||||
|
my $parent_window = $self->app->window;
|
||||||
|
my $window = Gtk4::Window->new;
|
||||||
|
$self->_window($window);
|
||||||
|
$window->set_default_size( 600, 600 );
|
||||||
|
$window->signal_connect('close-request', sub{
|
||||||
|
$self->_on_close;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
$window->set_title('Printer Selection');
|
||||||
|
$window->set_child(Gtk4::Label->new('Searching for printers...'));
|
||||||
|
$self->_select->add($self->_read_from_daemon);
|
||||||
|
Glib::Timeout->add(1000, sub {
|
||||||
|
eval {
|
||||||
|
$self->_read_usb_printers;
|
||||||
|
$self->_read_bluetooth_printers;
|
||||||
|
$self->_update_box;
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
$window->present;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _update_box($self) {
|
||||||
|
my $window = $self->_window;
|
||||||
|
my $box = Gtk4::Box->new( 'vertical', 10 );
|
||||||
|
for my $device ($self->_bluetooth_printers->@*) {
|
||||||
|
$self->_bluetoth_printer_print_to_box($device, $box);
|
||||||
|
}
|
||||||
|
for my $device ($self->_usb_printers->@*) {
|
||||||
|
$self->_usb_printer_print_to_box($device, $box);
|
||||||
|
}
|
||||||
|
$window->set_child($box);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _start_daemon_bluetooth_search($self) {
|
||||||
|
my ($read, $write);
|
||||||
|
pipe $read, $write;
|
||||||
|
$self->_read_from_daemon($read);
|
||||||
|
$self->_write_to_app($write);
|
||||||
|
my $pid = fork;
|
||||||
|
if (!$pid) {
|
||||||
|
close $read;
|
||||||
|
while (1) {
|
||||||
|
$self->_daemon_bluetooth_search_iteration;
|
||||||
|
}
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
close $write;
|
||||||
|
$self->_pid_daemon($pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _daemon_bluetooth_search_iteration($self) {
|
||||||
|
say 'Listing bluetooth devices';
|
||||||
|
my $devices = Net::Bluetooth::get_remote_devices;
|
||||||
|
my @return;
|
||||||
|
for my $address (keys %$devices) {
|
||||||
|
say "Detected $devices->{$address}:$address, looking if it supports Serial Port...";
|
||||||
|
my $search = Net::Bluetooth::sdp_search($address, "1101", "");
|
||||||
|
if (defined $search && defined $search->{RFCOMM}) {
|
||||||
|
say "$devices->{$address}:$address supports Serial Port and may be a printer, the port is: $search->{RFCOMM}";
|
||||||
|
push @return, Exd::DeviceToBluetooth->new(name => $devices->{$address}, address => $address, port => $search->{RFCOMM});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@return = map { $_->serialize } sort { $a->name cmp $b->name } @return;
|
||||||
|
$self->_write_to_app->print(JSON::to_json(\@return));
|
||||||
|
$self->_write_to_app->flush;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _on_close($self) {
|
||||||
|
kill 'TERM', $self->_pid_daemon;
|
||||||
|
waitpid $self->_pid_daemon, 0;
|
||||||
|
say 'Finished printer select daemon';
|
||||||
|
}
|
||||||
|
1;
|
Loading…
Reference in New Issue