# List Handling
use strict;
use warnings;
our (%gui, %sensgrp, %osversion, %EAbled, %EAudioDriverType, %EAudioControllerType, %hostspec, %ENetworkAdapterType, %ETruth);

sub fill_list_guest() {
    &addrow_log("Retrieving the list of guests from $endpoint...");
    &busy_window($gui{windowMain}, 0, 'watch');
    &clr_list_guest();
    my %guestlist;
    my @IMachine = IVirtualBox_getMachines($gui{websn});
    $guestlist{$_} = IMachine_getName($_) foreach (@IMachine);

    foreach my $machine (sort { lc($guestlist{$a}) cmp lc($guestlist{$b}) } (keys %guestlist)) {
        my $prettygname = $guestlist{$machine};
        my $status = IMachine_getAccessible($machine);
        my $ISnapshot = IMachine_getCurrentSnapshot($machine);
        $prettygname .=  ' (' . ISnapshot_getName($ISnapshot) . ')' if ($ISnapshot);

        if ($status eq 'false') {
            my $IVirtualBoxErrorInfo = IMachine_getAccessError($machine);
            $status = IVirtualBoxErrorInfo_getText($IVirtualBoxErrorInfo);
        }
        else { $status = IMachine_getState($machine); }

        my $osid = IMachine_getOSTypeId($machine);
        $prettygname .= "\n   $status";
        my $iter = $gui{liststoreGuest}->append;
        $gui{liststoreGuest}->set($iter,
                                  0, $guestlist{$machine},
                                  1, $osversion{$osid}{description},
                                  2, $machine,
                                  3, $status,
                                  4, $osid,
                                  5, IMachine_getId($machine),
                                  6, $osversion{$osid}{icon},
                                  7, $prettygname);
    }

    &addrow_log("List of guests from $endpoint retrieved.");
    &busy_window($gui{windowMain}, 1);
}

