# General GUI related functions and structures
use strict;
use warnings;
use utf8;
use File::Spec;
use File::Spec::Functions;
use File::Spec::Win32;
use File::Spec::Unix;
use Getopt::Std;
use Gtk3 -init;

our $sharedir;

my $builder = Gtk3::Builder->new;
$builder->add_from_file("$sharedir/remotebox.xml");
$builder->connect_signals();

our %gui = (appname         => $builder->get_object('aboutdialog')->get_program_name(),
            appver          => $builder->get_object('aboutdialog')->get_version(),
            vboxEditIOPorts => $builder->get_object('vboxEditIOPorts'),
            websn           => undef);

# Guest Status
$gui{pb}{Aborted} = &gui_new_pixbuf_from_file('gueststatus/Aborted.png');
$gui{pb}{DeletingSnapshot} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{DeletingSnapshotOnline} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{DeletingSnapshotPaused} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{Discarding} = &gui_new_pixbuf_from_file('gueststatus/Discarding.png');
$gui{pb}{Error} = &gui_new_pixbuf_from_file('gueststatus/Error.png');
$gui{pb}{FaultTolerantSyncing} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{FirstOnline} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{FirstTransient} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{LastOnline} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{LastTransient} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{LiveSnapshotting} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{OnlineSnapshotting} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{Paused} = &gui_new_pixbuf_from_file('gueststatus/Paused.png');
$gui{pb}{PoweredOff} = &gui_new_pixbuf_from_file('gueststatus/PoweredOff.png');
$gui{pb}{Restoring} = &gui_new_pixbuf_from_file('gueststatus/Restoring.png');
$gui{pb}{RestoringSnapshot} = &gui_new_pixbuf_from_file('gueststatus/Restoring.png');
$gui{pb}{Running} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{Saved} = &gui_new_pixbuf_from_file('gueststatus/Saved.png');
$gui{pb}{Saving} = &gui_new_pixbuf_from_file('gueststatus/Saving.png');
$gui{pb}{SettingUp} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{Snapshotting} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{Starting} = &gui_new_pixbuf_from_file('gueststatus/Running.png');
$gui{pb}{Stopping} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{Stuck} = &gui_new_pixbuf_from_file('gueststatus/Stuck.png');
$gui{pb}{Teleported} = &gui_new_pixbuf_from_file('gueststatus/PoweredOff.png');
$gui{pb}{Teleporting} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{TeleportingIn} = &gui_new_pixbuf_from_file('gueststatus/Misc.png');
$gui{pb}{TeleportingPausedVM} = &gui_new_pixbuf_from_file('gueststatus/Paused.png');
# Storage Icons
$gui{pb}{Network} = &gui_new_pixbuf_from_file('nw_16px.png');
$gui{pb}{HardDisk} = &gui_new_pixbuf_from_file('hd_16px.png');
$gui{pb}{DVD} = &gui_new_pixbuf_from_file('cd_16px.png');
$gui{pb}{Floppy} = &gui_new_pixbuf_from_file('fd_16px.png');
$gui{pb}{ctr}{IDE} = &gui_new_pixbuf_from_file('ide_16px.png');
$gui{pb}{ctr}{SATA} = &gui_new_pixbuf_from_file('sata_16px.png');
$gui{pb}{ctr}{SAS} = $gui{pb}{ctr}{SATA};
$gui{pb}{ctr}{SCSI} = &gui_new_pixbuf_from_file('scsi_16px.png');
$gui{pb}{ctr}{Floppy} = &gui_new_pixbuf_from_file('floppy_16px.png');
$gui{pb}{ctr}{USB} = &gui_new_pixbuf_from_file('usb_16px.png');
$gui{pb}{ctr}{PCIe} = &gui_new_pixbuf_from_file('nvme_16px.png');
$gui{pb}{ctr}{VirtioSCSI} = &gui_new_pixbuf_from_file('virtio_scsi_16px.png');
# Snapshot icons
$gui{pb}{SnapshotOffline} = &gui_new_pixbuf_from_file('snapshot_offline_16px.png');
$gui{pb}{SnapshotOnline} = &gui_new_pixbuf_from_file('snapshot_online_16px.png');
$gui{pb}{SnapshotCurrent} = &gui_new_pixbuf_from_file('machine_16px.png');
# OS Icons
$gui{pb}{OtherOS} = &gui_new_pixbuf_from_file('os/Other.png');
$gui{pb}{OtherOS64} = &gui_new_pixbuf_from_file('os/Other_64.png');
# Other Icons
$gui{pb}{VMGroup} = &gui_new_pixbuf_from_file('vm_group_16px.png');
$gui{pb}{DirIcon} = &gui_new_pixbuf_from_file('sf_16px.png');
$gui{pb}{FileIcon} = &gui_new_pixbuf_from_file('vm_open_filemanager_16px.png');
$gui{pb}{ParentIcon} = &gui_new_pixbuf_from_file('sf_parent_16px.png');
# Details Icons
$gui{pb}{CatGen} = &gui_new_pixbuf_from_file('machine_16px.png');
$gui{pb}{CatSys} = &gui_new_pixbuf_from_file('chipset_16px.png');
$gui{pb}{CatDisp} = &gui_new_pixbuf_from_file('vrdp_16px.png');
$gui{pb}{CatStor} = &gui_new_pixbuf_from_file('hd_16px.png');
$gui{pb}{CatAudio} = &gui_new_pixbuf_from_file('sound_16px.png');
$gui{pb}{CatNet} = &gui_new_pixbuf_from_file('nw_16px.png');
$gui{pb}{CatIO} = &gui_new_pixbuf_from_file('serial_port_16px.png');
$gui{pb}{CatUSB} = &gui_new_pixbuf_from_file('usb_16px.png');
$gui{pb}{CatShare} = &gui_new_pixbuf_from_file('sf_16px.png');
$gui{pb}{CatDesc} = &gui_new_pixbuf_from_file('description_16px.png');
# Progress Decals
$gui{pb}{ProgressClone} = &gui_new_pixbuf_from_file('progress_clone_90px.png');
$gui{pb}{ProgressRefresh} = &gui_new_pixbuf_from_file('progress_refresh_90px.png');
$gui{pb}{ProgressDelete} = &gui_new_pixbuf_from_file('progress_delete_90px.png');
$gui{pb}{ProgressExport} = &gui_new_pixbuf_from_file('progress_export_90px.png');
$gui{pb}{ProgressImport} = &gui_new_pixbuf_from_file('progress_import_90px.png');
$gui{pb}{ProgressInstallGA} = &gui_new_pixbuf_from_file('progress_install_guest_additions_90px.png');
$gui{pb}{ProgressMediaCreate} = &gui_new_pixbuf_from_file('progress_media_create_90px.png');
$gui{pb}{ProgressMediaDelete} = &gui_new_pixbuf_from_file('progress_media_delete_90px.png');
$gui{pb}{ProgressMediaMove} = &gui_new_pixbuf_from_file('progress_media_move_90px.png');
$gui{pb}{ProgressMediaResize} = &gui_new_pixbuf_from_file('progress_media_resize_90px.png');
$gui{pb}{ProgressNetwork} = &gui_new_pixbuf_from_file('progress_network_interface_90px.png');
$gui{pb}{ProgressPowerOff} = &gui_new_pixbuf_from_file('progress_poweroff_90px.png');
$gui{pb}{ProgressReadAppl} = &gui_new_pixbuf_from_file('progress_reading_appliance_90px.png');
$gui{pb}{ProgressSettings} = &gui_new_pixbuf_from_file('progress_settings_90px.png');
$gui{pb}{ProgressSnapshotCreate} = &gui_new_pixbuf_from_file('progress_snapshot_create_90px.png');
$gui{pb}{ProgressSnapshotDiscard} = &gui_new_pixbuf_from_file('progress_snapshot_discard_90px.png');
$gui{pb}{ProgressSnapshotRestore} = &gui_new_pixbuf_from_file('progress_snapshot_restore_90px.png');
$gui{pb}{ProgressStart} = &gui_new_pixbuf_from_file('progress_start_90px.png');
$gui{pb}{ProgressRestore} = &gui_new_pixbuf_from_file('progress_state_restore_90px.png');
$gui{pb}{ProgressStateSave} = &gui_new_pixbuf_from_file('progress_state_save_90px.png');

our (%prefs, %lists);

# Fill %gui so we can reference them easily.
foreach ($builder->get_objects) {
    my $id;
    eval{ $id = $_->Gtk3::Buildable::get_name; }; # DONT USE $_->get_name()
    $gui{$id} = $_ if ($id);
}

# Image Widgets
# Main Toolbar (windowMain)
$gui{imgConnectMain32} = &gui_new_img_from_file('connect_32px.png', $gui{toolbuttonConnect});
$gui{imgNewMain32} = &gui_new_img_from_file('vm_new_32px.png', $gui{toolbuttonNew});
$gui{imgSettingsMain32} = &gui_new_img_from_file('vm_settings_32px.png', $gui{toolbuttonSettings});
$gui{imgStartMain32} = &gui_new_img_from_file('vm_start_32px.png', $gui{toolbuttonStart});
$gui{imgStopMain32} = &gui_new_img_from_file('stop_32px.png', $gui{toolbuttonStop});
$gui{imgDiscardMain32} = &gui_new_img_from_file('vm_discard_32px.png', $gui{toolbuttonDiscard});
$gui{imgResetMain32} = &gui_new_img_from_file('reset_32px.png', $gui{toolbuttonReset});
$gui{imgDisplayMain32} = &gui_new_img_from_file('vrdp_32px.png', $gui{toolbuttonRemoteDisplay});
$gui{imgCADMain32} = &gui_new_img_from_file('keyboard_32px.png', $gui{toolbuttonCAD});
$gui{imgRefreshMain32} = &gui_new_img_from_file('refresh_32px.png', $gui{toolbuttonRefresh});
# Snapshots Toolbar (windowMain)
$gui{imgTakeSnap32} = &gui_new_img_from_file('snapshot_take_32px.png', $gui{buttonTakeSnapshot});
$gui{imgDeleteSnap32} = &gui_new_img_from_file('snapshot_delete_32px.png', $gui{buttonDeleteSnapshot});
$gui{imgRestoreSnap32} = &gui_new_img_from_file('snapshot_restore_32px.png', $gui{buttonRestoreSnapshot});
$gui{imgDetailsSnap32} = &gui_new_img_from_file('snapshot_show_details_32px.png', $gui{buttonDetailsSnapshot});
$gui{imgCloneSnap32} = &gui_new_img_from_file('vm_clone_32px.png', $gui{buttonCloneSnapshot});
$gui{imgRefreshSnap32} = &gui_new_img_from_file('refresh_32px.png', $gui{buttonRefreshSnapshot});
# Save Message Log (windowMain)
$gui{imgSaveMsgLog32} = &gui_new_img_from_file('log_viewer_save_32px.png', $gui{buttonMessageLogSave});
# (windowMain)
$gui{imgGrpShrink16} = &gui_new_img_from_file('vm_group_shrink_16px.png', $gui{buttonGroupShrink});
$gui{imgGrpExpand16} = &gui_new_img_from_file('vm_group_expand_16px.png', $gui{buttonGroupExpand});

# Edit Settings (dialogEdit)
# General (dialogEdit)
$gui{imgSetSnapFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonEditGenSnapFolder});
# System (dialogEdit)
$gui{imgBootLogoFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonEditSysLogoPath});
# Display (dialogEdit)
$gui{imgDispCapFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonEditDispCapturePath});
# Network (dialogEdit)
$gui{imgGenerateMAC22} = &gui_new_img_from_file('refresh_22px.png', $gui{buttonEditNetGenerateMac});
# I/O Ports (dialogEdit)
$gui{imgGeneratePortPath22} = &gui_new_img_from_file('refresh_22px.png', $gui{buttonEditSerialPortPathGenerate});
# VB Default Prefs (dialogVBPrefs)
$gui{imgGenMacFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonVBPrefsGenMachineFolderChoose});
$gui{imgGenAutoFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonVBPrefsGenAutostartDBFolder});
$gui{imgResetDefMacFolder16} = &gui_new_img_from_file('reset_defmacfolder_16px.png', $gui{buttonVBPrefsGenMachineFolderReset});
$gui{imgResetVRDPAuthLibFolder16} = &gui_new_img_from_file('reset_vrdpauthlib_16px.png', $gui{buttonVBPrefsGenDefVRDPAuthReset});
# RB Prefs (dialogPrefs)
$gui{imgPresetRDP16} = &gui_new_img_from_file('rdp_presets_16px.png', $gui{buttonPrefsRDPClientPreset});
$gui{imgPresetVNC16} = &gui_new_img_from_file('rdp_presets_16px.png', $gui{buttonPrefsVNCClientPreset});
# Export Appliance
$gui{imgExportApplFolder} = &gui_new_img_from_file('sf_16px.png', $gui{buttonExportApplFile});
# Import Appliance (dialogImportAppl)
$gui{imgImportApplFolder} = &gui_new_img_from_file('sf_16px.png', $gui{buttonImportApplChoose});
# File Chooser (dialogRemoteFileChooser)
$gui{imgRemoteFileChooserCDUp16} = &gui_new_img_from_file('sf_parent_16px.png', $gui{buttonRemoteFileChooserCDUp});
$gui{ImgRemoteFileChooserFolder16} = &gui_new_img_from_file('refresh_16px.png', $gui{buttonRemoteFileChooserRefresh});
# Log Window (dialogLog)
$gui{imgLogSave32} = &gui_new_img_from_file('log_viewer_save_32px.png', $gui{toolbuttonLogSave});
$gui{imgLogRefresh32} = &gui_new_img_from_file('log_viewer_refresh_32px.png', $gui{toolbuttonLogRefresh});

