package diskdrake::smbnfs_gtk; # $Id$ use diagnostics; use strict; use any; use fs; use diskdrake::interactive; use common; use interactive; use network::smb; use network::nfs; use my_gtk qw(:helpers :wrappers :ask); my ($all_hds, $in, $current_entry); sub main { ($in, $all_hds, my $type) = @_; my ($check, $create) = $type eq 'smb' ? (\&network::smb::check, \&smb_create) : (\&network::nfs::check, \&nfs_create); { local $my_gtk::pop_it = 1; $check->($in) or return; } my $w = my_gtk->new('DiskDrake'); $create->($w->{window}); $w->{rwindow}->set_default_size(400, 300) if $w->{rwindow}->can('set_default_size'); $w->{window}->show_all; $w->main; } ################################################################################ # nfs/smb: helpers ################################################################################ sub try { my ($kind, $name, @args) = @_; my $f = $diskdrake::interactive::{$name} or die "unknown function $name"; try_($kind, $name, \&{$f}, @args); } sub try_ { my ($kind, $name, $f, @args) = @_; eval { $f->($in, @args, $all_hds); }; if (my $err = $@) { $in->ask_warn(_("Error"), formatError($err)); } update($kind); Gtk->main_quit if $name eq 'Done'; } sub raw_hd_options { my ($in, $raw_hd) = @_; diskdrake::interactive::Options($in, {}, $raw_hd); } sub raw_hd_mount_point { my ($in, $raw_hd) = @_; diskdrake::interactive::Mount_point_raw_hd($in, $raw_hd, $all_hds); } sub per_entry_info_box { my ($box, $kind, $entry) = @_; $_->widget->destroy foreach $box->children; my $info; if ($entry) { $info = diskdrake::interactive::format_raw_hd_info($entry); } gtkpack($box, gtkadd(new Gtk::Frame(_("Details")), gtkset_justify(new Gtk::Label($info), 'left'))); } sub per_entry_action_box { my ($box, $kind, $entry) = @_; $_->widget->destroy foreach $box->children; my @buttons; push @buttons, map { my $s = $_; gtksignal_connect(new Gtk::Button(translate($s)), clicked => sub { try($kind, $s, {}, $entry) }); } (if_($entry->{isMounted}, __("Unmount")), if_($entry->{mntpoint} && !$entry->{isMounted}, __("Mount"))) if $entry; my @l = ( if_($entry, __("Mount point") => \&raw_hd_mount_point), if_($entry && $entry->{mntpoint}, __("Options") => \&raw_hd_options), __("Export") => sub { any::fileshare_config($in, $kind->{type}) }, __("Done") => \&done, ); push @buttons, map { my ($txt, $f) = @$_; gtksignal_connect(new Gtk::Button(translate($txt)), clicked => sub { try_($kind, $txt, $f, $entry) }); } group_by2(@l); gtkadd($box, gtkpack(new Gtk::HBox(0,0), @buttons)); } sub done { my ($in) = @_; diskdrake::interactive::Done($in, $all_hds); } sub update { my ($kind) = @_; per_entry_action_box($kind->{action_box}, $kind, $current_entry); per_entry_info_box($kind->{info_box}, $kind, $current_entry); } sub import_ctree { my ($kind, $default_imports, $find_servers, $find_exports, $create) = @_; my (%name2server, %wservers, %name2export, $inside); my $tree = Gtk::CTree->new(1, 0); $tree->set_column_auto_resize(0, 1); $tree->set_selection_mode('browse'); $tree->set_row_height($tree->style->font->ascent + $tree->style->font->descent + 1); my $add_server = sub { my ($server) = @_; my $name = $server->{name} || $server->{ip}; $name2server{$name} = $server; $wservers{$name} ||= $tree->insert_node(undef, undef, [$name], 5, (undef) x 4, 0, 0); $wservers{$name} }; my $add_exports = sub { my ($node) = @_; $tree->expand($node); my $name = first $tree->node_get_pixtext($node, 0); foreach ($find_exports->($name2server{$name})) { my $name = $_->{name} . ($_->{comment} ? " ($_->{comment})" : ''); $name2export{$name} = $_; $tree->insert_node($node, undef, [$name], 5, (undef) x 4, 1, 0); } }; my $click_here = $tree->insert_node(undef, undef, [_("click here")], 5, (undef) x 4, 0, 0); foreach (@$default_imports) { my $node = $add_server->({ name => $_ }); $add_exports->($node); } $tree->signal_connect(tree_select_row => sub { my $curr = $_[1]; $inside and return; $inside = 1; if ($curr->row->is_leaf) { my ($export) = $tree->node_get_pixtext($curr, 0); $export =~ s/ \(.*?\)$//; my ($server) = $tree->node_get_pixtext($curr->row->parent, 0); my $entry = $create->($server, $export); if (my ($e) = grep { $entry->{device} eq $_->{device} } @{$kind->{val}}) { $entry = $e; } else { push @{$kind->{val}}, $entry; } $current_entry = $entry; } else { if (!$curr->row->children) { gtkset_mousecursor_wait($tree->window); my_gtk::flush(); $tree->freeze; if ($curr == $click_here) { $add_server->($_) foreach sort { $a->{name} cmp $b->{name} } $find_servers->(); $tree->remove_node($click_here); } else { $add_exports->($curr); } $tree->thaw; gtkset_mousecursor_normal($tree->window); } $current_entry = undef; } update($kind); $inside = 0; }); $tree; } sub add_smbnfs { my ($widget, $kind, $find_servers, $find_exports, $create, $default_imports) = @_; die if $kind->{main_box}; $kind->{display_box} = createScrolledWindow(import_ctree($kind, $default_imports, $find_servers, $find_exports, $create)); $kind->{action_box} = new Gtk::HBox(0,0); $kind->{info_box} = new Gtk::VBox(0,0); $kind->{main_box} = gtkpack_(new Gtk::VBox(0,7), 1, gtkpack(new Gtk::HBox(0,7), gtkset_usize($kind->{display_box}, 200, 0), $kind->{info_box}), 0, $kind->{action_box}, ); $widget->add($kind->{main_box}); $current_entry = undef; update($kind); $kind; } ################################################################################ # nfs: helpers ################################################################################ sub nfs2kind { my ($l) = @_; { type => 'nfs', name => 'NFS', val => $l, no_auto => 1 }; } sub nfs_create { my ($widget) = @_; my $create = sub { my ($server, $export) = @_; my $nfs = { device => "$server:$export", type => 'nfs' }; fs::set_default_options($nfs); $nfs; }; my $servers = [ uniq(map { $_->{device} =~ m|(.*?):| } @{$all_hds->{nfss}}) ]; add_smbnfs($widget, nfs2kind($all_hds->{nfss}), \&network::nfs::find_servers, \&network::nfs::find_exports, $create, $servers); } ################################################################################ # smb: helpers ################################################################################ sub smb2kind { my ($l) = @_; { type => 'smb', name => 'Samba', val => $l, no_auto => 1 }; } sub smb_create { my ($widget) = @_; my $create = sub { my ($server, $export) = @_; my $smb = { device => "//$server/$export", type => 'smbfs', options => 'username=%' }; fs::set_default_options($smb); $smb; }; my $servers = [ uniq(map { $_->{device} =~ m|//(.*?)/| } @{$all_hds->{smbs}}) ]; add_smbnfs($widget, smb2kind($all_hds->{smbs}), \&network::smb::find_servers, \&network::smb::find_exports, $create, $servers); } 1;