sub fill_list_details() {
    &busy_window($gui{windowMain}, 0, 'watch');
    my %weight = (bold => 800,
                  norm => 400);
    &clr_list_details();
    my %guest = &getsel_list_guest();
    &addrow_log("Retrieving details of $guest{Name}...");
    my $IVRDEServer = IMachine_getVRDEServer($guest{IMachine});
    my @IStorageController = IMachine_getStorageControllers($guest{IMachine});
    my $IAudioAdapter = IMachine_getAudioAdapter($guest{IMachine});
    my $IUSBController = IMachine_getUSBController($guest{IMachine});
    &addrow_list_details(0, 'GENERAL', 2, $weight{bold});
    &addrow_list_details(0, 'Name:', 1, $guest{Name}, 2, $weight{norm});
    &addrow_list_details(0, 'OS Type:', 1, $guest{Os}, 2, $weight{norm});
    &addrow_list_details(0, 'SYSTEM', 2, $weight{bold});
    &addrow_list_details(0, 'Firmware:', 1, IMachine_getFirmwareType($guest{IMachine}), 2, $weight{norm});
    &addrow_list_details(0, 'Base Memory:', 1, IMachine_getMemorySize($guest{IMachine}) . ' MiB', 2, $weight{norm});
    &addrow_list_details(0, 'Processor(s):', 1, IMachine_getCPUCount($guest{IMachine}), 2, $weight{norm});

    foreach (1..4) {
        my $bootdev = IMachine_getBootOrder($guest{IMachine}, $_);
        &addrow_list_details(0, "Boot Device $_:", 1, $bootdev, 2, $weight{norm}) if ($bootdev ne 'Null');
    }

    &addrow_list_details(0, 'VT-x/AMV-V:', 1, $EAbled{IMachine_getHWVirtExProperty($guest{IMachine}, 'Enabled')}, 2, $weight{norm});
    &addrow_list_details(0, 'VT-x VPID:', 1, $EAbled{IMachine_getHWVirtExProperty($guest{IMachine}, 'VPID')}, 2, $weight{norm});
    &addrow_list_details(0, 'Nested Paging:', 1, $EAbled{IMachine_getHWVirtExProperty($guest{IMachine}, 'NestedPaging')}, 2, $weight{norm});
    &addrow_list_details(0, 'DISPLAY', 2, $weight{bold});
    &addrow_list_details(0, 'Video Memory:', 1, IMachine_getVRAMSize($guest{IMachine}) . ' MiB', 2, $weight{norm});
    &addrow_list_details(0, '3D Acceleration:', 1, $EAbled{IMachine_getAccelerate3DEnabled($guest{IMachine})}, 2, $weight{norm});
    &addrow_list_details(0, '2D Acceleration:', 1, $EAbled{IMachine_getAccelerate2DVideoEnabled($guest{IMachine})}, 2, $weight{norm});

    if (IVRDEServer_getEnabled($IVRDEServer) eq 'true') {
        &addrow_list_details(0, 'Remote Display Server:', 1, 'Enabled', 2, $weight{norm});
        &addrow_list_details(0, 'Remote Display Port(s):', 1, IVRDEServer_getVRDEProperty($IVRDEServer, 'TCP/Ports'), 2, $weight{norm});
    }
    else { &addrow_list_details(0, 'Remote Display Server:', 1, 'Disabled', 2, $weight{norm}); }

    &addrow_list_details(0, 'STORAGE', 2, $weight{bold});

    foreach my $controller (@IStorageController) {
        my $controllername = IStorageController_getName($controller);
        &addrow_list_details(0, 'Controller:', 1, $controllername, 2, $weight{norm});
        my @IMediumAttachment = IMachine_getMediumAttachmentsOfController($guest{IMachine}, $controllername);
        foreach my $attachment (@IMediumAttachment) {
            if ($$attachment{medium}) {
                # Use the base medium for information purposes
                &addrow_list_details(0, "  Port $$attachment{port}:",
                                     1, "$$attachment{type}: " . IMedium_getName(IMedium_getBase($$attachment{medium})),
                                     2, $weight{norm});
            }
        }
    }

    &addrow_list_details(0, 'AUDIO', 2, $weight{bold});

    if (IAudioAdapter_getEnabled($IAudioAdapter) eq 'true') {
        &addrow_list_details(0, 'Host Driver:', 1, $EAudioDriverType{IAudioAdapter_getAudioDriver($IAudioAdapter)}{desc}, 2, $weight{norm});
        &addrow_list_details(0, 'Controller:', 1, $EAudioControllerType{IAudioAdapter_getAudioController($IAudioAdapter)}, 2, $weight{norm});
    }
    else { &addrow_list_details(0, 'Audio Disabled', 2, $weight{norm}); }

    &addrow_list_details(0, 'NETWORK', 2, $weight{bold});

    foreach (0..($hostspec{maxnet}-1)) {
        my $INetworkAdapter = IMachine_getNetworkAdapter($guest{IMachine}, $_);
        if (INetworkAdapter_getEnabled($INetworkAdapter) eq 'true') {
            &addrow_list_details(0, "Adapter $_:",
                                 1, $ENetworkAdapterType{INetworkAdapter_getAdapterType($INetworkAdapter)} . ', ' .
                                                         INetworkAdapter_getAttachmentType($INetworkAdapter),
                                 2, $weight{norm});
        }
    }

    &addrow_list_details(0, 'SERIAL PORTS', 2, $weight{bold});

    foreach (0..($hostspec{maxser}-1)) {
        my $ISerialPort = IMachine_getSerialPort($guest{IMachine}, $_);
        if (ISerialPort_getEnabled($ISerialPort) eq 'true') {
            &addrow_list_details(0, "Port #$_:",
                                     1, 'Enabled, ' . ISerialPort_getHostMode($ISerialPort) . ', ' .
                                                      ISerialPort_getPath($ISerialPort),
                                     2, $weight{norm});
        }
        else { &addrow_list_details(0, "Port #$_:", 1, 'Disabled', 2, $weight{norm}); }
    }

    &addrow_list_details(0, 'USB', 2, $weight{bold});

    if (IUSBController_getEnabled($IUSBController) eq 'true' ) {
        my @IUSBDeviceFilter = IUSBController_getDeviceFilters($IUSBController);
        my $active = 0;
        my $inactive = 0;
        foreach my $filter (@IUSBDeviceFilter) {
            if (IUSBDeviceFilter_getActive($filter) eq 'true') { $active++; }
            else { $inactive++; }
        }
        &addrow_list_details(0, 'Active Device Filters:', 1, $active, 2, $weight{norm});
        &addrow_list_details(0, 'Inactive Device Filters:', 1, $inactive, 2, $weight{norm});
    }
    else { &addrow_list_details(0, 'Disabled', 2, $weight{norm}); }

    my @sf = IMachine_getSharedFolders($guest{IMachine});
    &addrow_list_details(0, 'SHARED FOLDERS', 2, $weight{bold});
    &addrow_list_details(0, 'Shared Folders:', 1, scalar(@sf), 2, $weight{norm});
    &addrow_log("Details of $guest{Name} retrieved.");
    &busy_window($gui{windowMain}, 1);
}