# VMM ToolBar
$gui{imgHDAdd32} = &gui_new_img_from_file('hd_add_32px.png', $gui{toolbuttonVMMAdd});
$gui{imgHDCopy32} = &gui_new_img_from_file('hd_copy_32px.png', $gui{toolbuttonVMMCopy});
$gui{imgHDCreate32} = &gui_new_img_from_file('hd_create_32px.png', $gui{toolbuttonVMMCreate});
$gui{imgHDModify32} = &gui_new_img_from_file('hd_modify_32px.png', $gui{toolbuttonVMMModify});
$gui{imgHDMove32} = &gui_new_img_from_file('hd_move_32px.png', $gui{toolbuttonVMMMove});
$gui{imgHDRelease32} = &gui_new_img_from_file('hd_release_32px.png', $gui{toolbuttonVMMRelease});
$gui{imgHDRemove32} = &gui_new_img_from_file('hd_remove_32px.png', $gui{toolbuttonVMMRemove});
$gui{imgCompact32} = &gui_new_img_from_file('compact_32px.png', $gui{toolbuttonVMMCompact});
$gui{imgRefreshVMM32} = &gui_new_img_from_file('refresh_32px.png', $gui{toolbuttonVMMRefresh});
$gui{imgFloppyAdd32} = &gui_new_img_from_file('fd_add_32px.png');
$gui{imgFloppyCopy32} = &gui_new_img_from_file('fd_copy_32px.png');
$gui{imgFloppyCreate32} = &gui_new_img_from_file('fd_create_32px.png');
$gui{imgFloppyModify32} = &gui_new_img_from_file('fd_modify_32px.png');
$gui{imgFloppyMove32} = &gui_new_img_from_file('fd_move_32px.png');
$gui{imgFloppyRelease32} = &gui_new_img_from_file('fd_release_32px.png');
$gui{imgFloppyRemove32} = &gui_new_img_from_file('fd_remove_32px.png');
$gui{imgDVDAdd32} = &gui_new_img_from_file('cd_add_32px.png');
$gui{imgDVDCopy32} = &gui_new_img_from_file('cd_copy_32px.png');
$gui{imgDVDCreate32} = &gui_new_img_from_file('cd_create_32px.png');
$gui{imgDVDModify32} = &gui_new_img_from_file('cd_modify_32px.png');
$gui{imgDVDMove32} = &gui_new_img_from_file('cd_move_32px.png');
$gui{imgDVDRelease32} = &gui_new_img_from_file('cd_release_32px.png');
$gui{imgDVDRemove32} = &gui_new_img_from_file('cd_remove_32px.png');
# Create New Floppy (dialogCreateFloppy)
$gui{imgCreateFloppyFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonCreateFloppyChooseLoc});
#
$gui{imgCopyFloppyFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonVMMCopyFloppyChooser});
# Create New HD (dialogCreateHD)
$gui{imgCreateHDFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonCreateHDChooseLoc});
# Copy HD (dialogVMMCopyHD)
$gui{imgCopyHDFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonCreateCopyChooser});
# Move HD (dialogVMMMoveMedium)
$gui{imgCopyHDFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonCreateCopyChooser});
# Copy Floppy (dialogVMMCopyFloppy)
$gui{imgMoveHDFolder16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonMoveMediumChooser});