sub fill_list_snapshots() {
    &busy_window($gui{windowMain}, 0, 'watch');
    &clr_list_snapshots();
    my %guest = &getsel_list_guest();
    my $ISnapshot_current = IMachine_getCurrentSnapshot($guest{IMachine});
    &addrow_log("Retrieving snapshot information for $guest{Name}...");

    if (IMachine_getSnapshotCount($guest{IMachine}) > 0) {
        my $ISnapshot = IMachine_findSnapshot($guest{IMachine}, undef); # get first snapshot
        &recurse_snapshot($ISnapshot, undef, $ISnapshot_current);
        $gui{treeviewSnapshots}->expand_all();
    }

    &addrow_log("Snapshot information for $guest{Name} retrieved.");
    &busy_window($gui{windowMain}, 1);
}

sub fill_list_remotefiles() {
    my ($location) = @_;
    $gui{liststoreRemoteFileChooser}->clear();
    IVFSExplorer_cd($gui{IVFSExplorer}, $location);
    IVFSExplorer_update($gui{IVFSExplorer});
    my @entries = IVFSExplorer_entryList($gui{IVFSExplorer});
    my $chop = (@entries / 4);
    my %files;
    unshift @entries, 'Dummy';

    foreach my $x (1..$chop) {
        $files{$entries[$x]}{type} = $entries[$x + $chop];
        $files{$entries[$x]}{size} = &bytesToX($entries[$x + ($chop * 2)]);
        $files{$entries[$x]}{mode} = sprintf("%o", $entries[$x + ($chop * 3)]);
    }

    my $iter = $gui{liststoreRemoteFileChooser}->append();
    $gui{liststoreRemoteFileChooser}->set($iter, 0, '(Parent)', 1, '..', 2, '', 3, '');

    foreach my $fname (sort { lc($a) cmp lc($b) } (keys %files)) {
        my $type = '';
        $type = '(Dir)' if ($files{$fname}{type} == 4);
        my $iter = $gui{liststoreRemoteFileChooser}->append();
        $gui{liststoreRemoteFileChooser}->set($iter, 0, $type, 1, $fname, 2, $files{$fname}{size}, 3, $files{$fname}{mode});
    }

    $gui{entryRemoteFileChooserLocation}->set_text(IVFSExplorer_getPath($gui{IVFSExplorer}));
}

sub fill_list_serverinfo() {
    $gui{liststoreServerInfo}->clear();
    &addrow_list_serverinfo(0, 'URL:', 1, $endpoint);
    &addrow_list_serverinfo(0, 'VirtualBox Version:', 1, $hostspec{vbver});
    &addrow_list_serverinfo(0, 'Build Revision:', 1, $hostspec{buildrev});
    &addrow_list_serverinfo(0, 'Package Type:', 1, $hostspec{pkgtype});
    &addrow_list_serverinfo(0, 'Global Settings File:', 1, $hostspec{settingsfile});
    &addrow_list_serverinfo(0, 'Machine Folder:', 1, $hostspec{machinedir});
    &addrow_list_serverinfo(0, 'Server Logical CPUs:', 1, $hostspec{maxhostcpuon});
    &addrow_list_serverinfo(0, 'Server CPU Type:', 1, $hostspec{cpudesc});
    &addrow_list_serverinfo(0, 'Server CPU Speed:', 1, "$hostspec{cpuspeed} Mhz (approx)");
    &addrow_list_serverinfo(0, 'Server Memory Size:', 1,  "$hostspec{memsize} MiB");
    &addrow_list_serverinfo(0, 'Server OS:', 1, $hostspec{os});
    &addrow_list_serverinfo(0, 'Server OS Version:', 1, $hostspec{osver});
    &addrow_list_serverinfo(0, 'Min Guest RAM:', 1, "$hostspec{minguestram} MiB");
    &addrow_list_serverinfo(0, 'Max Guest RAM:', 1, "$hostspec{maxguestram} MiB");
    &addrow_list_serverinfo(0, 'Min Guest Video RAM:', 1, "$hostspec{minguestvram} MiB");
    &addrow_list_serverinfo(0, 'Max Guest Video RAM:', 1, "$hostspec{maxguestvram} MiB");
    &addrow_list_serverinfo(0, 'Max Guest CPUs:', 1, $hostspec{maxguestcpu});
    &addrow_list_serverinfo(0, 'Max HD Image Size:', 1, &bytesToX($hostspec{maxhdsize}));
}

sub fill_list_vmmhd() {
    &busy_window($gui{dialogVMM}, 0, 'watch');
    $gui{entryVMMAttachedTo}->set_text(''); # Do whenever list is cleared
    $gui{entryVMMLocation}->set_text(''); # Do whenever list is cleared
    $gui{treestoreVMMHD}->clear();
    my %IMedium = &get_all_media('HardDisk');

    foreach my $hd (sort { lc($a) cmp lc($b) } (keys %IMedium)) {
        &recurse_media_snapshot($gui{treestoreVMMHD}, $IMedium{$hd}, undef, 'HardDisk');
    }

    &busy_window($gui{dialogVMM}, 1);
}

sub fill_list_vmmdvd() {
    &busy_window($gui{dialogVMM}, 0, 'watch');
    $gui{entryVMMAttachedTo}->set_text(''); # Do whenever list is cleared
    $gui{entryVMMLocation}->set_text(''); # Do whenever list is cleared
    $gui{treestoreVMMDVD}->clear();
    my %IMedium = &get_all_media('DVD');

    foreach my $dvd (sort { lc($a) cmp lc($b) } (keys %IMedium)) {
        &recurse_media_snapshot($gui{treestoreVMMDVD}, $IMedium{$dvd}, undef, 'DVD');
    }

    &busy_window($gui{dialogVMM}, 1);
}

sub fill_list_vmmfloppy() {
    &busy_window($gui{dialogVMM}, 0, 'watch');
    $gui{entryVMMAttachedTo}->set_text(''); # Do whenever list is cleared
    $gui{entryVMMLocation}->set_text(''); # Do whenever list is cleared
    $gui{treestoreVMMFloppy}->clear();
    my %IMedium = &get_all_media('Floppy');

    foreach my $floppy (sort { lc($a) cmp lc($b) } (keys %IMedium)) {
        &recurse_media_snapshot($gui{treestoreVMMFloppy}, $IMedium{$floppy}, undef, 'Floppy');
    }

    &busy_window($gui{dialogVMM}, 1);
}