# Host Only Network
$gui{imgAddNetHON16} = &gui_new_img_from_file('add_host_iface_16px.png', $gui{buttonVBPrefsAddHON});
$gui{imgDelNetHON16} = &gui_new_img_from_file('remove_host_iface_16px.png', $gui{buttonVBPrefsDelHON});
$gui{imgEditNetHON16} = &gui_new_img_from_file('host_iface_edit_16px.png', $gui{buttonVBPrefsEditHON});
# NAT Networks
$gui{imgAddNetNAT16} = &gui_new_img_from_file('add_host_iface_16px.png', $gui{buttonVBPrefsAddNAT});
$gui{imgDelNetNAT16} = &gui_new_img_from_file('remove_host_iface_16px.png', $gui{buttonVBPrefsDelNAT});
$gui{imgEditNetNAT16} = &gui_new_img_from_file('host_iface_edit_16px.png', $gui{buttonVBPrefsEditNAT});
# Edit Shared Folders
$gui{imgAddShared16} = &gui_new_img_from_file('sf_add_16px.png', $gui{buttonEditSharedAdd});
$gui{imgRemoveShared16} = &gui_new_img_from_file('remove_host_iface_16px.png', $gui{buttonEditSharedRemove});
$gui{imgEditShared16} = &gui_new_img_from_file('host_iface_edit_16px.png', $gui{buttonEditSharedEdit});
# Edit a Share (dialogShared)
$gui{imgEditAShare16} = &gui_new_img_from_file('sf_16px.png', $gui{buttonSharedFolderChoose});
# Boot Order
$gui{imgSysBootUp10} = &gui_new_img_from_file('arrow_up_10px.png', $gui{buttonEditSysBootUp});
$gui{imgSysDownUp10} = &gui_new_img_from_file('arrow_down_10px.png', $gui{buttonEditSysBootDown});
# Edit Storage
$gui{imgCtrAdd16} = &gui_new_img_from_file('controller_add_16px.png', $gui{buttonEditStorAddCtr});
$gui{imgCtrRemove16} = &gui_new_img_from_file('controller_remove_16px.png', $gui{buttonEditStorRemoveCtr});
$gui{imgAttachAdd16} = &gui_new_img_from_file('attachment_add_16px.png', $gui{buttonEditStorAddAttach});
$gui{imgAttachRemove16} = &gui_new_img_from_file('attachment_remove_16px.png', $gui{buttonEditStorRemoveAttach});
# USB Filters
$gui{imgUSBFilterNewZero16} = &gui_new_img_from_file('usb_new_16px.png', $gui{buttonEditUSBAddZ});
$gui{imgUSBFilterNew16} = &gui_new_img_from_file('usb_add_16px.png', $gui{buttonEditUSBAdd});
$gui{imgUSBFilterRemove16} = &gui_new_img_from_file('usb_remove_16px.png', $gui{buttonEditUSBRemove});
$gui{imgUSBFilterEdit16} = &gui_new_img_from_file('usb_filter_edit_16px.png', $gui{buttonEditUSBEdit});
$gui{imgUSBFilterUp16} = &gui_new_img_from_file('usb_moveup_16px.png', $gui{buttonEditUSBUp});
$gui{imgUSBFilterDown16} = &gui_new_img_from_file('usb_movedown_16px.png', $gui{buttonEditUSBDown});
# Port Forwarding Rules
$gui{imgRulePF4Add16} = &gui_new_img_from_file('rule_add_16px.png', $gui{buttonPFRulesAdd4});
$gui{imgRulePF4Edit16} = &gui_new_img_from_file('rule_edit_16px.png', $gui{buttonPFRulesEdit4});
$gui{imgRulePF4Remove16} = &gui_new_img_from_file('rule_remove_16px.png', $gui{buttonPFRulesRemove4});
$gui{imgRulePF6Add16} = &gui_new_img_from_file('rule_add_16px.png', $gui{buttonPFRulesAdd6});
$gui{imgRulePF6Edit16} = &gui_new_img_from_file('rule_edit_16px.png', $gui{buttonPFRulesEdit6});
$gui{imgRulePF6Remove16} = &gui_new_img_from_file('rule_remove_16px.png', $gui{buttonPFRulesRemove6});
# Adjustments
$gui{adjEditGenAutostartDelay} = &gui_new_adjustment($gui{sbEditGenAutostartDelay}, 0, 0, 999, 1, 10, 0);
$gui{adjCustomVideoH} = &gui_new_adjustment($gui{spinbuttonCustomVideoH}, 480, 80, 4000, 1, 10, 0);
$gui{spinbuttonPrefsHeight}->set_adjustment($gui{adjCustomVideoH});
$gui{adjCustomVideoW} = &gui_new_adjustment($gui{spinbuttonCustomVideoW}, 640, 80, 8000, 1, 10, 0);
$gui{spinbuttonPrefsWidth}->set_adjustment($gui{adjCustomVideoW});
$gui{adjEditDispAuthTime} = &gui_new_adjustment($gui{spinbuttonEditDispAuthTime}, 0, 0, 10000, 1, 100, 0);
$gui{adjEditDispCaptureFPS} = &gui_new_adjustment($gui{sbEditDispCaptureFPS}, 15, 1, 30, 1, 5, 0);
$gui{hscaleEditDispCaptureFPS}->set_adjustment($gui{adjEditDispCaptureFPS});
$gui{adjEditDispCaptureQuality} = &gui_new_adjustment($gui{sbEditDispCaptureQuality}, 128, 32, 2048, 1, 10, 0);
$gui{hscaleEditDispCaptureQuality}->set_adjustment($gui{adjEditDispCaptureQuality});
$gui{adjEditDispCaptureSizeH} = &gui_new_adjustment($gui{sbEditDispCaptureSizeH}, 200, 16, 1800, 1, 10, 0);
$gui{adjEditDispCaptureSizeW} = &gui_new_adjustment($gui{sbEditDispCaptureSizeW}, 320, 16, 2880, 1, 10, 0);
$gui{adjEditDispMonitor} = &gui_new_adjustment($gui{spinbuttonEditDispMonitor}, 0, 1, 64, 1, 1, 0);
$gui{hscaleEditDispMonitor}->set_adjustment($gui{adjEditDispMonitor});
$gui{adjEditDispVidMem} = &gui_new_adjustment($gui{spinbuttonEditDispVidMem}, 0, 1, 256, 1, 1, 0);
$gui{hscaleEditDispVidMem}->set_adjustment($gui{adjEditDispVidMem});
$gui{adjEditStorPortCount} = &gui_new_adjustment($gui{spinbuttonEditStorPortCount}, 1, 1, 30, 1, 1, 0);
$gui{adjEditSysBootLogo} = &gui_new_adjustment($gui{spinbuttonEditSysLogoTime}, 0, 0, 86400000, 1, 0, 0);
$gui{adjEditSysMem} = &gui_new_adjustment($gui{spinbuttonEditSysMem}, 4, 4, 2097152, 1, 16, 0);
$gui{hscaleEditSysMem}->set_adjustment($gui{adjEditSysMem});
$gui{adjEditSysProcessor} = &gui_new_adjustment($gui{hscaleEditSysProcessor}, 1, 1, 33, 1, 1, 1);
$gui{adjEditSysProcessorCap} = &gui_new_adjustment($gui{hscaleEditSysProcessorCap}, 100, 1, 100, 1, 10, 0);
$gui{adjPFIPGuestPort} = &gui_new_adjustment($gui{spinbuttonPFIPv4GuestPort}, 0, 0, 65535, 1, 10, 0);
$gui{spinbuttonPFIPv6GuestPort}->set_adjustment($gui{adjPFIPGuestPort});
$gui{adjPFIPHostPort} = &gui_new_adjustment($gui{spinbuttonPFIPv4HostPort}, 0, 0, 65535, 1, 10, 0);
$gui{spinbuttonPFIPv6HostPort}->set_adjustment($gui{adjPFIPHostPort});
$gui{adjEditSysTimeOffset} = &gui_new_adjustment($gui{spinbuttonEditSysTimeOffset}, 0, 0, 86400000, 1, 0, 0);
$gui{adjNewMemory} = &gui_new_adjustment($gui{spinbuttonNewMemory}, 4, 4, 2097152, 1, 16, 0);
$gui{hscaleNewMemory}->set_adjustment($gui{adjNewMemory});
$gui{adjNewNewHDSize} = &gui_new_adjustment($gui{spinbuttonCreateHDSize}, 8000, 8, 2097152, 1, 16, 0);
$gui{spinbuttonNewNewHDSize}->set_adjustment($gui{adjNewNewHDSize});
$gui{adjVMMModifyResizeHD} = &gui_new_adjustment($gui{spinbuttonVMMModifyResizeHD}, 8000, 8, 2097152, 1, 16, 0);
# Lists
# New Guest ISO 'ISO Name', 'IMedium'
$gui{liststoreNewGuestDVD} = &gui_new_lstore($gui{comboboxNewISOImage}, ['Glib::String', 'Glib::String']);
# TPM (Friendly Name, Value)
$gui{liststoreEditSysTPM} = &gui_new_lstore($gui{comboboxEditSysTPM}, ['Glib::String', 'Glib::String']);
# Log - Category, Value Weight
$gui{liststoreLog0} = &gui_new_lstore($gui{treeviewLog0}, ['Glib::String', 'Glib::String', 'Glib::Uint']);
$gui{liststoreLog1} = &gui_new_lstore($gui{treeviewLog1}, ['Glib::String', 'Glib::String', 'Glib::Uint']);
$gui{liststoreLog2} = &gui_new_lstore($gui{treeviewLog2}, ['Glib::String', 'Glib::String', 'Glib::Uint']);
$gui{liststoreLog3} = &gui_new_lstore($gui{treeviewLog3}, ['Glib::String', 'Glib::String', 'Glib::Uint']);
# Chooese Existing HD
$gui{liststoreNewChooseHD} = &gui_new_lstore($gui{comboboxNewChooseHD}, ['Glib::String', 'Glib::String']);
# Connection Profiles
$gui{liststoreProfiles} = &gui_new_lstore($gui{comboboxConnectProfile}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']);
$gui{treeviewConnectionProfiles}->set_model($gui{liststoreProfiles}); # Also set it for the profile connection
# Message log
$gui{liststoreMsgLog} = &gui_new_lstore($gui{treeviewMsgLog}, ['Glib::String']);
# Network Adapter Type: ID, Description
$gui{liststoreEditNetAdapterType} = &gui_new_lstore($gui{comboboxEditNetType}, ['Glib::String', 'Glib::String'], [0, 1], $lists{network_adapters});
# Network Attachment Type: ID, Description
$gui{liststoreEditNetAttachTo} = &gui_new_lstore($gui{comboboxEditNetAttach}, ['Glib::String', 'Glib::String'], [0, 1], $lists{network_attach_types});
# Clone States: Name
$gui{liststoreClone} = &gui_new_lstore($gui{comboboxCloneType}, ['Glib::String'], [0], $lists{clone_states});
# Clone Mac Policies: Name
$gui{liststoreCloneMAC} = &gui_new_lstore($gui{comboboxCloneMAC}, ['Glib::String'], [0], $lists{mac_policies});
# Import Appliance
$gui{liststoreImportApplMAC} = &gui_new_lstore($gui{comboboxImportApplMAC}, ['Glib::String'], [0], $lists{mac_policies});
# Custom Video Depths for Hints
$gui{liststoreCustomVideoD} = &gui_new_lstore($gui{comboboxCustomVideoD}, ['Glib::String', 'Glib::Uint'], [0, 1], $lists{custom_video_d});
# New Floppy Disk Image
$gui{liststoreNewFloppySize} = &gui_new_lstore($gui{comboboxCreateFloppySize}, ['Glib::String', 'Glib::String'], [0, 1], $lists{floppy_sizes});
# New HD and Copy HD
$gui{liststoreNewImageFormat} = &gui_new_lstore($gui{comboboxCreateHDFormat}, ['Glib::String', 'Glib::String'], [0, 1], $lists{hd_img_formats});
$gui{comboboxCopyHDFormat}->set_model($gui{liststoreNewImageFormat}); # Also add
$gui{comboboxNewNewFormat}->set_model($gui{liststoreNewImageFormat}); # Also add
#
$gui{liststorePFIPProtocol} = &gui_new_lstore($gui{comboboxPFIPv4Protocol}, ['Glib::String', 'Glib::String'], [0, 1], $lists{ip_protocols});
$gui{comboboxPFIPv6Protocol}->set_model($gui{liststorePFIPProtocol}); # Also add
# Appliance Formats for Export
$gui{liststoreExportApplFormat} = &gui_new_lstore($gui{comboboxExportApplFormat}, ['Glib::String', 'Glib::String', 'Glib::String'], [0, 1, 2], $lists{appliance_formats});
# RDP Auth Methods
$gui{liststoreDispAuthMeth} = &gui_new_lstore($gui{comboboxDispAuthMeth}, ['Glib::String', 'Glib::String'], [0, 1], $lists{rdp_auth_methods});
# Audio Codecs
$gui{liststoreEditAudioCodecAC97} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_codecs_ac97});
$gui{liststoreEditAudioCodecSB16} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_codecs_sb16});
$gui{liststoreEditAudioCodecHDA} = &gui_new_lstore($gui{comboboxEditAudioCodec}, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_codecs_hda});
# Audio Controllers
$gui{liststoreEditAudioCtr} = &gui_new_lstore($gui{comboboxEditAudioCtr}, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_controllers});
# Audio Drivers
$gui{liststoreEditAudioDriverFreeBSD} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_freebsd});
$gui{liststoreEditAudioDriverLin} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_linux});
$gui{liststoreEditAudioDriverMac} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_mac});
$gui{liststoreEditAudioDriverOther} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_other});
$gui{liststoreEditAudioDriverSol} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_solaris});
$gui{liststoreEditAudioDriverWin} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_drivers_windows});
# Audio Capture Quality
$gui{liststoreEditDispCaptureAudioQuality} = &gui_new_lstore($gui{comboboxEditDispAudioQuality}, ['Glib::String', 'Glib::String'], [0, 1], $lists{audio_capture_quality});
# Display Capture Sizes
$gui{liststoreDispCaptureSize} = &gui_new_lstore($gui{comboboxEditDispCaptureSize}, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{disp_capture_sizes});
# Clipboard Options
$gui{liststoreEditClip} = &gui_new_lstore($gui{comboboxEditGenClip}, ['Glib::String', 'Glib::String'], [0, 1], $lists{clipboard_modes});
# Listore Info
$gui{liststoreInfo} = &gui_new_lstore($gui{treeviewInfo}, ['Glib::String', 'Glib::String', 'Glib::Uint', 'Glib::Double']);
# Capture Modes
$gui{liststoreEditDispCaptureMode} = &gui_new_lstore($gui{comboboxEditDispCaptureMode}, ['Glib::String', 'Glib::String'], [0, 1], $lists{capture_modes});
# Auto Stops
$gui{liststoreEditGenAutostop} = &gui_new_lstore($gui{comboboxEditGenAutostop}, ['Glib::String', 'Glib::String'], [0, 1], $lists{auto_stop_types});
# OS Families
$gui{liststoreEditGenOSFam} = &gui_new_lstore($gui{comboboxEditGenOSFam}, ['Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
$gui{liststoreEditGenOSVer} = &gui_new_lstore($gui{comboboxEditGenOSVer}, ['Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
$gui{liststoreNewOSFam} = &gui_new_lstore($gui{comboboxNewOSFam}, ['Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
$gui{liststoreNewOSVer} = &gui_new_lstore($gui{comboboxNewOSVer}, ['Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
# Internal Net Names
$gui{liststoreEditNetName} = &gui_new_lstore($gui{comboboxEditNetName}, ['Glib::String', 'Glib::String']);
$gui{liststoreEditNetNameInt} = &gui_new_lstore($gui{comboboxentryEditNetNameInt}, ['Glib::String']);
#
$gui{liststoreEditNetPromiscuous} = &gui_new_lstore($gui{comboboxEditNetPromiscuous}, ['Glib::String', 'Glib::String'], [0, 1], $lists{network_promiscuous_modes});
# Network Adapter lists
$gui{liststoreEditNetAdapter} = &gui_new_lstore($gui{comboboxEditNetSelectedAdapter}, ['Glib::String', 'Glib::Uint'], [0, 1], $lists{network_adapter_instances});
#
$gui{liststoreEditNetGenDriver} = &gui_new_lstore($gui{comboboxentryEditNetGenDriver}, ['Glib::String']);
# Device Ports
$gui{liststoreEditStorDevPortSAS} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{sas_device_ports});
$gui{liststoreEditStorDevPortSATA} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{sata_device_ports});
$gui{liststoreEditStorDevPortSCSI} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{scsi_device_ports});
$gui{liststoreEditStorDevPortUSB} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{usb_device_ports});
$gui{liststoreEditStorDevPortNVMe} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{nvme_device_ports});
$gui{liststoreEditStorDevPortIDE} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{ide_device_ports});
$gui{liststoreEditStorDevPortFloppy} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{floppy_device_ports});
$gui{liststoreEditStorDevPortVirtio} = &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint', 'Glib::Uint'], [0, 1, 2], $lists{virtio_device_ports});
# Floppy Drive Types
$gui{liststoreEditStorFloppyType} = &gui_new_lstore($gui{comboboxEditStorFloppyType}, ['Glib::String', 'Glib::String'], [0, 1], $lists{floppy_drive_types});
# IO Ports
$gui{liststoreEditSerialMode} = &gui_new_lstore($gui{comboboxEditSerialMode}, ['Glib::String'], [0], $lists{serial_modes});
$gui{liststoreEditSerialPort} = &gui_new_lstore($gui{comboboxEditIOSelectedSerial}, ['Glib::String', 'Glib::Uint'], [0, 1], $lists{serial_port_instances});
$gui{liststoreEditSerialPortNum} = &gui_new_lstore($gui{comboboxEditSerialPortNum}, ['Glib::String'], [0], $lists{serial_port_types});
$gui{liststoreEditSerialUART} = &gui_new_lstore($gui{comboboxEditSerialUART}, ['Glib::String', 'Glib::String'], [0, 1], $lists{serial_uart_types});
$gui{liststoreEditParallelPortNum} = &gui_new_lstore($gui{comboboxEditParallelPortNum}, ['Glib::String'], [0], $lists{parallel_port_types});
#
$gui{liststoreEditShared} = &gui_new_lstore($gui{treeviewEditShared}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String']);
# Controller Types
$gui{liststoreEditStorFloppyCtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{floppy_ctr_types});
$gui{liststoreEditStorIDECtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{ide_ctr_types});
$gui{liststoreEditStorNVMeCtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{nvme_ctr_types});
$gui{liststoreEditStorSASCtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{sas_ctr_types});
$gui{liststoreEditStorSATACtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{sata_ctr_types});
$gui{liststoreEditStorSCSICtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{scsi_ctr_types});
$gui{liststoreEditStorUSBCtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{usb_ctr_types});
$gui{liststoreEditStorVirtioSCSICtrType} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{virtio_ctr_types});
# Chipsets
$gui{liststoreEditSysChipset} = &gui_new_lstore($gui{comboboxEditSysChipset}, ['Glib::String', 'Glib::String'], [0, 1], $lists{chipset_types});
# keyboards
$gui{liststoreEditSysKeyboard} = &gui_new_lstore($gui{comboboxEditSysKeyboard}, ['Glib::String', 'Glib::String'], [0, 1], $lists{keyboard_types});
# ParaVirt
$gui{liststoreEditSysParavirt} = &gui_new_lstore($gui{comboboxEditSysParavirt},  ['Glib::String', 'Glib::String'], [0, 1], $lists{paravirt_types});
# Pointers
$gui{liststoreEditSysPointing} = &gui_new_lstore($gui{comboboxEditSysPointing}, ['Glib::String', 'Glib::String'], [0, 1], $lists{pointer_types});
# USB Filters
$gui{liststoreEditUSBFilter} = &gui_new_lstore($gui{treeviewEditUSBFilters}, ['Glib::Boolean', 'Glib::String', 'Glib::String', 'Glib::Uint']);
$gui{liststoreUSBFilterRemote} = &gui_new_lstore($gui{comboboxUSBFilterRemote}, ['Glib::String', 'Glib::String'], [0, 1], $lists{usb_remote_filter_types});
$gui{crndrtoggleEditUSBEnabled} = &gui_new_cellrenderer('toggle');
$gui{treeviewcolumnEditUSBEnabled}->pack_start($gui{crndrtoggleEditUSBEnabled}, FALSE);
$gui{treeviewcolumnEditUSBEnabled}->add_attribute($gui{crndrtoggleEditUSBEnabled}, 'active', 0);
# VGA Cards
$gui{liststoreEditVirtualVGA} = &gui_new_lstore($gui{comboboxEditDispVGA}, ['Glib::String', 'Glib::String'], [0, 1], $lists{graphics_card_types});
#
$gui{liststoreExportApplMAC} = &gui_new_lstore($gui{comboboxExportApplMAC}, ['Glib::String'], [0], $lists{mac_policies_export});
# Cyphers
$gui{liststoreGenEncryptionCipher} = &gui_new_lstore($gui{comboboxEditGenEncryptionCipher}, ['Glib::String', 'Glib::String'], [0, 1], $lists{cypher_types});
# IP Filters
$gui{liststorePFRulesIPv4} = &gui_new_lstore($gui{treeviewPFRulesIPv4}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']);
$gui{liststorePFRulesIPv6} = &gui_new_lstore($gui{treeviewPFRulesIPv6}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']);
# Stop Types
$gui{liststorePrefsDefaultStop} = &gui_new_lstore($gui{comboboxPrefsDefaultStop}, ['Glib::String', 'Glib::String'], [0, 1], $lists{stop_types});
# File Chooser
$gui{liststoreRemoteFileChooser} = &gui_new_lstore($gui{treeviewRemoteFileChooser}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
# HON
$gui{liststoreVBPrefsHON} = &gui_new_lstore($gui{treeviewVBPrefsHON}, ['Glib::String', 'Glib::String', 'Glib::String']);
# Media State Types
$gui{liststoreVMMModifyType} = &gui_new_lstore($gui{comboboxVMMModifyType}, ['Glib::String', 'Glib::String'], [0, 1], $lists{media_state_types});
#
$gui{liststoreEditSysBoot} = &gui_new_lstore($gui{treeviewEditSysBoot}, ['Glib::Boolean', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String']);
$gui{crndrtoggleEditSysBootEnabled} = &gui_new_cellrenderer('toggle');
$gui{columnEditSysBootEnabled}->pack_start($gui{crndrtoggleEditSysBootEnabled}, FALSE);
$gui{columnEditSysBootEnabled}->add_attribute($gui{crndrtoggleEditSysBootEnabled}, 'active', 0);
#
$gui{liststoreVBPrefsNAT} = &gui_new_lstore($gui{treeviewVBPrefsNAT}, ['Glib::Boolean', 'Glib::String', 'Glib::String']);
$gui{crndrtoggleVBPrefsNATEnabled} = &gui_new_cellrenderer('toggle');
$gui{treeviewcolumnVBPrefsNATEnabled}->pack_start($gui{crndrtoggleVBPrefsNATEnabled}, FALSE);
$gui{treeviewcolumnVBPrefsNATEnabled}->add_attribute($gui{crndrtoggleVBPrefsNATEnabled}, 'active', 0);
# Details
$gui{treestoreDetails} = &gui_new_tstore($gui{treeviewDetails}, ['Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::Uint', 'Glib::Double', 'Glib::String']);
# Edit Storage
$gui{treestoreEditStor} = &gui_new_tstore($gui{treeviewEditStor}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::Uint', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::Uint', 'Glib::Uint', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
# Guest
$gui{treestoreGuest} = &gui_new_tstore($gui{treeviewGuest}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
# Snaphots
$gui{treestoreSnapshots} = &gui_new_tstore($gui{treeviewSnapshots}, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']);
# VMM Storage
$gui{treestoreVMMHD} = &gui_new_tstore($gui{treeviewVMMHD}, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']);
$gui{treestoreVMMFloppy} = &gui_new_tstore($gui{treeviewVMMFloppy}, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String']);
$gui{treestoreVMMDVD} = &gui_new_tstore($gui{treeviewVMMDVD}, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String']);
#
$gui{txtbSnapshotDescription} = &gui_new_textbuffer($gui{textviewSnapshotDescription});
$gui{txtbExportApplLicense} = &gui_new_textbuffer($gui{textviewExportApplLicense});
$gui{txtbExportApplDescription} = &gui_new_textbuffer($gui{textviewExportApplDescription});
$gui{txtbEditGenDescription} = &gui_new_textbuffer($gui{textviewEditGenDescription});
$gui{txtbEditNetGeneric} = &gui_new_textbuffer($gui{textviewEditNetGeneric});
# Menus
$gui{menuCtrAdd} = &gui_new_menu();
$gui{miCtrAddIDE} = &gui_new_menu_item('_IDE Controller', 'ide_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddSCSI} = &gui_new_menu_item('_SCSI Controller', 'scsi_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddSATA} = &gui_new_menu_item('SA_TA Controller', 'sata_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddSAS} = &gui_new_menu_item('S_AS Controller', 'sata_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddFloppy} = &gui_new_menu_item('_Floppy Controller', 'floppy_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddUSB} = &gui_new_menu_item('_USB Controller', 'usb_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddNVMe} = &gui_new_menu_item('_NVMe (PCIe) Controller', 'nvme_add_16px.png', $gui{menuCtrAdd});
$gui{miCtrAddVirtioSCSI} = &gui_new_menu_item('_Virtio-SCSI Controller', 'virtio_scsi_add_16px.png', $gui{menuCtrAdd});
#
$gui{menuStop} = &gui_new_menu();
$gui{miStopPower} = &gui_new_menu_item('Instant _Power Off', 'vm_poweroff_16px.png', $gui{menuStop});
$gui{miStopACPI} = &gui_new_menu_item('_ACPI Shutdown', 'vm_shutdown_16px.png', $gui{menuStop});
$gui{miStopSave} = &gui_new_menu_item('_Save State', 'vm_save_state_16px.png', $gui{menuStop});
#
$gui{menuKeyboardMini} = &gui_new_menu();
$gui{menuRDPPreset} = &gui_new_menu();
$gui{menuVNCPreset} = &gui_new_menu();
#
$gui{menuFile} = &gui_new_menu();
$gui{miConnect} = &gui_new_menu_item('_Connect to VirtualBox', 'connect_16px.png', $gui{menuFile});
$gui{miProfiles} = &gui_new_menu_item('Connection P_rofiles', 'profile_16px.png', $gui{menuFile});
$gui{miImportAppl} = &gui_new_menu_item('_Import Appliance', 'import_16px.png', $gui{menuFile});
$gui{miExportAppl} = &gui_new_menu_item('_Export Appliance', 'export_16px.png', $gui{menuFile});
$gui{miVMM} = &gui_new_menu_item('_Virtual Media Manager', 'media_manager_16px.png', $gui{menuFile});
$gui{miHostNetMan} = &gui_new_menu_item('_Host Network Manager', 'host_iface_manager_16px.png', $gui{menuFile});
$gui{miServerInfo} = &gui_new_menu_item('_Server Information', 'session_info_16px.png', $gui{menuFile});
$gui{miPrefs} = &gui_new_menu_item('RemoteBox _Preferences', 'rb_settings_16px.png', $gui{menuFile});
$gui{miVBPrefs} = &gui_new_menu_item('Virtual_Box Preferences', 'global_settings_16px.png', $gui{menuFile});
$gui{menuFile}->append(&gui_new_menu_sep());
$gui{miQuit} = &gui_new_menu_item('_Quit', 'close_16px.png', $gui{menuFile});
$gui{menuitemFile}->set_submenu($gui{menuFile});
#
$gui{menuScreenshot} = &gui_new_menu();
$gui{miScreenshotsavepng} = &gui_new_menu_item('Save _PNG screenshot...', 'screenshot_take_16px.png', $gui{menuScreenshot});
$gui{miScreenshotIcon} = &gui_new_menu_item('_Set screenshot as icon', 'screenshot_take_16px.png', $gui{menuScreenshot});
$gui{miScreenshotReset} = &gui_new_menu_item('_Reset guest icon', 'reset_scrshot_16px.png', $gui{menuScreenshot});
#
$gui{menuDisplay} = &gui_new_menu();
$gui{miRemoteDisplay} = &gui_new_menu_item('_Open Guest Display', 'vrdp_16px.png', $gui{menuDisplay});
$gui{miSetVideo} = &gui_new_menu_item('Resolution Hint', 'vrdp_16px.png', $gui{menuDisplay}); # Has a sub-menu
#
$gui{menuSetVideo} = &gui_new_menu();
$gui{miSetVideoCustom} = &gui_new_menu_item('_Custom', 'vrdp_16px.png', $gui{menuSetVideo});
$gui{miSetVideo}->set_submenu($gui{menuSetVideo});
# Populate the submenu for the screensize video hinting
my $scr_res_tbl = &get_scr_res_tbl();

foreach my $res (@{$scr_res_tbl}) {
    $gui{'miSetVideo' . "$$res{w}_$$res{h}"} = &gui_new_menu_item($$res{w} . 'x' . $$res{h} . ":32 ($$res{aspx}:$$res{aspy})", 'vrdp_16px.png', $gui{menuSetVideo});
    $gui{'miSetVideo' . "$$res{w}_$$res{h}"}->signal_connect('activate' => \&send_video_hint, [$$res{w}, $$res{h}, 32]);
    $gui{'miSetVideo' . "$$res{w}_$$res{h}"}->set_tooltip_text('Requires a minimum of ' . &vram_needed($$res{w}, $$res{h}, 32) . 'MB of video memory assigned to the guest');
}
#
$gui{menuKeyboard} = &gui_new_menu();
$gui{miKeyboardCAF} = &gui_new_menu_item('Ctrl-Alt-F...', 'keyboard_16px.png', $gui{menuKeyboard}); # Has sub menu
$gui{miKeyboardASF} = &gui_new_menu_item('Alt-Sysrq+...', 'keyboard_16px.png', $gui{menuKeyboard}); # Has sub menu
$gui{menuKeyboardCAF} = &gui_new_menu();
$gui{miKeyboardCAF}->set_submenu($gui{menuKeyboardCAF});
$gui{menuKeyboardASF} = &gui_new_menu();
$gui{miKeyboardASF}->set_submenu($gui{menuKeyboardASF});
# Populate the keyboard sequence menus
my $cafx_code_tbl = &get_cafx_code_tbl();

foreach my $code (@{$cafx_code_tbl}) {
    $gui{'miKeyboard' . $$code{desc}} = &gui_new_menu_item($$code{desc}, 'keyboard_16px.png', $gui{menuKeyboardCAF});
    $gui{'miKeyboard' . $$code{desc}}->signal_connect('activate' => \&keyboard_send, $code);
}

my $asfx_code_tbl = &get_asfx_code_tbl();

foreach my $code (@{$asfx_code_tbl}) {
    $gui{'miKeyboard' . $$code{desc}} = &gui_new_menu_item($$code{desc}, 'keyboard_16px.png', $gui{menuKeyboardASF});
    $gui{'miKeyboard' . $$code{desc}}->signal_connect('activate' => \&keyboard_send, $code);
}

$gui{miKeyboardCAD} = &gui_new_menu_item('Ctrl-Alt-Del', 'keyboard_16px.png', $gui{menuKeyboard});
$gui{miKeyboardCAD}->signal_connect(activate => \&keyboard_CAD);
my $misc_code_tbl = &get_misc_code_tbl();

foreach my $code (@{$misc_code_tbl}) {
    $gui{'miKeyboard' . $$code{desc}} = &gui_new_menu_item($$code{desc}, 'keyboard_16px.png', $gui{menuKeyboard});
    $gui{'miKeyboard' . $$code{desc}}->signal_connect('activate' => \&keyboard_send, $code);
    $gui{'miKeyboardMini' . $$code{desc}} = &gui_new_menu_item($$code{desc}, 'keyboard_16px.png', $gui{menuKeyboardMini});
    $gui{'miKeyboardMini' . $$code{desc}}->signal_connect('activate' => \&keyboard_send, $code);
}

$gui{miKeyboardRK} = &gui_new_menu_item('Release Keys', 'keyboard_16px.png', $gui{menuKeyboard});
$gui{miKeyboardRK}->signal_connect('activate' => \&keyboard_releasekeys);
#
$gui{menuMachine} = &gui_new_menu();
$gui{miNew} = &gui_new_menu_item('_New Guest', 'vm_new_16px.png', $gui{menuMachine});
$gui{miAdd} = &gui_new_menu_item('_Add Guest', 'vm_add_16px.png', $gui{menuMachine});
$gui{miSettings} = &gui_new_menu_item('_Settings', 'vm_settings_16px.png', $gui{menuMachine});
$gui{miClone} = &gui_new_menu_item('Cl_one', 'vm_clone_16px.png', $gui{menuMachine});
$gui{miRemove} = &gui_new_menu_item('_Remove', 'delete_16px.png', $gui{menuMachine});
$gui{miSetGroup} = &gui_new_menu_item('Set _Group', 'vm_group_name_16px.png', $gui{menuMachine});
$gui{miUngroup} = &gui_new_menu_item('_Ungroup', 'vm_group_remove_16px.png', $gui{menuMachine});
$gui{menuMachine}->append(&gui_new_menu_sep());
$gui{miScreenshot} = &gui_new_menu_item('Screenshot', 'screenshot_take_16px.png', $gui{menuMachine}); # Has a sub menu
$gui{miScreenshot}->set_submenu($gui{menuScreenshot});
$gui{miLogs} = &gui_new_menu_item('Show Guest _Logs', 'show_logs_16px.png', $gui{menuMachine});
$gui{menuitemMachine}->set_submenu($gui{menuMachine});
#
$gui{menuAction} = &gui_new_menu();
$gui{miStart} = &gui_new_menu_item('_Start', 'vm_start_16px.png', $gui{menuAction});
$gui{miStop} = &gui_new_menu_item('Stop', 'state_aborted_16px.png', $gui{menuAction}); # Has a sub menu
$gui{miPause} = &gui_new_menu_item('_Pause', 'vm_pause_16px.png', $gui{menuAction});
$gui{miResume} = &gui_new_menu_item('Res_ume', 'vm_start_16px.png', $gui{menuAction});
$gui{miDiscard} = &gui_new_menu_item('_Discard Saved State', 'vm_discard_16px.png', $gui{menuAction});
$gui{miReset} = &gui_new_menu_item('_Reset', 'vm_reset_16px.png', $gui{menuAction});
$gui{menuMainStop} = &gui_new_menu();
$gui{miPower} = &gui_new_menu_item('Instant _Power Off', 'vm_poweroff_16px.png', $gui{menuMainStop});
$gui{miACPI} = &gui_new_menu_item('_ACPI Shutdown', 'vm_shutdown_16px.png', $gui{menuMainStop});
$gui{miSave} = &gui_new_menu_item('_Save State', 'vm_save_state_16px.png', $gui{menuMainStop});
$gui{miStop}->set_submenu($gui{menuMainStop});
$gui{miAction}->set_submenu($gui{menuAction});
#
$gui{menuDevices} = &gui_new_menu();
$gui{miDisplay} = &gui_new_menu_item('Display', 'vrdp_16px.png', $gui{menuDevices});
$gui{miDisplay}->set_submenu($gui{menuDisplay}); # Has a sub menu
$gui{miKeyboard} = &gui_new_menu_item('Keyboard', 'keyboard_16px.png', $gui{menuDevices}); # Has a sub menu
$gui{miKeyboard}->set_submenu($gui{menuKeyboard});
$gui{miFloppy} = &gui_new_menu_item('Change _Floppy...', 'fd_16px.png', $gui{menuDevices}); # Has a dynamic sub menu
$gui{miFloppy}->set_submenu(&gui_new_menu()); # This menu is not used, but hints for GTK. We attach one later
$gui{miDVD} = &gui_new_menu_item('Change _Optical Disc...', 'cd_16px.png', $gui{menuDevices}); # Has a dynamic sub menu
$gui{miDVD}->set_submenu(&gui_new_menu()); # This menu is not used, but hints for GTK. We attach one later
$gui{miUSB} = &gui_new_menu_item('HotPlug _USB Device...', 'usb_16px.png', $gui{menuDevices}); # Has a dynamic sub menu
$gui{miUSB}->set_submenu(&gui_new_menu()); # This menu is not used, but hints for GTK. We attach one later
$gui{miHotPlugCPU} = &gui_new_menu_item('HotPlug _CPU...', 'cpu_16px.png', $gui{menuDevices}); # Has a dynamic sub menu
$gui{miHotPlugCPU}->set_submenu(&gui_new_menu()); # This menu is not used, but hints for GTK. We attach one later
$gui{miDevices}->set_submenu($gui{menuDevices});
#
$gui{menuHelp} = &gui_new_menu();
$gui{miAbout} = &gui_new_menu_item('_About', 'session_info_16px.png', $gui{menuHelp});
$gui{menuitemHelp}->set_submenu($gui{menuHelp});

# We have to register signals manually, which we want to block at some point because we need the sigids
# as blocking any other way is not supported in perl-gtk (other blocking funcs map to null funcs)
our %signal = (buttonCreateCopyChooser_clicked          => $gui{buttonCreateCopyChooser}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Destination Hard Disk Image', entrywidget => \$gui{entryCopyHDName}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               buttonCreateFloppyChooseLoc_clicked      => $gui{buttonCreateFloppyChooseLoc}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Destination Floppy Image', entrywidget => \$gui{entryCreateFloppyName}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               buttonCreateHDChooseLoc_clicked          => $gui{buttonCreateHDChooseLoc}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Destination Hard Disk Image', entrywidget => \$gui{entryCreateHDName}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               buttonEditDispCapturePath_clicked        => $gui{buttonEditDispCapturePath}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Capture File', entrywidget => \$gui{entryEditDispCapturePath}, mode => 'file', filter => '.*', callback => \&handle_videofilechooser}),
               buttonEditGenSnapFolder_clicked          => $gui{buttonEditGenSnapFolder}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Snapshot Folder', entrywidget => \$gui{entryEditGenSnapFolder}, mode => 'dir', filter => ' ^', callback => \&handle_snapshotfolderchooser}),
               buttonEditSysLogoPath_clicked            => $gui{buttonEditSysLogoPath}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose BIOS Logo', entrywidget => \$gui{entryEditSysLogoPath}, mode => 'file', filter => '^.*\.bmp$', callback => \&handle_bioslogofilechooser}),
               buttonEditSysResetBootKeys               => $gui{buttonEditSysResetBootKeys}->signal_connect('released' => \&sys_mother_reset_boot_keys),
               buttonEditUSBAdd_buttonReleaseEvent      => $gui{buttonEditUSBAdd}->signal_connect('button-release-event' => sub { $gui{menuUSB}->popup(undef, undef, undef, undef, 0, $_[1]->time) if ($_[1]->button == 1); }),
               buttonExportApplFile_clicked             => $gui{buttonExportApplFile}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Export Appliance File', entrywidget => \$gui{entryExportApplFile}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               buttonImportApplChoose_clicked           => $gui{buttonImportApplChoose}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Import Appliance File', entrywidget => \$gui{entryImportApplFile}, mode => 'file', filter => '^.*\.ova$|^.*\.ovf$|^.*\.tar\.gz$|^.*\.tgz$', callback => \&handle_remote_file_entry}),
               buttonMoveMediumChooser_clicked          => $gui{buttonMoveMediumChooser}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Destination Medium', entrywidget => \$gui{entryMoveMediumTo}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               buttonPFRulesAdd4_clicked                => $gui{buttonPFRulesAdd4}->signal_connect('clicked' => \&show_dialog_pf4, 'ADD'),
               buttonPFRulesAdd6_clicked                => $gui{buttonPFRulesAdd6}->signal_connect('clicked' => \&show_dialog_pf6, 'ADD'),
               buttonPFRulesEdit4_clicked               => $gui{buttonPFRulesEdit4}->signal_connect('clicked' => \&show_dialog_pf4, 'EDIT'),
               buttonPFRulesEdit6_clicked               => $gui{buttonPFRulesEdit6}->signal_connect('clicked' => \&show_dialog_pf6, 'EDIT'),
               buttonPFRulesRemove4_clicked             => $gui{buttonPFRulesRemove4}->signal_connect('clicked' => \&remove_pf_rule4),
               buttonPFRulesRemove6_clicked             => $gui{buttonPFRulesRemove6}->signal_connect('clicked' => \&remove_pf_rule6),
               buttonSharedFolderChoose_clicked  => $gui{buttonSharedFolderChoose}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Shared Folder', entrywidget => \$gui{entrySharedFolderPath}, mode => 'dir', filter => ' ^', callback => \&handle_remote_folder_entry}),
               buttonVBPrefsGenAutostartDBFolder_clicked => $gui{buttonVBPrefsGenAutostartDBFolder}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Autostart Database Folder', entrywidget => \$gui{entryVBPrefsGenAutostartDBFolder}, mode => 'dir', filter => ' ^', callback => \&handle_remote_folder_entry}),
               buttonVBPrefsGenMachineFolderChoose_clicked  => $gui{buttonVBPrefsGenMachineFolderChoose}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Machine Folder', entrywidget => \$gui{entryVBPrefsGenMachineFolder}, mode => 'dir', filter => ' ^', callback => \&handle_remote_folder_entry}),
               buttonVMMCopyFloppyChooser_clicked       => $gui{buttonVMMCopyFloppyChooser}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Destination Floppy Image', entrywidget => \$gui{entryVMMCopyFloppyName}, mode => 'file', filter => '.*', callback => \&handle_remote_file_entry}),
               checkbuttonEditSysSecureBoot_toggled     => $gui{checkbuttonEditSysSecureBoot}->signal_connect('toggled' => \&sys_mother_secureboot),
               checkbuttonEditUSBEnable_toggled         => $gui{checkbuttonEditUSBEnable}->signal_connect('toggled' => \&usb_toggle),
               comboboxConnectProfile_changed           => $gui{comboboxConnectProfile}->signal_connect('changed' => \&select_profile),
               comboboxCopyHDFormat_changed             => $gui{comboboxCopyHDFormat}->signal_connect('changed' => \&sens_copyhdformat),
               comboboxCreateHDFormat_changed           => $gui{comboboxCreateHDFormat}->signal_connect('changed' => \&storage_sens_create_hd),
               comboboxCustomVideoD_changed             => $gui{comboboxCustomVideoD}->signal_connect('changed' => \&update_vidmeminfo),
               comboboxDispAuthMeth_changed             => $gui{comboboxDispAuthMeth}->signal_connect('changed' => \&disp_rem_auth),
               comboboxEditAudioCodec_changed           => $gui{comboboxEditAudioCodec}->signal_connect('changed' => \&audio_codec),
               comboboxEditAudioCtr_changed             => $gui{comboboxEditAudioCtr}->signal_connect('changed' => \&audio_ctr),
               comboboxEditAudioDriver_changed          => $gui{comboboxEditAudioDriver}->signal_connect('changed' => \&audio_driver),
               comboboxEditDispAudioQuality_changed     => $gui{comboboxEditDispAudioQuality}->signal_connect('changed' => \&disp_cap_audio_quality),
               comboboxEditDispCaptureMode_changed      => $gui{comboboxEditDispCaptureMode}->signal_connect('changed' => \&disp_cap_mode),
               comboboxEditDispCaptureSize_changed      => $gui{comboboxEditDispCaptureSize}->signal_connect('changed' => \&disp_cap_size),
               comboboxEditDispVGA_changed              => $gui{comboboxEditDispVGA}->signal_connect('changed' => \&disp_scr_VGA),
               comboboxEditGenAutostop_changed          => $gui{comboboxEditGenAutostop}->signal_connect('changed' => \&gen_adv_autostop_mode),
               comboboxEditGenClip_changed              => $gui{comboboxEditGenClip}->signal_connect('changed' => \&gen_adv_clipboard),
               comboboxEditGenOSFam_changed             => $gui{comboboxEditGenOSFam}->signal_connect('changed' => \&gen_basic_os_family, $gui{comboboxEditGenOSVer}),
               comboboxEditGenOSVer_changed             => $gui{comboboxEditGenOSVer}->signal_connect('changed' => \&gen_basic_os_version, $gui{comboboxEditGenOSFam}),
               comboboxEditIOSelectedSerial_changed     => $gui{comboboxEditIOSelectedSerial}->signal_connect('changed' => \&init_edit_io_serial),
               comboboxEditNetAttach_changed            => $gui{comboboxEditNetAttach}->signal_connect('changed' => \&net_attach, $gui{checkbuttonEditNetEnable}),
               comboboxEditNetName_changed              => $gui{comboboxEditNetName}->signal_connect('changed' => \&net_name, $gui{checkbuttonEditNetEnable}),
               comboboxEditNetPromiscuous_changed       => $gui{comboboxEditNetPromiscuous}->signal_connect('changed' => \&net_promiscuous),
               comboboxEditNetSelectedAdapter_changed   => $gui{comboboxEditNetSelectedAdapter}->signal_connect('changed' => \&init_edit_network),
               comboboxEditNetType_changed              => $gui{comboboxEditNetType}->signal_connect('changed' => \&net_adapter_type, $gui{checkbuttonEditNetEnable}),
               comboboxEditParallelPortNum_changed      => $gui{comboboxEditParallelPortNum}->signal_connect('changed' => \&io_par_num),
               comboboxEditSerialMode_changed           => $gui{comboboxEditSerialMode}->signal_connect('changed' => \&io_ser_mode),
               comboboxEditSerialPortNum_changed        => $gui{comboboxEditSerialPortNum}->signal_connect('changed' => \&io_ser_num),
               comboboxEditSerialUART_changed           => $gui{comboboxEditSerialUART}->signal_connect('changed' => \&io_ser_uart),
               comboboxEditStorCtrType_changed          => $gui{comboboxEditStorCtrType}->signal_connect('changed' => \&storage_ctr_type),
               comboboxEditStorFloppyType_changed       => $gui{comboboxEditStorFloppyType}->signal_connect('changed' => \&storage_floppy_type),
               comboboxEditSysChipset_changed           => $gui{comboboxEditSysChipset}->signal_connect('changed' => \&sys_mother_chipset),
               comboboxEditSysKeyboard_changed          => $gui{comboboxEditSysKeyboard}->signal_connect('changed' => \&sys_mother_keyboard),
               comboboxEditSysParavirt_changed          => $gui{comboboxEditSysParavirt}->signal_connect('changed' => \&sys_accel_paravirt),
               comboboxEditSysPointing_changed          => $gui{comboboxEditSysPointing}->signal_connect('changed' => \&sys_mother_pointer),
               comboboxEditSysTPM_changed               => $gui{comboboxEditSysTPM}->signal_connect('changed' => \&sys_mother_tpm),
               comboboxentryEditNetGenDriver_changed    => $gui{comboboxentryEditNetGenDriver}->signal_connect('changed' => \&net_generic_driver, $gui{checkbuttonEditNetEnable}),
               comboboxentryEditNetNameInt_changed      => $gui{comboboxentryEditNetNameInt}->signal_connect('changed' => \&net_name_internal, $gui{checkbuttonEditNetEnable}),
               comboboxNewNewFormat_changed             => $gui{comboboxNewNewFormat}->signal_connect('changed' => \&sens_hdformatchanged),
               comboboxNewOSFam_changed                 => $gui{comboboxNewOSFam}->signal_connect('changed' => \&newgen_osfam, $gui{comboboxNewOSVer}),
               comboboxNewOSVer_changed                 => $gui{comboboxNewOSVer}->signal_connect('changed' => \&newgen_osver, $gui{comboboxNewOSFam}),
               crndrtoggleEditSysBootEnabled_toggled    => $gui{crndrtoggleEditSysBootEnabled}->signal_connect('toggled' => \&sys_mother_boot_dev_toggle),
               crndrtoggleEditUSBEnabled_toggled        => $gui{crndrtoggleEditUSBEnabled}->signal_connect('toggled' => \&usb_toggle_filter),
               crndrtoggleVBPrefsNATEnabled_toggled     => $gui{crndrtoggleVBPrefsNATEnabled}->signal_connect('toggled' => \&vbprefs_togglenat),
               entryEditGenSnapFolder_activate          => $gui{entryEditGenSnapFolder}->signal_connect('activate' => \&gen_snapfolder),
               entryEditGenSnapFolder_focus             => $gui{entryEditGenSnapFolder}->signal_connect('focus' => \&gen_snapfolder),
               hscaleEditSysProcessorCap_formatValue    => $gui{hscaleEditSysProcessorCap}->signal_connect('format-value' => sub { return " $_[1]% Max"; }), # Formats the slider for the execution cap
               hscaleEditSysProcessorCap_valueChanged   => $gui{hscaleEditSysProcessorCap}->signal_connect('value-changed' => \&sys_proc_cap),
               hscaleEditSysProcessor_formatValue       => $gui{hscaleEditSysProcessor}->signal_connect('format-value' => sub { return " $_[1] vCPUs"; }), # Formats the slider value for the processors
               hscaleEditSysProcessor_valueChanged      => $gui{hscaleEditSysProcessor}->signal_connect('value-changed' => \&sys_proc_count),
               miAbout_activate                         => $gui{miAbout}->signal_connect('activate' => \&show_dialog_about),
               miACPI_activate                          => $gui{miACPI}->signal_connect('activate' => \&stop_guest_acpi),
               miAdd_activate                           => $gui{miAdd}->signal_connect('activate' => \&show_remote_filechooser, {title => 'Choose Guest VBox File', entrywidget => '', mode => 'file', filter => '^.*\.vbox$', callback => \&handle_vboxfilechooser}),
               miClone_activate                         => $gui{miClone}->signal_connect('activate' => \&show_dialog_clone),
               miConnect_activate                       => $gui{miConnect}->signal_connect('activate' => \&show_dialog_connect),
               miCtrAddFloppy_activate                  => $gui{miCtrAddFloppy}->signal_connect('activate' => \&storage_ctr_add, 'Floppy'),
               miCtrAddIDE_activate                     => $gui{miCtrAddIDE}->signal_connect('activate' => \&storage_ctr_add, 'IDE'),
               miCtrAddNVMe_activate                    => $gui{miCtrAddNVMe}->signal_connect('activate' => \&storage_ctr_add, 'PCIe'),
               miCtrAddSASactivate                      => $gui{miCtrAddSAS}->signal_connect('activate' => \&storage_ctr_add, 'SAS'),
               miCtrAddSATA_activate                    => $gui{miCtrAddSATA}->signal_connect('activate' => \&storage_ctr_add, 'SATA'),
               miCtrAddSCSI_activate                    => $gui{miCtrAddSCSI}->signal_connect('activate' => \&storage_ctr_add, 'SCSI'),
               miCtrAddUSB_activate                     => $gui{miCtrAddUSB}->signal_connect('activate' => \&storage_ctr_add, 'USB'),
               miCtrAddVirtioSCSI_activate              => $gui{miCtrAddVirtioSCSI}->signal_connect('activate' => \&storage_ctr_add, 'VirtioSCSI'),
               miDiscard_activate                       => $gui{miDiscard}->signal_connect('activate' => \&discard_saved_state),
               miDVD_activate                           => $gui{miDVD}->signal_connect('activate' => \&fill_menu_optical),
               miExportAppl_activate                    => $gui{miExportAppl}->signal_connect('activate' => \&show_dialog_exportappl),
               miFloppy_activate                        => $gui{miFloppy}->signal_connect('activate' => \&fill_menu_floppy),
               miHostNetMan_activate                    => $gui{miHostNetMan}->signal_connect('activate' => \&show_dialog_hostnetman),
               miHotPlugCPU_activate                    => $gui{miHotPlugCPU}->signal_connect('activate' => \&fill_menu_cpu),
               miImportAppl_activate                    => $gui{miImportAppl}->signal_connect('activate' => \&show_dialog_importappl),
               miLogs_activate                          => $gui{miLogs}->signal_connect('activate' => \&show_dialog_log),
               miNew_activate                           => $gui{miNew}->signal_connect('activate' => \&show_dialog_new_guest),
               miPause_activate                         => $gui{miPause}->signal_connect('activate' => \&pause_guest),
               miPower_activate                         => $gui{miPower}->signal_connect('activate' => \&stop_guest_poweroff),
               miPrefs_activate                         => $gui{miPrefs}->signal_connect('activate' => \&show_dialog_prefs),
               miProfiles_activate                      => $gui{miProfiles}->signal_connect('activate' => \&show_dialog_profiles),
               miQuit_activate                          => $gui{miQuit}->signal_connect('activate' => \&quit_remotebox),
               miRemoteDisplay_activate                 => $gui{miRemoteDisplay}->signal_connect('activate' => \&open_remote_display),
               miRemove_activate                        => $gui{miRemove}->signal_connect('activate' => \&remove_guest),
               miReset_activate                         => $gui{miSave}->signal_connect('activate' => \&reset_guest),
               miResume_activate                        => $gui{miResume}->signal_connect('activate' => \&resume_guest),
               miSave_activate                          => $gui{miSave}->signal_connect('activate' => \&stop_guest_savestate),
               miScreenshotIcon_activate                => $gui{miScreenshotIcon}->signal_connect('activate' => \&screenshot_to_icon),
               miScreenshotReset_activate               => $gui{miScreenshotReset}->signal_connect('activate' => \&reset_icon),
               miScreenshotsavepng_activate             => $gui{miScreenshotsavepng}->signal_connect('activate' => \&screenshot),
               miServerInfo_activate                    => $gui{miServerInfo}->signal_connect('activate' => \&show_dialog_serverinfo),
               miSetGroup_activate                      => $gui{miSetGroup}->signal_connect('activate' => \&show_dialog_group),
               miSettings_activate                      => $gui{miSettings}->signal_connect('activate' => \&show_dialog_edit),
               miSetVideoCustom_activate                => $gui{miSetVideoCustom}->signal_connect('activate' => \&send_video_hint),
               miStart_activate                         => $gui{miStart}->signal_connect('activate' => \&start_guest),
               miStopACPI_activate                      => $gui{miStopACPI}->signal_connect('activate' => \&stop_guest_acpi),
               miStopPower_activate                     => $gui{miStopPower}->signal_connect('activate' => \&stop_guest_poweroff),
               miStopSave_activate                      => $gui{miStopSave}->signal_connect('activate' => \&stop_guest_savestate),
               miUngroup_activate                       => $gui{miUngroup}->signal_connect('activate' => \&clear_group),
               miUSB_activate                           => $gui{miUSB}->signal_connect('activate' => \&fill_menu_usb),
               miVBPrefs_activate                       => $gui{miVBPrefs}->signal_connect('activate' => \&show_dialog_vbprefs),
               miVMM_activate                           => $gui{miVMM}->signal_connect('activate' => \&show_dialog_vmm),
               sbEditDispCaptureFPS_valueChanged        => $gui{sbEditDispCaptureFPS}->signal_connect('value-changed' => \&disp_cap_fps),
               sbEditDispCaptureQuality_valueChanged    => $gui{sbEditDispCaptureQuality}->signal_connect('value-changed' => \&disp_cap_vidrate),
               sbEditDispCaptureSizeH_valueChanged      => $gui{sbEditDispCaptureSizeH}->signal_connect('value-changed' => \&disp_cap_size_h),
               sbEditDispCaptureSizeW_valueChanged      => $gui{sbEditDispCaptureSizeW}->signal_connect('value-changed' => \&disp_cap_size_w),
               sbEditGenAutostartDelay_valueChanged     => $gui{sbEditGenAutostartDelay}->signal_connect('value-changed' => \&gen_adv_autostart_delay),
               spinbuttonCreateHDSize_input             => $gui{spinbuttonCreateHDSize}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonCreateHDSize_output            => $gui{spinbuttonCreateHDSize}->signal_connect('output' => \&spinbox_bytes_out),
               spinbuttonCustomVideoH_valueChanged      => $gui{spinbuttonCustomVideoH}->signal_connect('value-changed' => \&update_vidmeminfo),
               spinbuttonCustomVideoW_valueChanged      => $gui{spinbuttonCustomVideoW}->signal_connect('value-changed' => \&update_vidmeminfo),
               spinbuttonEditDispAuthTime_input         => $gui{spinbuttonEditDispAuthTime}->signal_connect('input' => \&spinbox_time_in),
               spinbuttonEditDispAuthTime_output        => $gui{spinbuttonEditDispAuthTime}->signal_connect('output' => \&spinbox_time_out),
               spinbuttonEditDispAuthTime_valueChanged  => $gui{spinbuttonEditDispAuthTime}->signal_connect('value-changed' => \&disp_rem_timeout),
               spinbuttonEditDispMonitor_valueChanged   => $gui{spinbuttonEditDispMonitor}->signal_connect('value-changed' => \&disp_scr_monitors),
               spinbuttonEditDispVidMem_input           => $gui{spinbuttonEditDispVidMem}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonEditDispVidMem_output          => $gui{spinbuttonEditDispVidMem}->signal_connect('output' => \&spinbox_bytes_out),
               spinbuttonEditDispVidMem_valueChanged    => $gui{spinbuttonEditDispVidMem}->signal_connect('value-changed' => \&disp_scr_vid_mem),
               spinbuttonEditStorPortCount_valueChanged => $gui{spinbuttonEditStorPortCount}->signal_connect('value-changed' => \&storage_port_count),
               spinbuttonEditSysLogoTime_input          => $gui{spinbuttonEditSysLogoTime}->signal_connect('input' => \&spinbox_time_in),
               spinbuttonEditSysLogoTime_output         => $gui{spinbuttonEditSysLogoTime}->signal_connect('output' => \&spinbox_time_out),
               spinbuttonEditSysLogoTime_valueChanged   => $gui{spinbuttonEditSysLogoTime}->signal_connect('value-changed' => \&sys_logo_disp_time),
               spinbuttonEditSysMem_input               => $gui{spinbuttonEditSysMem}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonEditSysMem_output              => $gui{spinbuttonEditSysMem}->signal_connect('output' => \&spinbox_bytes_out),
               spinbuttonEditSysMem_valueChanged        => $gui{spinbuttonEditSysMem}->signal_connect('value-changed' => \&sys_mother_mem),
               spinbuttonEditSysTimeOffset_input        => $gui{spinbuttonEditSysTimeOffset}->signal_connect('input' => \&spinbox_time_in),
               spinbuttonEditSysTimeOffset_output       => $gui{spinbuttonEditSysTimeOffset}->signal_connect('output' => \&spinbox_time_out),
               spinbuttonEditSysTimeOffset_valueChanged => $gui{spinbuttonEditSysTimeOffset}->signal_connect('value-changed' => \&sys_adv_time_offset),
               spinbuttonNewMemory_input                => $gui{spinbuttonNewMemory}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonNewMemory_output               => $gui{spinbuttonNewMemory}->signal_connect('output' => \&spinbox_bytes_out),
               spinbuttonNewNewHDSize_input             => $gui{spinbuttonNewNewHDSize}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonNewNewHDSize_output            => $gui{spinbuttonNewNewHDSize}->signal_connect('output' => \&spinbox_bytes_out),
               spinbuttonVMMModifyResizeHD_input        => $gui{spinbuttonVMMModifyResizeHD}->signal_connect('input' => \&spinbox_bytes_in),
               spinbuttonVMMModifyResizeHD_output       => $gui{spinbuttonVMMModifyResizeHD}->signal_connect('output' => \&spinbox_bytes_out),
               textviewEditGenDescription_focusOutEvent => $gui{textviewEditGenDescription}->signal_connect('focus-out-event' => \&gen_description),
               textviewEditGenDescription_focusOutEvent => $gui{textviewEditGenDescription}->signal_connect('focus-out-event' => \&gen_description),
               textviewEditNetGeneric_focusOutEvent     => $gui{textviewEditNetGeneric}->signal_connect('focus-out-event' => \&net_generic_properties),
               toolbuttonVMMAdd_clicked                 => $gui{toolbuttonVMMAdd}->signal_connect('clicked' => \&show_remote_filechooser, {title => 'Choose Media Images', entrywidget => '', mode => 'multifile', filter => '.*', callback => \&vmm_add}),
               treeviewConnectionProfiles_cursorChanged => $gui{treeviewConnectionProfiles}->signal_connect('cursor-changed' => \&onsel_list_profile),
               treeviewDetails_rowCollapsed             => $gui{treeviewDetails}->signal_connect('row-collapsed' => \&collapse_details_row),
               treeviewDetails_rowExpanded              => $gui{treeviewDetails}->signal_connect('row-expanded' => \&expand_details_row),
               treeviewEditShared_cursorChanged         => $gui{treeviewEditShared}->signal_connect('cursor-changed' => \&onsel_list_shared),
               treeviewEditShared_rowActivated          => $gui{treeviewEditShared}->signal_connect('row-activated' => \&show_dialog_shared),
               treeviewEditStor_cursorChanged           => $gui{treeviewEditStor}->signal_connect('cursor-changed' => \&onsel_list_editstorage),
               treeviewEditSysBoot_cursorChanged1       => $gui{treeviewEditSysBoot}->signal_connect('cursor-changed' => \&sys_mother_boot_order),
               treeviewEditSysBoot_cursorChanged2       => $gui{treeviewEditSysBoot}->signal_connect('cursor-changed' => \&sys_mother_sens_boot_sel),
               treeviewEditUSBFilters_cursorChanged     => $gui{treeviewEditUSBFilters}->signal_connect('cursor-changed' => \&onsel_list_usbfilters),
               treeviewGuest_buttonPressEvent           => $gui{treeviewGuest}->signal_connect('button-press-event' => \&show_rmb_menu),
               treeviewGuest_cursorChanged              => $gui{treeviewGuest}->signal_connect('cursor-changed' => \&onsel_list_guest),
               treeviewGuest_rowActivated               => $gui{treeviewGuest}->signal_connect('row-activated' => \&show_dialog_edit),
               treeviewPFRulesIPv4_cursorChanged        => $gui{treeviewPFRulesIPv4}->signal_connect('cursor-changed' => \&onsel_list_pf4),
               treeviewPFRulesIPv6_cursorChanged        => $gui{treeviewPFRulesIPv6}->signal_connect('cursor-changed' => \&onsel_list_pf6),
               treeviewRemoteFileChooser_cursorChanged  => $gui{treeviewRemoteFileChooser}->signal_connect('cursor-changed' => \&onsel_list_remotefiles_single),
               treeviewRemoteFileChooser_rowActivated   => $gui{treeviewRemoteFileChooser}->signal_connect('row-activated' => \&onsel_list_remotefiles),
               treeviewSnapshots_cursorChanged          => $gui{treeviewSnapshots}->signal_connect('cursor-changed' => \&onsel_list_snapshots),
               treeviewSnapshots_rowActivated           => $gui{treeviewSnapshots}->signal_connect('row-activated' => \&show_dialog_snap_details),
               treeviewVBPrefsHON_cursorChanged         => $gui{treeviewVBPrefsHON}->signal_connect('cursor-changed' => \&onsel_list_vbprefshon),
               treeviewVBPrefsHON_rowActivated          => $gui{treeviewVBPrefsHON}->signal_connect('row-activated' => \&show_dialog_edithon),
               treeviewVBPrefsNAT_cursorChanged         => $gui{treeviewVBPrefsNAT}->signal_connect('cursor-changed' => \&onsel_list_vbprefsnat),
               treeviewVBPrefsNAT_rowActivated          => $gui{treeviewVBPrefsNAT}->signal_connect('row-activated' => \&show_dialog_editnat),
               treeviewVMMDVD_cursorChanged             => $gui{treeviewVMMDVD}->signal_connect('cursor-changed' => \&onsel_list_vmmdvd),
               treeviewVMMFloppy_cursorChanged          => $gui{treeviewVMMFloppy}->signal_connect('cursor-changed' => \&onsel_list_vmmfloppy),
               treeviewVMMFloppy_rowActivated           => $gui{treeviewVMMFloppy}->signal_connect('row-activated' => \&show_dialog_vmm_modify),
               treeviewVMMHD_cursorChanged              => $gui{treeviewVMMHD}->signal_connect('cursor-changed' => \&onsel_list_vmmhd),
               treeviewVMMHD_rowActivated               => $gui{treeviewVMMHD}->signal_connect('row-activated' => \&show_dialog_vmm_modify));


# Work around a bug in Glade that disables toolbutton menus
$gui{toolbuttonStop}->set_menu($gui{menuStop});
$gui{toolbuttonCAD}->set_menu($gui{menuKeyboardMini});

# Work around a bug in Glade. Setting selection mode does not work
$gui{treeviewInfo}->get_selection->set_mode('GTK_SELECTION_NONE');

# Populate the liststore for the framesize for video capture
my $fsiter;

foreach my $res (@{$scr_res_tbl}) {
    $fsiter = $gui{liststoreDispCaptureSize}->append;
    $gui{liststoreDispCaptureSize}->set($fsiter, [0, 1, 2], ["$$res{w}x$$res{h} ($$res{aspx}:$$res{aspy})", $$res{w}, $$res{h}]);
}

# Populate RDP/VNC preset menus
my $rdp_preset_tbl = &get_rdp_preset_tbl();

foreach my $preset (@{$rdp_preset_tbl}) {
    $gui{'miRDPPreset' . $$preset{num}} = &gui_new_menu_item($$preset{desc}, 'vrdp_16px.png', $gui{menuRDPPreset});
    $gui{'miRDPPreset' . $$preset{num}}->signal_connect('activate' => \&set_rdppreset, $$preset{command});
}

my $vnc_preset_tbl = &get_vnc_preset_tbl();

foreach my $preset (@{$vnc_preset_tbl}) {
    $gui{'miVNCPreset' . $$preset{num}} = &gui_new_menu_item($$preset{desc}, 'vrdp_16px.png', $gui{menuVNCPreset});
    $gui{'miVNCPreset' . $$preset{num}}->signal_connect('activate' => \&set_vncpreset, $$preset{command});
}

# Transient Window Handling
# A window's transient is automatically set on open
{
    my @winlist = ($gui{windowMain});

    # Set the transient window's (ie parent window) sensitivity on
    sub transwin_sens_on {
        my ($win) = @_;
        pop @winlist;
        my $transwin = $win->get_transient_for();
        $transwin->set_sensitive(1) if ($transwin);
    }

    # Set the transient window's (ie parent window) sensitivity off
    sub transwin_sens_off {
        my ($win) = @_;
        my $transwin = $winlist[$#winlist]; # Get the last opened window
        push @winlist, $win;
        $win->set_transient_for($transwin) if ($transwin);
        $transwin->set_sensitive(0) if ($transwin);
    }
}

# Ghosts window and optionally sets pointer
sub busy_window {
    my ($window, $sens, $pointer) = @_;
    my $gdkwindow = $window->get_window();
    $window->set_sensitive($sens);
    &set_pointer($window, $pointer);
}

# Set's the style of the mouse pointer
sub set_pointer {
    my ($window, $pointer) = @_;
    my $gdkwindow = $window->get_window();

    # If the window is no visible, gdkwindow is empty, so check.
    if ($gdkwindow) {
        if ($pointer) { $gdkwindow->set_cursor(Gtk3::Gdk::Cursor->new($pointer)); }
        else {$gdkwindow->set_cursor(undef); }
    }
    Gtk3::main_iteration while Gtk3::events_pending;
}

sub handle_bioslogofilechooser {
    my ($basedir, $filename) = @_;
    if ($basedir and $filename) {
        $gui{entryEditSysLogoPath}->set_text(&rcatfile($basedir, $filename));
        &sys_logo_path();
    }
}

sub handle_videofilechooser {
    my ($basedir, $filename) = @_;
    if ($basedir and $filename) {
        $gui{entryEditDispCapturePath}->set_text(&rcatfile($basedir, $filename));
        &disp_cap_path();
    }
}

sub handle_remote_folder_entry {
    my ($basedir, $filearr, $entrywidget) = @_;
    my $file = ${$filearr}[0]->{FileName};
    my $type = ${$filearr}[0]->{Type};

    # Depending on what the user does, there will either be an additional directory
    # to append or not. Type (Dir) already excludes (Parent)
    $basedir = &rcatdir($basedir, $file) if ($file and $type eq '(Dir)');
    $entrywidget->set_text($basedir) if ($basedir and $entrywidget);
}

sub handle_remote_file_entry {
    my ($basedir, $file, $entrywidget) = @_;
    $entrywidget->set_text(&rcatfile($basedir, $file)) if ($basedir and $file and $entrywidget);
}

sub handle_snapshotfolderchooser {
    my ($location, $filearrayref) = @_;
    my $file = ${$filearrayref}[0]->{FileName};
    my $type = ${$filearrayref}[0]->{Type};

    # Depending on what the user does, there will either be an additional directory
    # to append or not. Type (Dir) already excludes (Parent)
    $location = &rcatdir($location, $file) if ($file and $type eq '(Dir)');
    $gui{entryEditGenSnapFolder}->set_text($location) if ($location);
    &gen_snapfolder();
}

sub handle_vboxfilechooser {
    my ($basedir, $filename) = @_;

    if ($basedir and $filename) {
        my $vboxfile = &rcatfile($basedir, $filename);
        my $IMachine = IVirtualBox_openMachine($gui{websn}, $vboxfile);
        if ($IMachine) {
            IVirtualBox_registerMachine($gui{websn}, $IMachine);
            &addrow_msg_log("Imported guest from $vboxfile");
            &fill_list_guest();
        }
        else { &addrow_msg_log("Failed to import guest from $vboxfile"); }
    }
}

sub show_remote_filechooser {
    my ($widget, $data) = @_;
    # Set to the deference entry widget  if it exists or empty
    my $entrywidget = ($$data{entrywidget}) ? ${$$data{entrywidget}} : '';
    my $vhost = &vhost();
    my $basedir;
    $gui{dialogRemoteFileChooser}->set_title($$data{title} . " $endpoint");
    $gui{entryRemoteFileChooserFilter}->set_text($$data{filter});

    if ($$data{mode} eq 'dir') {
        $gui{treeviewRemoteFileChooser}->get_selection->set_mode('GTK_SELECTION_SINGLE');
        $gui{hboxRemoteFileChooserFile}->hide();
        $basedir = $entrywidget->get_text() if ($$data{entrywidget});
    }
    elsif ($$data{mode} eq 'multifile') {
        $gui{treeviewRemoteFileChooser}->get_selection->set_mode('GTK_SELECTION_MULTIPLE');
        $gui{hboxRemoteFileChooserFile}->hide();
        $basedir = $entrywidget->get_text() if ($$data{entrywidget});
    }
    else {
        $gui{treeviewRemoteFileChooser}->get_selection->set_mode('GTK_SELECTION_SINGLE');
        $gui{hboxRemoteFileChooserFile}->show();

        if ($$data{entrywidget}) {
            my ($vol, $dir, $file) = &rsplitpath($entrywidget->get_text());
            $basedir = $vol . $dir;
            $gui{entryRemoteFileChooserFile}->set_text($file) if ($file);
        }
    }

    $basedir = $$vhost{machinedir} unless ($basedir);
    my $IAppliance = IVirtualBox_createAppliance($gui{websn});
    $gui{IVFSExplorer} = IAppliance_createVFSExplorer($IAppliance, "file://$basedir");
    &fill_list_remotefiles($basedir, $$data{filter});
    my $response = $gui{dialogRemoteFileChooser}->run();
    $gui{dialogRemoteFileChooser}->hide();
    IManagedObjectRef_release($gui{IVFSExplorer});
    IManagedObjectRef_release($IAppliance);

    if ($response eq 'ok') {
        my $location = $gui{entryRemoteFileChooserLocation}->get_text();
        my $filename = $gui{entryRemoteFileChooserFile}->get_text();

        if ($$data{mode} eq 'file') {
            &{$$data{callback}}($location, $filename, $entrywidget)
        }
        else {
            my $filearrayref;
            $filearrayref = &getsel_list_remotefiles();
            &{$$data{callback}}($location, $filearrayref, $entrywidget); # Execute the handler
        }
    }

    return $gui{entryRemoteFileChooserLocation}->get_text();
}

# Refreshes the contents of the file chooser
sub refresh_remotefilechooser {
    &fill_list_remotefiles($gui{entryRemoteFileChooserLocation}->get_text(), $gui{entryRemoteFileChooserFilter}->get_text());
}

# Moves to the parent directory in the file chooser
sub cdup_remotefilechooser {
    IVFSExplorer_cdUp($gui{IVFSExplorer});
    &fill_list_remotefiles(IVFSExplorer_getPath($gui{IVFSExplorer}), $gui{entryRemoteFileChooserFilter}->get_text());
}

# Display a progress window for tasks which can take a long time
sub show_progress_window {
    my ($IProgress, $msg, $decal) = @_;
    my $resultcode = 0;
    my $timer = 0;
    $decal ? $gui{imageProgressBig}->set_from_pixbuf($decal) : $gui{imageProgressBig}->set_from_pixbuf($gui{pb}{ProgressSettings});
    $gui{dialogProgress}->set_title($msg);
    $gui{labelProgress}->set_text('Please Wait...'); # Reset text so its not cached from a previous call
    $gui{progressbar}->set_text(''); # Reset text so its not cached from a previous call
    $gui{progressbar}->set_fraction(0); # Reset fraction back to 0
    (IProgress_getCancelable($IProgress) eq 'true') ? $gui{buttonProgressCancel}->show() : $gui{buttonProgressCancel}->hide();
    Gtk3::main_iteration while Gtk3::events_pending;

    $timer = Glib::Timeout->add(1000,
        sub {
            $gui{buttonProgressCancel}->hide() if (IProgress_getCancelable($IProgress) eq 'false'); # Sometimes cancellable earlier but not later on
            my $percent = IProgress_getPercent($IProgress);
            my $secsremaining = IProgress_getTimeRemaining($IProgress);
            $gui{labelProgress}->set_text(IProgress_getOperationDescription($IProgress));
            if (IProgress_getCompleted($IProgress) eq 'true') {
                Glib::Source->remove($timer);
                $timer = 0;
                $gui{progressbar}->set_fraction(1.00);
                $gui{progressbar}->set_text('100%');
                $resultcode = IProgress_getResultCode($IProgress);
                $gui{dialogProgress}->response('ok');
                return 0;
            }
            else {

                $gui{progressbar}->set_fraction($percent * 0.01);
                if ($percent > 10 and $secsremaining > 0) {
                    my $humantime = &secs_to_humantime($secsremaining);
                    $gui{progressbar}->set_text("$percent% (About $humantime remaining)");
                }
                else { $gui{progressbar}->set_text("$percent%"); }
                return 1;
            }
        });

    my $response = $gui{dialogProgress}->run();
    $gui{dialogProgress}->hide();
    Glib::Source->remove($timer) if ($timer);
    IProgress_cancel($IProgress) if ($response ne 'ok');
    Gtk3::main_iteration while Gtk3::events_pending;
    return $resultcode;
}

# Restore RemoteBox's window position to the last save position
sub restore_window_pos {
    my ($winname) = @_;

    if ($prefs{"WINPOS_$winname"}) {
        my ($w, $h, $x, $y) = split ':', $prefs{"WINPOS_$winname"};
        $gui{$winname}->move($x, $y);
        $gui{$winname}->resize($w, $h);
    }
}

# Permit certain chars only for a guest name
sub validate_name {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[\?\/\;\*\\\<\>\|\.]//; # Strip these chars
    return $char, $pos;
}

# Permite certain chats only for group names
sub validate_group {
    my ($entry, $char, $len, $pos) = @_;
    $char = '' if ($char !~ m/[a-z]|[A-Z]|\//); # Strip all which doesn't match this
    return $char, $pos;
}

# Basic character validation for hexadecial
sub validate_hex {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^A-F0-9a-f]//; # Strip everything but these chars
    return $char, $pos;
}

# Basic character validation for a port range
sub validate_port {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^0-9,-]//; # Strip everything but these chars
    return $char, $pos;
}

# Permit only numbers in an entry
sub validate_number {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^0-9]//; # Strip everything but these chars
    return $char, $pos;
}

# Basic character validation for IPv4
sub validate_ipv4 {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^0-9,.]//; # Strip everything but these chars
    return $char, $pos;
}

# Basic character validation for IPv6
sub validate_ipv6 {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^A-F0-9a-f,:]//; # Strip everything but these chars
    return $char, $pos;
}

# Basic character validation for CIDR
sub validate_cidr {
    my ($entry, $char, $len, $pos) = @_;
    $char =~ s/[^0-9,.,\/]//; # Strip everything but these chars
    return $char, $pos;
}

# Validate an IPv4 CIDR
sub valid_cidr {
    return 1 if ($_[0] =~ m/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$/);
}

# Validate an IPv4 Address
sub valid_ipv4 {
    return 1 if ($_[0] =~ m/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/);
}

# FIXME Needs to validate an IPv6 address
sub valid_ipv6 { return 1; }

# Adds appropriate units to a spinbox when specifying memory or disk
sub spinbox_bytes_out {
    my ($widget) = @_;
    my $txt = $widget->get_text();
    my $adjustment = $widget->get_adjustment();
    my $adjval = int($adjustment->get_value());

    if ($adjval < 1024) {
        $adjustment->set_step_increment(1.00);
        $txt = "$adjval MB";
    }
    elsif ($adjval < 1048576) {
        $adjustment->set_step_increment(10.25);
        $adjval /= 1024;
        $txt = sprintf('%0.2f GB', $adjval);
    }
    else {
        $adjustment->set_step_increment(10486);
        $adjval /= 1048576;
        $txt = sprintf('%0.2f TB', $adjval);
    }

    $widget->set_text($txt);
    return 1;
}

# Parses the input and assumes m is mega, g is Giga and t is tera
sub spinbox_bytes_in {
    my ($widget) = @_;
    my $txt = $widget->get_text();

    if ($txt =~ m/m/i) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $widget->get_adjustment->set_value(int($txt)); # Force to be an integer, can't have <1MB
    }
    elsif ($txt =~ m/g/i) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $txt = ($txt * 1024);
        $widget->get_adjustment->set_value($txt);
    }
    elsif ($txt =~ m/t/i) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $txt = ($txt * 1048576);
        $widget->get_adjustment->set_value($txt);
    }

    return 0;
}

sub spinbox_time_in {
    my ($widget) = @_;
    my $txt = $widget->get_text();

    if ($txt =~ m/ms/i) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $widget->get_adjustment->set_value(int($txt));
    }
    elsif ($txt =~ m/sec/i) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $txt = ($txt * 1000);
        $widget->get_adjustment->set_value($txt);
    }
    elsif ($txt =~ m/min/) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $txt =~ s/\.+/\./; # Handle many . here but wont catch 3.5.3.5 for example
        $txt = ($txt * 60000);
        $widget->get_adjustment->set_value($txt);
    }

    return 0;
}