sub fill_list_editshared() {
    my ($IMachine) = @_;
    &sensitive_off($gui{buttonEditSharedRemove}, $gui{buttonEditSharedEdit}); # Do whenever list is cleared
    $gui{liststoreEditShared}->clear();
    my @ISharedFolder = IMachine_getSharedFolders($IMachine);

    foreach my $share (@ISharedFolder) {
        my $access = 'Full';
        my $automount = 'No';
        my $tooltip = "$$share{name}: $$share{hostPath}";
        $access = 'Read-Only' if ($$share{writable} eq 'false');
        $automount = 'Yes' if ($$share{autoMount} eq 'true');
        $tooltip = $$share{lastAccessError} if ($$share{lastAccessError});
        $tooltip = 'Share is not accessible' if ($$share{accessible} eq 'false');
        my $iter = $gui{liststoreEditShared}->append;
        if ($$share{accessible} eq 'false') { $gui{liststoreEditShared}->set($iter, 0, $$share{name}, 1, $$share{hostPath}, 2, $access, 3, $automount, 4, $gui{pixbufstatuserror16}, 5, $tooltip); }
        else { $gui{liststoreEditShared}->set($iter, 0, $$share{name}, 1, $$share{hostPath}, 2, $access, 3, $automount, 5, $tooltip); }
    }
}

sub fill_list_editstorage() {
    my ($IMachine) = @_;
    &busy_window($gui{dialogEdit}, 0, 'watch');
    &sensitive_off(@{ $sensgrp{stor_unsel} }); # Do whenever list is cleared
    $gui{treestoreEditStor}->clear();
    my @IStorageController = IMachine_getStorageControllers($IMachine);

    foreach my $controller (@IStorageController) {
        my $cname = IStorageController_getName($controller);
        my $bus = IStorageController_getBus($controller);
        my $iter = $gui{treestoreEditStor}->append(undef);
        $gui{treestoreEditStor}->set($iter, 0, $cname, 1, $cname, 2, $bus . ' Controller', 3, $controller, 7, $cname);
        my @IMediumAttachment = IMachine_getMediumAttachmentsOfController($IMachine, $cname);

        foreach my $attachment (@IMediumAttachment) {
            my $citer = $gui{treestoreEditStor}->append($iter);

            if ($$attachment{medium}) {
                my $baseIMedium = IMedium_getBase($$attachment{medium});
                my $mname = IMedium_getName($baseIMedium); # Use the
                my $prettyname = $mname;
                if ($baseIMedium ne $$attachment{medium}) { $prettyname = "(*) $prettyname"; }
                $gui{treestoreEditStor}->set($citer, 0, $mname,
                                                     1, $cname,
                                                     2, $$attachment{type},
                                                     3, $$attachment{medium},
                                                     4, $$attachment{device},
                                                     5, $$attachment{port},
                                                     6, IMedium_getLocation($$attachment{medium}),
                                                     7, $prettyname);
            }
            else {
                $gui{treestoreEditStor}->set($citer, 0, '<empty>',
                                                     1, $cname,
                                                     2, $$attachment{type},
                                                     3, '<empty>',
                                                     4, $$attachment{device},
                                                     5, $$attachment{port},
                                                     6, '<empty>',
                                                     7, '<empty>');
            }
        }
    }

    $gui{treeviewEditStor}->expand_all();
    &busy_window($gui{dialogEdit}, 1);
}

sub fill_list_usbfilters() {
    my ($IUSBController) = @_;
    &busy_window($gui{dialogVMM}, 0, 'watch');
    &sensitive_off(@{ $sensgrp{usb_sel} }); # Do whenever list is cleared
    $gui{liststoreEditUSBFilter}->clear();
    my @IUSBDeviceFilters = IUSBController_getDeviceFilters($IUSBController);
    my $pos = 0;

    foreach my $filter (@IUSBDeviceFilters) {
        my $iter = $gui{liststoreEditUSBFilter}->append();
        $gui{liststoreEditUSBFilter}->set($iter,
                                      0, $ETruth{IUSBDeviceFilter_getActive($filter)},
                                      1, $filter,
                                      2, IUSBDeviceFilter_getName($filter),
                                      3, $pos);
        $pos++;
    }

    &busy_window($gui{dialogVMM}, 1);
}