# Adds appropriate units to a spinbox when specifying time
sub spinbox_time_out {
    my ($widget) = @_;
    my $txt = $widget->get_text();
    my $adjustment = $widget->get_adjustment();
    my $adjval = int($adjustment->get_value());

    if ($adjval < 1000) {
        $adjustment->set_step_increment(1.00);
        $txt = "$adjval ms";
    }
    elsif ($adjval < 60000) {
        $adjustment->set_step_increment(10.00);
        $adjval /= 1000;
        $txt = sprintf('%0.2f secs', $adjval);
    }
    else {
        $adjustment->set_step_increment(600.00);
        $adjval /= 60000;
        $txt = sprintf('%0.2f mins', $adjval);
    }

    $widget->set_text($txt);
    return 1;
}

# Adds appropriate units to a spinbox when specifying percent
sub spinbox_pc_out {
    my ($widget) = @_;
    my $adjustment = $widget->get_adjustment();
    my $adjval = int($adjustment->get_value());
    $widget->set_text($adjval . '%');
    return 1;
}

# Handles a percent when specified in a spinbox
sub spinbox_pc_in {
    my ($widget) = @_;
    my $txt = $widget->get_text();

    if ($txt =~ m/\%/) {
        $txt =~ s/[^\d.]//g; # Strip all except digits and .
        $widget->get_adjustment->set_value(int($txt));
    }

    return 0;
}

# Creates an optionally filled liststore, filled if $cols exists and attaches if $parent exists
sub gui_new_lstore {
    my ($parent, $coldef, $cols, $data) = @_;
    my $lstore = Gtk3::ListStore->new($coldef);

    foreach my $row (@{$data}) {
        my $iter = $lstore->append();
        $lstore->set($iter, $cols, $row);
    }

    $parent->set_model($lstore) if ($parent);
    return $lstore;
}

# Creates an empty TreeStore
sub gui_new_tstore {
    my ($parent, $coldef) = @_;
    my $tstore = Gtk3::TreeStore->new($coldef);
    $parent->set_model($tstore) if ($parent);
    return $tstore;
}

# Creates a new dialog window
sub gui_new_dialog {
    my ($title, $transient, $response_ok) = @_;
	my $dialog = Gtk3::Dialog->new();
    $dialog->set_title($title);
    $dialog->set_type_hint('GDK_WINDOW_TYPE_HINT_DIALOG');
    $dialog->set_skip_taskbar_hint(TRUE);
    $dialog->set_transient_for($transient) if ($transient);
    $dialog->set_modal(TRUE);
    $dialog->add_button('OK', 'ok');
    $dialog->set_position('GTK_WIN_POS_CENTER_ON_PARENT');
    $dialog->set_destroy_with_parent(TRUE);
    $dialog->set_mnemonics_visible(TRUE);
    $dialog->set_focus_visible(TRUE);
    $dialog->set_decorated(TRUE);
    $dialog->set_accept_focus(TRUE);
    $dialog->set_icon_name('remotebox'); # We can use from file instead but will need specific OS filenames etc
    $dialog->signal_connect('response' => $response_ok) if $response_ok; # FIXME
    $dialog->set_deletable(TRUE); # Basically tells the WM to show a close button (but some ignore it)
    # Note: After calling this function - we can assign a default widget which is activated with return (set_default)
    # Maybe this should be automatically set to the OK button
    # Do we need to care about set_application?
    return $dialog;
}