sub fill_list_vbprefsnet() {
    &busy_window($gui{dialogVBPrefs}, 0, 'watch');
    &sensitive_off(@{ $sensgrp{vbprefsnet} }); # Do whenever list is cleared
    $gui{liststoreVBPrefsNet}->clear();
    my $IHost = IVirtualBox_getHost($gui{websn});
    my @IHostNetworkInterface = IHost_findHostNetworkInterfacesOfType($IHost, 'HostOnly');

    foreach my $if (@IHostNetworkInterface) {
        my $iter = $gui{liststoreVBPrefsNet}->append();
        $gui{liststoreVBPrefsNet}->set($iter,
                                       0, IHostNetworkInterface_getName($if),
                                       1, $if,
                                       2, IHostNetworkInterface_getId($if));
    }
    &busy_window($gui{dialogVBPrefs}, 1);
}

sub clr_list() { $_->clear() foreach (@_); }

sub clr_list_guest() {
    &sensitive_off(@{ $sensgrp{unselected} });
    $gui{liststoreGuest}->clear();
    &clr_list_details();
    &clr_list_snapshots();
    $gui{textbufferDescription}->set_text('');
}

sub clr_list_details() { $gui{liststoreDetails}->clear(); }

sub clr_list_snapshots() {
    &sensitive_off(@{ $sensgrp{snap} });
    $gui{treestoreSnapshots}->clear();
}

# Adds a message to message log and scrolls to bottom
sub addrow_log() {
    my ($msg) = @_;
    my $iter = $gui{liststoreLog}->append;
    $gui{liststoreLog}->set($iter, 0, $msg);
    $gui{treeviewLog}->scroll_to_cell($gui{treeviewLog}->get_model->get_path($iter));
}

sub addrow_list() {
    my $store = shift(@_);
    my $iter = $store->append();
    $store->set($iter, @_);
    return $iter;
}

sub addrow_list_details() {
    my $iter = $gui{liststoreDetails}->append;
    $gui{liststoreDetails}->set($iter, @_);
    return $iter;
}

sub addrow_list_serverinfo() {
    my $iter = $gui{liststoreServerInfo}->append;
    $gui{liststoreServerInfo}->set($iter, @_);
    return $iter;
}

sub getsel_combo() {
    my ($widget, $col) = @_;
    my $model = $widget->get_model();
    my $iter = $widget->get_active_iter();

    if (defined($col)) { return $model->get($iter, $col); }
    else { return $model->get($iter); }
}