sub gui_destroy_dialog {
    my ($widget, $response_id) = @_;
	$widget->destroy();
}

# Create a cell renderer
sub gui_new_cellrenderer {
    my ($type) = @_;
    my $cellrenderer;

    if ($type eq 'toggle') {
        $cellrenderer = Gtk3::CellRendererToggle->new();
    }
    else {
        print("WARNING: No cellrender type $type has been defined\n");
    }

    return $cellrenderer;
}

# Create a textbuffer widget
sub gui_new_textbuffer {
    my ($parent) = @_;
    my $tbuffer = Gtk3::TextBuffer->new();
    $parent->set_buffer($tbuffer) if ($parent);
    return $tbuffer;
}

# Create an image widget from a file
sub gui_new_img_from_file {
    my ($filename, $parent) = @_;
    my $img = Gtk3::Image->new_from_file("$sharedir/icons/$filename");

    if ($parent) {
        if ($parent =~ m/^Gtk3::ToolButton/ or $parent =~ m/Gtk3::MenuToolButton/) { $parent->set_icon_widget($img); }
        else { $parent->set_image($img); }
    }

    $img->show();
    return $img;
}

# Create a pixbuf from a file
sub gui_new_pixbuf_from_file {
    my ($filename) = @_;
    my $pb = Gtk3::Gdk::Pixbuf->new_from_file("$sharedir/icons/$filename");
    return $pb;
}