sub getsel_list_guest() {
    return (IMachine => '') if (!$gui{treeviewGuest}->get_selection->get_selected()); # Return if nothing selected
    my @cols = ('Name', 'Os', 'IMachine', 'Status', 'Osid', 'Uuid', 'Icon', 'Prettyname');
    my $model = $gui{treeviewGuest}->get_model();
    my ($path) = $gui{treeviewGuest}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_remotefiles() {
    my @cols = ('Type', 'FileName', 'Size', 'Mode');
    my $model = $gui{treeviewRemoteFileChooser}->get_model();
    my ($path) = $gui{treeviewRemoteFileChooser}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_snapshots() {
    my @cols = ('Name', 'Date', 'ISnapshot');
    my $model = $gui{treeviewSnapshots}->get_model();
    my ($path) = $gui{treeviewSnapshots}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_vmmhd() {
    my @cols = ('Name', 'IMedium', 'Attached', 'Asize', 'Vsize', 'Accessible', 'Tooltip');
    my $model = $gui{treeviewVMMHD}->get_model();
    my ($path) = $gui{treeviewVMMHD}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_vmmdvd() {
    my @cols = ('Name', 'IMedium', 'Attached', 'Size', 'Accessible', 'Tooltip');
    my $model = $gui{treeviewVMMDVD}->get_model();
    my ($path) = $gui{treeviewVMMDVD}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_vmmfloppy() {
    my @cols = ('Name', 'IMedium', 'Attached', 'Size', 'Accessible', 'Tooltip');
    my $model = $gui{treeviewVMMFloppy}->get_model();
    my ($path) = $gui{treeviewVMMFloppy}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_editshared() {
    my @cols = ('Name', 'Folder', 'Access', 'Mount', 'Accessible', 'Tooltip');
    my $model = $gui{treeviewEditShared}->get_model();
    my ($path) = $gui{treeviewEditShared}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_editstorage() {
    my @cols = ('Name', 'Controllernameformedia', 'Type', 'IObject', 'Devnum', 'Port', 'Location', 'Prettyname');
    my $model = $gui{treeviewEditStor}->get_model();
    my ($path) = $gui{treeviewEditStor}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_usbfilters() {
    return (IUSBDeviceFilter => '') if (!$gui{treeviewEditUSBFilters}->get_selection->get_selected()); # Return if nothing selected
    my @cols = ('Enabled', 'IUSBDeviceFilter', 'Name', 'Position');
    my $model = $gui{treeviewEditUSBFilters}->get_model();
    my ($path) = $gui{treeviewEditUSBFilters}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub getsel_list_vbprefsnet() {
    my @cols = ('Name', 'IHostNetworkInterface', 'Uuid');
    my $model = $gui{treeviewVBPrefsNet}->get_model();
    my ($path) = $gui{treeviewVBPrefsNet}->get_cursor();
    return undef unless ($path);
    my $iter = $model->get_iter($path);
    my @row = $model->get($iter);
    my %hash;
    $hash{$_} = shift @row foreach (@cols);
    return %hash;
}

sub onsel_list_guest() {
    my %guest = &getsel_list_guest();
    &clr_list_details();
    &sensitive_off(@{ $sensgrp{unselected} });
    $gui{textbufferDescription}->set_text(IMachine_getDescription($guest{IMachine}));
    my $status = IMachine_getState($guest{IMachine});
    &fill_list_snapshots();

    if ($status eq 'Running' | $status eq 'Starting') { &sensitive_on(@{ $sensgrp{running} }); }
    elsif ($status eq 'Saved') { &sensitive_on(@{ $sensgrp{saved} }); }
    elsif ($status eq 'Paused') { &sensitive_on(@{ $sensgrp{paused} }); }
    elsif ($status eq 'PoweredOff' | $status eq 'Aborted') { &sensitive_on(@{ $sensgrp{poweroff} }); }
    else { &sensitive_off(@{ $sensgrp{unselected} }); }
}

sub onsel_list_remotefiles() {
    my %file = &getsel_list_remotefiles();

    if ($file{FileName} eq '..') { &cdup_remotefilechooser(); }
    elsif ($file{Type} eq '(Dir)') {
        my $path = IVFSExplorer_getPath($gui{IVFSExplorer});
        IVFSExplorer_cd($gui{IVFSExplorer}, "$path/$file{FileName}");
        &fill_list_remotefiles(IVFSExplorer_getPath($gui{IVFSExplorer}));
    }
}

sub onsel_list_snapshots() { &sensitive_on(@{ $sensgrp{snap} }); }

sub onsel_list_vmmhd() {
    my %hd = &getsel_list_vmmhd();

    # Don't allow remove/release if it has sub-snapshots
    if (IMedium_getChildren($hd{IMedium})) {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    elsif ($hd{Attached} eq '<None>') {
        &sensitive_on($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    else {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_on($gui{toolbuttonVMMRelease});
    }

    $gui{entryVMMAttachedTo}->set_text($hd{Attached});
    $gui{entryVMMLocation}->set_text(IMedium_getLocation($hd{IMedium}));
}

sub onsel_list_vmmdvd() {
    my %dvd = &getsel_list_vmmdvd();

    # Don't allow remove/release if it has sub-snapshots
    if (IMedium_getChildren($dvd{IMedium})) {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    elsif ($dvd{Attached} eq '<None>') {
        &sensitive_on($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    else {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_on($gui{toolbuttonVMMRelease});
    }

    $gui{entryVMMAttachedTo}->set_text($dvd{Attached});
    $gui{entryVMMLocation}->set_text(IMedium_getLocation($dvd{IMedium}));
}

sub onsel_list_vmmfloppy() {
    my %floppy = &getsel_list_vmmfloppy();

    # Don't allow remove/release if it has sub-snapshots
    if (IMedium_getChildren($floppy{IMedium})) {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    elsif ($floppy{Attached} eq '<None>') {
        &sensitive_on($gui{toolbuttonVMMRemove});
        &sensitive_off($gui{toolbuttonVMMRelease});
    }
    else {
        &sensitive_off($gui{toolbuttonVMMRemove});
        &sensitive_on($gui{toolbuttonVMMRelease});
    }

    $gui{entryVMMAttachedTo}->set_text($floppy{Attached});
    $gui{entryVMMLocation}->set_text(IMedium_getLocation($floppy{IMedium}));
}

sub onsel_list_editshared() { &sensitive_on($gui{buttonEditSharedRemove}, $gui{buttonEditSharedEdit}); }

sub onsel_list_editstorage() {
    my %storitem = &getsel_list_editstorage();

    if ($storitem{Type} =~ m/Controller/) {
        &sensitive_on(@{ $sensgrp{ctr_sel_on} });
        &sensitive_off($gui{buttonEditStorRemoveAttach});
        $gui{entryEditStorCtrName}->set_text($storitem{Name});
        &editstor_ctrtype_fill($storitem{Type}, $storitem{IObject});

        if ($storitem{Type} eq 'IDE Controller' or $storitem{Type} eq 'SATA Controller') {
            &sensitive_on($gui{menuitemAttachHD}, $gui{menuitemAttachDVD});
            &sensitive_off($gui{menuitemAttachFloppy});
        }
        elsif ($storitem{Type} eq 'Floppy Controller') {
            &sensitive_off($gui{menuitemAttachHD}, $gui{menuitemAttachDVD});
            &sensitive_on($gui{menuitemAttachFloppy});
        }
        else {
            &sensitive_on($gui{menuitemAttachHD});
            &sensitive_off($gui{menuitemAttachFloppy}, $gui{menuitemAttachDVD});
        }
    }
    elsif ($storitem{Type} eq 'DVD') { # Allow DVDs to be inserted if DVD drive selected
        &sensitive_on($gui{buttonEditStorRemoveAttach}, $gui{buttonEditStorAddAttach}, $gui{menuitemAttachDVD});
        &sensitive_off($gui{menuitemAttachHD}, $gui{menuitemAttachFloppy}, $gui{buttonEditStorRemoveCtr});
    }
    elsif ($storitem{Type} eq 'Floppy') { # Allow floppys to be inserted if floppy drive selected
        &sensitive_on($gui{buttonEditStorRemoveAttach}, $gui{buttonEditStorAddAttach}, $gui{menuitemAttachFloppy});
        &sensitive_off($gui{menuitemAttachHD}, $gui{menuitemAttachDVD}, $gui{buttonEditStorRemoveCtr});
    }
    else {
        &sensitive_on($gui{buttonEditStorRemoveAttach});
        &sensitive_off(@{ $sensgrp{ctr_sel_off} });
    }
}

sub onsel_list_usbfilters() { &sensitive_on( @{ $sensgrp{usb_sel} } ); }

sub onsel_list_vbprefsnet() { &sensitive_on( @{ $sensgrp{vbprefsnet} } ); }

1;