# Create a base menu
sub gui_new_menu {
    my $menu = Gtk3::Menu->new();
    $menu->set_reserve_toggle_size(TRUE);
    return $menu;
}

# Menu Item with optional image
sub gui_new_menu_item {
    my ($label, $imgfile, $parent) = @_;
    my $item = Gtk3::ImageMenuItem->new_with_mnemonic($label);

    if ($imgfile) {
        my $img = Gtk3::Image->new_from_file("$sharedir/icons/$imgfile");
        $item->set_image($img);
        $item->set_always_show_image(TRUE);
    }

    $parent->append($item) if ($parent);
    $item->show();
    return $item;
}

# Menu Item with optional image
sub gui_new_menu_item_no_mnemonic {
    my ($label, $imgfile, $parent) = @_;
    my $item = Gtk3::ImageMenuItem->new_with_label($label);

    if ($imgfile) {
        my $img = Gtk3::Image->new_from_file("$sharedir/icons/$imgfile");
        $item->set_image($img);
        $item->set_always_show_image(TRUE);
    }

    $parent->append($item) if ($parent);
    $item->show();
    return $item;
}

# Menu Item with checkmark
sub gui_new_check_menu_item {
    my ($label, $parent) = @_;
    my $item = Gtk3::CheckMenuItem->new_with_label($label);
    $parent->append($item) if ($parent);
    $item->show();
    return $item;
}

# Menu Separator
sub gui_new_menu_sep {
    my $sep = Gtk3::SeparatorMenuItem->new();
    $sep->show();
    return $sep;
}

# Creates an adjustment and optionally attaches it
sub gui_new_adjustment {
    my ($parent, $init, $lower, $upper, $stepinc, $pageinc, $pagesize) = @_;
    my $adj = Gtk3::Adjustment->new($init, $lower, $upper, $stepinc, $pageinc, $pagesize);
    $parent->set_adjustment($adj) if ($parent);
    return $adj;
}

1;
