# General GUI related functions and structures
#
# RemoteBox is heavily under transition with regards to the GUI.
# The dependence on Glade and GtkBuilder is progressively being
# removed and replaced with direct code. This is significant work
# whilst keeping the application functional. Following completion
# of the transition, GUI code optimisation will take place.
#
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         => 'RemoteBox',
            appver          => 'v3.3',
            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);
}

# 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});
# 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});
# 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});
# Adjustments
$gui{adjEditGenAutostartDelay} = &gui_new_adjustment($gui{sbEditGenAutostartDelay}, 0, 0, 999, 1, 10, 0);
$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{adjEditSysTimeOffset} = &gui_new_adjustment($gui{spinbuttonEditSysTimeOffset}, 0, 0, 86400000, 1, 0, 0);
# TPM (Friendly Name, Value)
$gui{liststoreEditSysTPM} = &gui_new_lstore($gui{comboboxEditSysTPM}, ['Glib::String', 'Glib::String']);
# 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});
# 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});
# 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']);
# 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{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});
# Cyphers
$gui{liststoreGenEncryptionCipher} = &gui_new_lstore($gui{comboboxEditGenEncryptionCipher}, ['Glib::String', 'Glib::String'], [0, 1], $lists{cypher_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);
# 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']);
#
$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('_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 signals
# as blocking any other way is not supported in perl-gtk (other blocking funcs map to null funcs)
our %signal = (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); }),
               checkbuttonEditSysSecureBoot_toggled     => $gui{checkbuttonEditSysSecureBoot}->signal_connect('toggled' => \&sys_mother_secureboot),
               checkbuttonEditUSBEnable_toggled         => $gui{checkbuttonEditUSBEnable}->signal_connect('toggled' => \&usb_toggle),
               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}),
               crndrtoggleEditSysBootEnabled_toggled    => $gui{crndrtoggleEditSysBootEnabled}->signal_connect('toggled' => \&sys_mother_boot_dev_toggle),
               crndrtoggleEditUSBEnabled_toggled        => $gui{crndrtoggleEditUSBEnabled}->signal_connect('toggled' => \&usb_toggle_filter),
               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_dialogClone),
               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),
               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),
               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),
               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),
               treeviewSnapshots_cursorChanged          => $gui{treeviewSnapshots}->signal_connect('cursor-changed' => \&onsel_list_snapshots),
               treeviewSnapshots_rowActivated           => $gui{treeviewSnapshots}->signal_connect('row-activated' => \&show_dialog_snap_details));

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

# 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});
}

# Build the AboutDialog
sub build_dialogAbout {
    $gui{d}{About} = Gtk3::AboutDialog->new();
    $gui{d}{About}->set_program_name($gui{appname});
    $gui{d}{About}->set_version($gui{appver});
    $gui{d}{About}->set_comments("RemoteBox is a client for managing VirtualBox and its guests over the network.\nFor use with VirtualBox 7.1.x");
    $gui{d}{About}->set_copyright("RemoteBox (ex. artwork) Copyright © 2010-2024 Ian Chapman\nRemoteBox is not affiliated with Oracle.\nAll trademarks belong to their respective owners.\n\nIf you like RemoteBox or have found it useful, please consider donating.");
    $gui{d}{About}->set_documenters(['Ian Chapman <packages@amiga-hardware.com>']);
    $gui{d}{About}->set_artists(['Icons are included which originate from the VirtualBox Open Source Edition, released under the GPL']);
    $gui{d}{About}->set_authors(['Ian Chapman <packages@amiga-hardware.com>']);
    $gui{d}{About}->set_license_type('GTK_LICENSE_GPL_2_0');
    $gui{d}{About}->set_logo(&gui_new_pixbuf_from_file('remotebox-about.png'));
    $gui{d}{About}->set_website('http://remotebox.knobgoblin.org.uk');
    $gui{d}{About}->set_website_label('Donate or visit the RemoteBox site');
    $gui{d}{About}->set_transient_for($gui{windowMain});
}

# Build Warning MessageDialog
sub build_messageDialogsAll {
    # General warning dialog
    $gui{d}{warningMessageDialog} = Gtk3::MessageDialog->new_with_markup($gui{windowMain}, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_WARNING', 'GTK_BUTTONS_OK', '<b><big>Warning Message Dialog</big></b>');
    $gui{d}{warningMessageDialog}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{warningMessageDialog});
    $gui{d}{warningMessageDialog}->signal_connect('show' => \&transwin_sens_off, $gui{d}{warningMessageDialog});
    $gui{d}{warningMessageDialog}->set_deletable(FALSE);
    # General error dialog
    $gui{d}{errorMessageDialog} = Gtk3::MessageDialog->new_with_markup($gui{windowMain}, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_ERROR', 'GTK_BUTTONS_OK', '<b><big>Error Message Dialog</big></b>');
    $gui{d}{errorMessageDialog}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{errorMessageDialog});
    $gui{d}{errorMessageDialog}->signal_connect('show' => \&transwin_sens_off, $gui{d}{errorMessageDialog});
    $gui{d}{errorMessageDialog}->set_deletable(FALSE);
    # The Remove selected guest dialog
    $gui{d}{RemoveGuest} = Gtk3::MessageDialog->new_with_markup($gui{windowMain}, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_WARNING', 'GTK_BUTTONS_NONE', '<b><big>Remove the selected guest?</big></b>');
    $gui{d}{RemoveGuest}->format_secondary_text('Choose whether to remove the guest and delete the associated files or only remove it from VirtualBox. Deleting all files is a permanent and irreversible operation. Removing will allow you to add the guest again at a later date');
    $gui{d}{RemoveGuest}->set_deletable(FALSE);
    $gui{d}{RemoveGuest}->set_default_response('cancel');
    $gui{d}{RemoveGuest}->add_button('Cancel', 'cancel');
    $gui{d}{RemoveGuest}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{RemoveGuest});
    $gui{d}{RemoveGuest}->signal_connect('show' => \&transwin_sens_off, $gui{d}{RemoveGuest});
    my $removebutton = $gui{d}{RemoveGuest}->add_button('Remove Only', 1);
    $removebutton->set_always_show_image(TRUE);
    $removebutton->set_image(&gui_new_img_from_file('dialog_remove_only_16px.png'));
    $removebutton->set_image_position('GTK_POS_LEFT');
    my $deletebutton = $gui{d}{RemoveGuest}->add_button('Delete All Files', 2);
    $deletebutton->set_always_show_image(TRUE);
    $deletebutton->set_image(&gui_new_img_from_file('dialog_delete_all_files_16px.png'));
    $deletebutton->set_image_position('GTK_POS_LEFT');
    # The Remove HD dialog
    $gui{d}{RemoveHD} = Gtk3::MessageDialog->new_with_markup($gui{windowMain}, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_WARNING', 'GTK_BUTTONS_NONE', '<b><big>Remove or Delete Hard Disk Image?</big></b>');
    $gui{d}{RemoveHD}->format_secondary_text("Deleting the hard disk image will permanently remove it from the host's file system. It will no longer be available in VirtualBox and all data on the disk image will be destroyed.\nRemoving will make the hard disk image unavailable to VirtualBox, however it may be added again at a later date.");
    $gui{d}{RemoveHD}->set_deletable(FALSE);
    $gui{d}{RemoveHD}->set_default_response('cancel');
    $gui{d}{RemoveHD}->add_button('Cancel', 'cancel');
    $gui{d}{RemoveHD}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{RemoveGuest});
    $gui{d}{RemoveHD}->signal_connect('show' => \&transwin_sens_off, $gui{d}{RemoveGuest});
    my $removehdbutton = $gui{d}{RemoveHD}->add_button('Remove Only', 2);
    $removehdbutton->set_always_show_image(TRUE);
    $removehdbutton->set_image(&gui_new_img_from_file('dialog_remove_only_16px.png'));
    $removehdbutton->set_image_position('GTK_POS_LEFT');
    my $deletehdbutton = $gui{d}{RemoveHD}->add_button('Delete', 1);
    $deletehdbutton->set_always_show_image(TRUE);
    $deletehdbutton->set_image(&gui_new_img_from_file('hd_remove_16px.png'));
    $deletehdbutton->set_image_position('GTK_POS_LEFT');
    # InvalidObject Reference Dialog
    $gui{d}{invalidobjectMessage} = Gtk3::MessageDialog->new_with_markup($gui{windowMain}, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_ERROR', 'GTK_BUTTONS_NONE', '<b><big>Invalid Object Reference</big></b>');
    $gui{d}{invalidobjectMessage}->set_deletable(FALSE);
    $gui{d}{invalidobjectMessage}->set_default_response('cancel');
    $gui{d}{invalidobjectMessage}->add_button('Continue Anyway', 'ok');
    $gui{d}{invalidobjectMessage}->add_button('Disconnect', 'cancel');
    $gui{d}{invalidobjectMessage}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{invalidobjectMessage});
    $gui{d}{invalidobjectMessage}->signal_connect('show' => \&transwin_sens_off, $gui{d}{invalidobjectMessage});
}

# Build local file choosers
sub build_filechooserDialogsAll {
    # Chooser for saving a screenshot
    $gui{d}{ScreenShotFileChooser} = Gtk3::FileChooserDialog->new('Save Screenshot', undef, 'GTK_FILE_CHOOSER_ACTION_SAVE', 'Cancel', 'cancel', 'Save', 'ok');
    $gui{d}{ScreenShotFileChooser}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{ScreenShotFileChooser});
    $gui{d}{ScreenShotFileChooser}->signal_connect('show' => \&transwin_sens_off, $gui{d}{ScreenShotFileChooser});
    # Chooser for saving a log
    $gui{d}{LogFileChooser} = Gtk3::FileChooserDialog->new('Save Log File', undef, 'GTK_FILE_CHOOSER_ACTION_SAVE', 'Cancel', 'cancel', 'Save', 'ok');
    $gui{d}{LogFileChooser}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{LogFileChooser});
    $gui{d}{LogFileChooser}->signal_connect('show' => \&transwin_sens_off, $gui{d}{LogFileChooser});
}

# Build the Custom Resolution Dialog
sub build_dialogCustomResolution {
    $gui{d}{CustomVideo} = &gui_new_dialog({title  => 'Resolution Hint',
                                            cancel => TRUE});

    $gui{d}{CustomVideo}{sbVideoW} = &gui_new_spinbutton({lo  => 1,
                                                          hi  => 9999,
                                                          inc => 1,
                                                          tip => 'Resolution width'});

    $gui{d}{CustomVideo}{sbVideoH} = &gui_new_spinbutton({lo  => 1,
                                                          hi  => 9999,
                                                          inc => 1,
                                                          tip => 'Resolution height'});

    $gui{d}{CustomVideo}{cboxVideoDepth} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::Uint'], [0, 1], $lists{custom_video_d}),
                                                                    active => 2,
                                                                    tip    => 'Resolution depth. Higher depths mean more colours'});

    $gui{adjCustomVideoW} = &gui_new_adjustment($gui{d}{CustomVideo}{sbVideoW}, 640, 80, 8000, 1, 10, 0);
    $gui{adjCustomVideoH} = &gui_new_adjustment($gui{d}{CustomVideo}{sbVideoH}, 480, 80, 4000, 1, 10, 0);
    $gui{d}{CustomVideo}{labelVideoInfo} = &gui_new_widgetlabel({text => '', xalign => 0.5});
    $gui{d}{CustomVideo}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Width:', mnwidget => $gui{d}{CustomVideo}{sbVideoW}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{CustomVideo}{sbVideoW},  1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Height:', mnwidget => $gui{d}{CustomVideo}{sbVideoH}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{CustomVideo}{sbVideoH},  1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Depth:', mnwidget => $gui{d}{CustomVideo}{cboxVideoDepth}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{CustomVideo}{cboxVideoDepth}, 1, 2, 1, 1);
    $grid->attach($gui{d}{CustomVideo}{labelVideoInfo}, 1, 3, 2, 1);
    $gui{d}{CustomVideo}{sbVideoW}->signal_connect('value-changed' => \&update_vidmeminfo);
    $gui{d}{CustomVideo}{sbVideoH}->signal_connect('value-changed' => \&update_vidmeminfo);
    $gui{d}{CustomVideo}{cboxVideoDepth}->signal_connect('changed' => \&update_vidmeminfo);
}

# Build the connection dialog
sub build_dialogConnect {
    $gui{d}{Connect} = &gui_new_dialog({title  => 'Connect to VirtualBox Server',
                                        cancel => TRUE,
                                        ok     => 'Connect'});

    $gui{d}{Connect}{cboxProfile} = &gui_new_simplecombobox({model  => $gui{d}{Connect}{lstoreProfile} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']), # This is also shared with the profile manager
                                                             active => -1,
                                                             tip    => 'Choose a connection profile'});

    $gui{d}{Connect}{entryURL} = &gui_new_entry({width => 60,
                                                 tip   => 'The URL of the VirtualBox server. For example http://myserver:18083'});

    $gui{d}{Connect}{entryUser} = &gui_new_entry({width => 60,
                                                  tip   => 'The user to connect as. Leave blank if authentication is disabled on the server'});

    $gui{d}{Connect}{entryPass} = &gui_new_entry({width => 60,
                                                  tip   => 'The user password. Leave blank if authentication is disabled on the server',
                                                  pass  => TRUE});

    $gui{d}{Connect}{checkSSL} = &gui_new_check({text   => '_Verify certificate on SSL connections',
                                                 active => TRUE,
                                                 tip    => 'Only connects to the server if its certificate passes verification'});

    $gui{d}{Connect}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'C_onnection Profile:', mnwidget => $gui{d}{Connect}{cboxProfile}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{Connect}{cboxProfile}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_URL:', mnwidget => $gui{d}{Connect}{entryURL}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{Connect}{entryURL}, 1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'User_name:', mnwidget => $gui{d}{Connect}{entryUser}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{Connect}{entryUser}, 1, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Password:', mnwidget => $gui{d}{Connect}{entryPass}}), 0, 3, 1, 1);
    $grid->attach($gui{d}{Connect}{entryPass}, 1, 3, 1, 1);
    $grid->attach($gui{d}{Connect}{checkSSL}, 1, 4, 1, 1);
    $gui{d}{Connect}{cboxProfile}->signal_connect('changed' => \&select_profile);
    $gui{d}{Connect}{entryURL}->signal_connect('key-press-event' => \&set_connection_prof_inactive);
    $gui{d}{Connect}{entryUser}->signal_connect('key-press-event' => \&set_connection_prof_inactive);
    $gui{d}{Connect}{entryPass}->signal_connect('key-press-event' => \&set_connection_prof_inactive);
    $gui{d}{Connect}{checkSSL}->signal_connect('toggled' => \&rbprefs_sslverify);
}

# Build the password dialog for encryped guests
sub build_dialogDecPassword {
    $gui{d}{DecPassword} = &gui_new_dialog({title  => 'Decryption Password',
                                            cancel => TRUE});

    $gui{d}{DecPassword}{entryPass} = &gui_new_entry({width => 60,
                                                  tip   => 'The password to decrypt the specified medium',
                                                  pass  => TRUE});

    $gui{d}{DecPassword}{labelKeyID} = &gui_new_widgetlabel({text => '',
                                                             xalign => 0.5});

    $gui{d}{DecPassword}{labelDisk} = &gui_new_widgetlabel({text => '',
                                                            xalign => 0.5});

    $gui{d}{DecPassword}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach($gui{d}{DecPassword}{labelKeyID}, 0, 0, 2, 1);
    $grid->attach($gui{d}{DecPassword}{labelDisk}, 0, 1, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Password:', mnwidget => $gui{d}{DecPassword}{entryPass}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{DecPassword}{entryPass}, 1, 2, 1, 1);
}

# Build the dialog for Shared Folders.
sub build_dialogSharedFolders {
    $gui{d}{SharedFolders} = &gui_new_dialog({title  => 'Shared Folders',
                                              cancel => TRUE});

    $gui{d}{SharedFolders}{entryPath} = &gui_new_entry({width  => 35,
                                                        tip    => 'Full path to the shared folder, which must be accessible by the server'});

    $gui{d}{SharedFolders}{entryName} = &gui_new_entry({width  => 35,
                                                        maxlen => 128,
                                                        tip    => 'The name of shared folder as referenced by the guest'});

    $gui{d}{SharedFolders}{checkReadOnly} = &gui_new_check({text   => '_Read-Only',
                                                            active => FALSE,
                                                            tip    => 'Mount the folder as read-only'});

    $gui{d}{SharedFolders}{checkAutoMount} = &gui_new_check({text   => '_Auto Mount',
                                                             active => FALSE,
                                                             tip    => 'Automatically mount the folder when the guest starts'});

    $gui{d}{SharedFolders}{checkPermanent} = &gui_new_check({text   => '_Make Permanent',
                                                             active => FALSE,
                                                             tip    => 'Make this share non-transient'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the folder on the server'});

    $gui{d}{SharedFolders}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Folder _Path:', mnwidget => $gui{d}{SharedFolders}{entryPath}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{SharedFolders}{entryPath}, 1, 0, 1, 1);
    $grid->attach($buttonfolder, 2, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Folder _Name:', mnwidget => $gui{d}{SharedFolders}{entryName}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{SharedFolders}{entryName}, 1, 1, 2, 1);
    $grid->attach($gui{d}{SharedFolders}{checkReadOnly}, 1, 3, 2, 1);
    $grid->attach($gui{d}{SharedFolders}{checkAutoMount}, 1, 4, 2, 1);
    $grid->attach($gui{d}{SharedFolders}{checkPermanent}, 1, 5, 2, 1);

    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Shared Folder',
                                                                           entrywidget => \$gui{d}{SharedFolders}{entryPath},
                                                                           mode        => 'dir',
                                                                           filter      => ' ^',
                                                                           callback    => \&handle_remote_folder_entry}),
}

# Build the Copy Floppy Dialog
sub build_dialogCopyFloppy {
    $gui{d}{CopyFloppy} = &gui_new_dialog({title  => 'Copy Floppy Disk Image',
                                           cancel => TRUE,
                                           ok     => 'Copy'});

    $gui{d}{CopyFloppy}{entrySrc} = &gui_new_entry({width  => 35,
                                                    tip    => 'The source floppy disk image'});
    $gui{d}{CopyFloppy}{entrySrc}->set_editable(FALSE);
    $gui{d}{CopyFloppy}{entrySrc}->set_can_focus(FALSE);

    $gui{d}{CopyFloppy}{entryDst} = &gui_new_entry({width  => 35,
                                                    tip    => 'The destination floppy disk image'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the destination and image name'});

    $gui{d}{CopyFloppy}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Source Floppy:'}), 0, 0, 1, 1);
    $grid->attach($gui{d}{CopyFloppy}{entrySrc}, 1, 0, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'New Floppy _Name:', mnwidget => $gui{d}{CopyFloppy}{entryDst}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{CopyFloppy}{entryDst}, 1, 1, 1, 1);
    $grid->attach($buttonfolder, 2, 1, 1, 1);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Destination Floppy Image',
                                                                           entrywidget => \$gui{d}{CopyFloppy}{entryDst},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build the Move Medium dialog
sub build_dialogMoveMedium {
    $gui{d}{MoveMedium} = &gui_new_dialog({title  => 'Move Medium',
                                           cancel => TRUE,
                                           ok     => 'Move'});

    $gui{d}{MoveMedium}{entrySrc} = &gui_new_entry({width  => 35,
                                                    tip    => 'The source medium to move'});
    $gui{d}{MoveMedium}{entrySrc}->set_editable(FALSE);
    $gui{d}{MoveMedium}{entrySrc}->set_can_focus(FALSE);

    $gui{d}{MoveMedium}{entryDst} = &gui_new_entry({width  => 35,
                                                    tip    => 'The destination location and file name'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the destination and file name'});

    $gui{d}{MoveMedium}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Medium:'}), 0, 0, 1, 1);
    $grid->attach($gui{d}{MoveMedium}{entrySrc}, 1, 0, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'New _Destination:', mnwidget => $gui{d}{MoveMedium}{entryDst}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{MoveMedium}{entryDst}, 1, 1, 1, 1);
    $grid->attach($buttonfolder, 2, 1, 1, 1);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Destination Medium',
                                                                           entrywidget => \$gui{d}{MoveMedium}{entryDst},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build Create Floppy dialog
sub build_dialogCreateFloppy {
    $gui{d}{CreateFloppy} = &gui_new_dialog({title   => 'Create Floppy Disk Image',
                                             cancel  => TRUE,
                                             ok      => 'Create',
                                             okimage => &gui_new_img_from_file('fd_create_16px.png')});

    $gui{d}{CreateFloppy}{entryImage} = &gui_new_entry({width  => 35,
                                                        tip    => 'The floppy disk image filename, without extension'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the destination and file name'});

    $gui{d}{CreateFloppy}{cboxSize} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{floppy_sizes}),
                                                               active => 1,
                                                               tip    => 'The size of the floppy disk image'});

    $gui{d}{CreateFloppy}{checkFAT12} = &gui_new_check({text => '_FAT12 Formatted',
                                                        active => TRUE,
                                                        tip    => 'Preformat the disk with the FAT12 filesystem'});

    $gui{d}{CreateFloppy}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Floppy _Image:', mnwidget => $gui{d}{CreateFloppy}{entryImage}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{CreateFloppy}{entryImage}, 1, 0, 1, 1);
    $grid->attach($buttonfolder, 2, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Floppy _Size:', mnwidget => $gui{d}{CreateFloppy}{cboxSize}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{CreateFloppy}{cboxSize}, 1, 1, 2, 1);
    $grid->attach($gui{d}{CreateFloppy}{checkFAT12}, 1, 2, 2, 1);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Destination Floppy Image',
                                                                           entrywidget => \$gui{d}{CreateFloppy}{entryImage},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build the USB Filter dialog
sub build_dialogUSBFilter {
    $gui{d}{USBFilter} = &gui_new_dialog({title  => 'USB Filter Properties',
                                          cancel => TRUE});

    $gui{d}{USBFilter}{entryName} = &gui_new_entry({tip => 'Name of the USB filter'});
    $gui{d}{USBFilter}{entryVendorID} = &gui_new_entry({maxlen => 4,
                                                      tip    => 'The hex number of the vendor ID to match. Leave empty to match any'});

    $gui{d}{USBFilter}{entryProductID} = &gui_new_entry({maxlen => 4,
                                                       tip    => 'The hex number of the product ID to match. Leave empty to match any'});

    $gui{d}{USBFilter}{entryRev} = &gui_new_entry({maxlen => 4,
                                                   tip    => 'The hex number of the revision to match. Leave empty to match any'});

    $gui{d}{USBFilter}{entryManufacturer} = &gui_new_entry({tip => 'The manufacturer string to match. Leave empty to match any'});
    $gui{d}{USBFilter}{entryProduct} = &gui_new_entry({tip => 'The product string to match. Leave empty to match any'});
    $gui{d}{USBFilter}{entrySerial} = &gui_new_entry({tip => 'The serial string to match. Leave empty to match any'});
    $gui{d}{USBFilter}{entryPort} = &gui_new_entry({maxlen => 4,
                                                    tip    => 'The host USB port number to match. Leave empty to match any USB port'});

    $gui{d}{USBFilter}{cboxRemote} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{usb_remote_filter_types}),
                                                              active => 0,
                                                              tip    => 'Whether to apply the filters remotely, locally or both'});

    $gui{d}{USBFilter}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Name:', mnwidget => $gui{d}{USBFilter}{entryName}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryName}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Vendor ID:', mnwidget => $gui{d}{USBFilter}{entryVendorID}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryVendorID}, 1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Product ID:', mnwidget => $gui{d}{USBFilter}{entryProductID}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryProductID}, 1, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Revision:', mnwidget => $gui{d}{USBFilter}{entryRev}}), 0, 3, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryRev}, 1, 3, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Manufacturer:', mnwidget => $gui{d}{USBFilter}{entryManufacturer}}), 0, 4, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryManufacturer}, 1, 4, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Pro_duct:', mnwidget => $gui{d}{USBFilter}{entryProduct}}), 0, 5, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryProduct}, 1, 5, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Serial #:', mnwidget => $gui{d}{USBFilter}{entrySerial}}), 0, 6, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entrySerial}, 1, 6, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Por_t:', mnwidget => $gui{d}{USBFilter}{entryPort}}), 0, 7, 1, 1);
    $grid->attach($gui{d}{USBFilter}{entryPort}, 1, 7, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'R_emote:', mnwidget => $gui{d}{USBFilter}{cboxRemote}}), 0, 8, 1, 1);
    $grid->attach($gui{d}{USBFilter}{cboxRemote}, 1, 8, 1, 1);
}

# Build the Import Appliance Dialog
sub build_dialogImportAppl {
    $gui{d}{ImportAppl} = &gui_new_dialog({title   => 'Import Appliance',
                                           cancel  => TRUE,
                                           ok      => 'Import',
                                           okimage => &gui_new_img_from_file('dialog_import_16px.png')});

    $gui{d}{ImportAppl}{entryAppl} = &gui_new_entry({width  => 35,
                                                     tip    => 'The path and file name of the appliance to import'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the appliance to import'});

    $gui{d}{ImportAppl}{cboxMAC} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String'], [0], $lists{mac_policies}),
                                                            active => 1,
                                                            tip    => 'Choose how the MAC addresses are handled on import'});

    $gui{d}{ImportAppl}{checkConvert} = &gui_new_check({text   => '_Convert hard drives to VDI format',
                                                        active => FALSE,
                                                        tip    => 'Convert hard drive images to VDI format on import'});

    $gui{d}{ImportAppl}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_ovf_import.png'), 0, 0, 1, 4);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => '_Appliance (OVA/OVF):', mnwidget => $gui{d}{ImportAppl}{entryAppl}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{ImportAppl}{entryAppl}, 2, 0, 1, 1);
    $grid->attach($buttonfolder, 3, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_MAC Address Policy:', mnwidget => $gui{d}{ImportAppl}{cboxMAC}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{ImportAppl}{cboxMAC}, 2, 1, 2, 1);
    $grid->attach($gui{d}{ImportAppl}{checkConvert}, 2, 2, 2, 1);
    $grid->attach(&gui_new_layout(), 3, 3, 1, 1);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Import Appliance File',
                                                                           entrywidget => \$gui{d}{ImportAppl}{entryAppl},
                                                                           mode        => 'file',
                                                                           filter      => '^.*\.ova$|^.*\.ovf$|^.*\.tar\.gz$|^.*\.tgz$',
                                                                           callback     => \&handle_remote_file_entry});
}

# Build the Export Appliance Dialog
sub build_dialogExportAppl {
    $gui{d}{ExportAppl} = &gui_new_dialog({title   => 'Export Appliance',
                                           cancel  => TRUE,
                                           ok      => 'Export',
                                           okimage => &gui_new_img_from_file('dialog_export_16px.png')});

    $gui{d}{ExportAppl}{entryFile} = &gui_new_entry({width  => 35,
                                                     tip    => "Location and filename on the server where the appliance will be saved\n* Location must be absolute and writable\n* Do not specify the file extension\nThe path and file name of the appliance to import"});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose where on the server to save the appliance'});

    $gui{d}{ExportAppl}{cboxFormat} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String'], [0, 1, 2], $lists{appliance_formats}),
                                                               active => 2,
                                                               tip    => 'The OVF format version'});

    $gui{d}{ExportAppl}{cboxMAC} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String'], [0], $lists{mac_policies_export}),
                                                            active => 1,
                                                            tip    => 'Choose how the MAC addresses are handled on export'});

    $gui{d}{ExportAppl}{checkISO} = &gui_new_check({text   => '_Include ISO image files',
                                                    active => FALSE,
                                                    tip    => 'Include any attached ISO files in the exported appliance'});

    $gui{d}{ExportAppl}{entryName} = &gui_new_entry({width  => 35,
                                                     tip    => 'The name of the appliance'});

    $gui{d}{ExportAppl}{entryProduct} = &gui_new_entry({width  => 35,
                                                        tip    =>  'The name of the product'});

    $gui{d}{ExportAppl}{entryProductURL} = &gui_new_entry({width  => 35,
                                                           tip    => "The URL of the product's website"});

    $gui{d}{ExportAppl}{entryVendor} = &gui_new_entry({width  => 35,
                                                       tip    => 'The name of the vendor'});

    $gui{d}{ExportAppl}{entryVendorURL} = &gui_new_entry({width  => 35,
                                                          tip    => "The URL of the vendor's website"});

    $gui{d}{ExportAppl}{entryVersion} = &gui_new_entry({width  => 35,
                                                        tip => 'The version of the appliance'});

    $gui{d}{ExportAppl}{tbDescription} = &gui_new_textbuffer(undef);
    $gui{d}{ExportAppl}{tbLicense} = &gui_new_textbuffer(undef);

    my $tv1 = &gui_new_textview({editable => TRUE,
                                 buffer   => $gui{d}{ExportAppl}{tbDescription},
                                 tip      => 'A description of the appliance'});

    my $tv2 = &gui_new_textview({editable => TRUE,
                                 buffer   => $gui{d}{ExportAppl}{tbLicense},
                                 tip      => "The appliance's license"});

    my $frame1 = &gui_new_frame({label => 'Export To'});
    my $frame2 = &gui_new_frame({label => 'Appliance Information'});
    $gui{d}{ExportAppl}->get_content_area()->add(my $grid1 = &gui_new_grid());
    # COL ROW WIDTH HEIGHT
    $grid1->attach(my $img = &gui_new_img_from_file('wizard_ovf_export.png'), 0, 0, 1, 2);
    $img->set_alignment(0.0, 0.0);
    $grid1->attach($frame1, 1, 0, 1, 1);
    $grid1->attach($frame2, 1, 1, 1, 1);
    $frame1->add(my $grid2 = &gui_new_grid());
    $grid2->attach(&gui_new_widgetlabel({text => '_File:', mnwidget => $gui{d}{ExportAppl}{entryFile}}), 0, 0, 1, 1);
    $grid2->attach($gui{d}{ExportAppl}{entryFile}, 1, 0, 1, 1);
    $grid2->attach($buttonfolder, 2, 0, 1, 1);
    $grid2->attach(&gui_new_widgetlabel({text => 'F_ormat:', mnwidget => $gui{d}{ExportAppl}{cboxFormat}}), 0, 1, 1, 1);
    $grid2->attach($gui{d}{ExportAppl}{cboxFormat}, 1, 1, 2, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_MAC Address Policy:', mnwidget => $gui{d}{ExportAppl}{cboxMAC}}), 0, 2, 1, 1);
    $grid2->attach($gui{d}{ExportAppl}{cboxMAC}, 1, 2, 2, 1);
    $grid2->attach($gui{d}{ExportAppl}{checkISO}, 1, 4, 2, 1);
    $frame2->add(my $grid3 = &gui_new_grid());
    $grid3->attach(&gui_new_widgetlabel({text => '_Name:', mnwidget => $gui{d}{ExportAppl}{entryName}}), 0, 0, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryName}, 1, 0, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => '_Product:', mnwidget => $gui{d}{ExportAppl}{entryProduct}}), 0, 1, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryProduct}, 1, 1, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => 'Product _URL:', mnwidget => $gui{d}{ExportAppl}{entryProductURL}}), 0, 2, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryProductURL}, 1, 2, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => '_Vendor:', mnwidget => $gui{d}{ExportAppl}{entryVendor}}), 0, 3, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryVendor}, 1, 3, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => 'V_endor URL:', mnwidget => $gui{d}{ExportAppl}{entryVendorURL}}), 0, 4, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryVendorURL}, 1, 4, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => 'Ve_rsion:', mnwidget => $gui{d}{ExportAppl}{entryVersion}}), 0, 5, 1, 1);
    $grid3->attach($gui{d}{ExportAppl}{entryVersion}, 1, 5, 1, 1);
    $grid3->attach(&gui_new_widgetlabel({text => '_Description:', mnwidget => $tv1}), 0, 6, 1, 1);
    $grid3->attach(my $scrollwin1 = &gui_new_scrolledwindow(), 1, 6, 1, 1);
    $scrollwin1->add_with_viewport($tv1);
    $grid3->attach(&gui_new_widgetlabel({text => '_License:', mnwidget => $tv2}), 0, 7, 1, 1);
    $grid3->attach(my $scrollwin2 = &gui_new_scrolledwindow(), 1, 7, 1, 1);
    $scrollwin2->add_with_viewport($tv2);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Export Appliance File',
                                                                           entrywidget => \$gui{d}{ExportAppl}{entryFile},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build the Import Appliance Dialog
sub build_dialogClone {
    $gui{d}{Clone} = &gui_new_dialog({title   => 'Clone Guest',
                                      cancel  => TRUE,
                                      ok      => 'Clone',
                                      okimage => &gui_new_img_from_file('dialog_clone_16px.png')});

    $gui{d}{Clone}{entryName} = &gui_new_entry({width  => 35,
                                                maxlen => 255,
                                                tip    => 'The name give the clone'});

    $gui{d}{Clone}{cboxType} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String'], [0], $lists{clone_states}),
                                                        active => 0,
                                                        tip    => '* All States : Includes any associated snapshots in the clone\n* Current State Only: Clones the current state, not any associated snapshots\n* Linked: Takes a snapshot of the original guest and links it to the cloneChoose how the MAC addresses are handled on import'});

    $gui{d}{Clone}{cboxMAC} = &gui_new_simplecombobox({model => &gui_new_lstore(undef, ['Glib::String'], [0], $lists{mac_policies}),
                                                       active => 1,
                                                       tip    => 'Choose how the MAC addresses are handled during cloning'});

    $gui{d}{Clone}{checkKeepDiskName} = &gui_new_check({text   => 'Keep _Disk Names',
                                                        active => FALSE,
                                                        tip    => 'Maintain the disk names during cloning'});

    $gui{d}{Clone}{checkKeepUUIDs} = &gui_new_check({text   => 'Keep _Hardware UUIDs',
                                                        active => FALSE,
                                                        tip    => 'Maintain the hardware UUIDs during cloning'});

    $gui{d}{Clone}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_clone.png'), 0, 0, 1, 6);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => 'Clone _Name:', mnwidget => $gui{d}{Clone}{entryName}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{Clone}{entryName}, 2, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Clone _Type:', mnwidget => $gui{d}{Clone}{cboxType}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{Clone}{cboxType}, 2, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_MAC Address Policy:', mnwidget => $gui{d}{Clone}{cboxMAC}}), 1, 2, 1, 1);
    $grid->attach($gui{d}{Clone}{cboxMAC}, 2, 2, 1, 1);
    $grid->attach($gui{d}{Clone}{checkKeepDiskName}, 2, 3, 1, 1);
    $grid->attach($gui{d}{Clone}{checkKeepUUIDs}, 2, 4, 1, 1);
    $grid->attach(&gui_new_layout(), 2, 5, 1, 1);
}

# Build the IPv4 PortFordwarding dialog
sub build_dialogPFRule4 {
    $gui{d}{PFRule4} = &gui_new_dialog({title  => 'Add IPv4 Port-Forwarding Rule',
                                        cancel => TRUE,
                                        ok     => 'Apply'});

    $gui{d}{PFRule4}{entryName} = &gui_new_entry({width  => 35,
                                                  maxlen => 255,
                                                  tip    => 'Name of the port-forwarding rule'});

    $gui{d}{PFRule4}{cboxProtocol} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{ip_protocols}),
                                                              active => 0,
                                                              tip    => 'The protocol for the port-forwarding rule'});

    $gui{d}{PFRule4}{entryHostIP} = &gui_new_entry({width  => 35,
                                                    maxlen => 15,
                                                    tip    => 'The IP of the host to port-forward'});

    $gui{d}{PFRule4}{sbHostPort} = &gui_new_spinbutton({lo     => 1,
                                                        hi     => 65535,
                                                        inc    => 1,
                                                        maxlen => 5,
                                                        tip    => 'The port number on the host to port-forward'});

    $gui{d}{PFRule4}{adjHostPort} = &gui_new_adjustment(undef,, 0, 0, 65535, 1, 10, 0);
    $gui{d}{PFRule4}{sbHostPort}->set_adjustment($gui{d}{PFRule4}{adjHostPort});

    $gui{d}{PFRule4}{entryGuestIP} = &gui_new_entry({width  => 35,
                                                     maxlen => 15,
                                                     tip    => 'The IP of the guest to port-forward to'});

    $gui{d}{PFRule4}{sbGuestPort} = &gui_new_spinbutton({lo     => 1,
                                                         hi     => 65535,
                                                         inc    => 1,
                                                         maxlen => 5,
                                                         tip    => 'The port number on the guest to port-forward to'});

    $gui{d}{PFRule4}{adjGuestPort} = &gui_new_adjustment(undef, 0, 0, 65535, 1, 10, 0);
    $gui{d}{PFRule4}{sbGuestPort}->set_adjustment($gui{d}{PFRule4}{adjGuestPort});
    $gui{d}{PFRule4}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Name:', mnwidget => $gui{d}{PFRule4}{entryName}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{PFRule4}{entryName}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Protocol:', mnwidget => $gui{d}{PFRule4}{cboxProtocol}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{PFRule4}{cboxProtocol}, 1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Host IP:', mnwidget => $gui{d}{PFRule4}{entryHostIP}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{PFRule4}{entryHostIP}, 1, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'H_ost Port:', mnwidget => $gui{d}{PFRule4}{sbHostPort}}), 0, 3, 1, 1);
    $grid->attach($gui{d}{PFRule4}{sbHostPort}, 1, 3, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Guest IP:', mnwidget => $gui{d}{PFRule4}{entryGuestIP}}), 0, 4, 1, 1);
    $grid->attach($gui{d}{PFRule4}{entryGuestIP}, 1, 4, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'G_uest Port:', mnwidget => $gui{d}{PFRule4}{sbGuestPort}}), 0, 5, 1, 1);
    $grid->attach($gui{d}{PFRule4}{sbGuestPort}, 1, 5, 1, 1);
}

# Build the IPv6 PortFordwarding dialog
sub build_dialogPFRule6 {
    $gui{d}{PFRule6} = &gui_new_dialog({title  => 'Add IPv6 Port-Forwarding Rule',
                                        cancel => TRUE,
                                        ok     => 'Apply'});

    $gui{d}{PFRule6}{entryName} = &gui_new_entry({width  => 35,
                                                  maxlen => 255,
                                                  tip    => 'Name of the port-forwarding rule'});

    $gui{d}{PFRule6}{cboxProtocol} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{ip_protocols}),
                                                              active => 0,
                                                              tip    => 'The protocol for the port-forwarding rule'});

    $gui{d}{PFRule6}{entryHostIP} = &gui_new_entry({width  => 35,
                                                    maxlen => 45,
                                                    tip    => 'The IP of the host to port-forward'});

    $gui{d}{PFRule6}{sbHostPort} = &gui_new_spinbutton({lo     => 1,
                                                        hi     => 65535,
                                                        inc    => 1,
                                                        maxlen => 5,
                                                        tip    => 'The port number on the host to port-forward'});

    $gui{d}{PFRule6}{adjHostPort} = &gui_new_adjustment(undef,, 0, 0, 65535, 1, 10, 0);
    $gui{d}{PFRule6}{sbHostPort}->set_adjustment($gui{d}{PFRule6}{adjHostPort});

    $gui{d}{PFRule6}{entryGuestIP} = &gui_new_entry({width  => 35,
                                                     maxlen => 45,
                                                     tip    => 'The IP of the guest to port-forward to'});

    $gui{d}{PFRule6}{sbGuestPort} = &gui_new_spinbutton({lo     => 1,
                                                         hi     => 65535,
                                                         inc    => 1,
                                                         maxlen => 5,
                                                         tip    => 'The port number on the guest to port-forward to'});

    $gui{d}{PFRule6}{adjGuestPort} = &gui_new_adjustment(undef, 0, 0, 65535, 1, 10, 0);
    $gui{d}{PFRule6}{sbGuestPort}->set_adjustment($gui{d}{PFRule6}{adjGuestPort});
    $gui{d}{PFRule6}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Name:', mnwidget => $gui{d}{PFRule6}{entryName}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{PFRule6}{entryName}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Protocol:', mnwidget => $gui{d}{PFRule6}{cboxProtocol}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{PFRule6}{cboxProtocol}, 1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Host IP:', mnwidget => $gui{d}{PFRule6}{entryHostIP}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{PFRule6}{entryHostIP}, 1, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'H_ost Port:', mnwidget => $gui{d}{PFRule6}{sbHostPort}}), 0, 3, 1, 1);
    $grid->attach($gui{d}{PFRule6}{sbHostPort}, 1, 3, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Guest IP:', mnwidget => $gui{d}{PFRule6}{entryGuestIP}}), 0, 4, 1, 1);
    $grid->attach($gui{d}{PFRule6}{entryGuestIP}, 1, 4, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'G_uest Port:', mnwidget => $gui{d}{PFRule6}{sbGuestPort}}), 0, 5, 1, 1);
    $grid->attach($gui{d}{PFRule6}{sbGuestPort}, 1, 5, 1, 1);
}

# Build Host Only Network dialog
sub build_dialogHON {
    $gui{d}{HON} = &gui_new_dialog({title  => 'Host-Only Network Manager',
                                    cancel => TRUE});

    $gui{d}{HON}{entryIPV4Addr} = &gui_new_entry({width  => 39,
                                                  maxlen => 15,
                                                  tip    => 'The IP address of the host for this adapter'});

    $gui{d}{HON}{entryIPV4Netmask} = &gui_new_entry({width  => 39,
                                                     maxlen => 15,
                                                     tip    => 'The netmask of the host for this adapter'});

    $gui{d}{HON}{entryIPV6Addr} = &gui_new_entry({width  => 39,
                                                  maxlen => 39,
                                                  tip    => 'The IPv6 address of the host for this adapter'});

    $gui{d}{HON}{entryIPV6Netmask} = &gui_new_entry({width  => 39,
                                                     maxlen => 3,
                                                     tip    => 'The IPv6 netmask of the host for this adapter'});

    $gui{d}{HON}{checkEnableDHCP} = &gui_new_check({text   => '_Enable Server',
                                                    active => FALSE,
                                                    tip    => 'Enable the DHCP Server'});

    $gui{d}{HON}{entryServerAddr} = &gui_new_entry({width  => 39,
                                                    maxlen => 15,
                                                    tip    => 'The IP address of the DHCP server assigned to this adapter'});

    $gui{d}{HON}{entryServerNetmask} = &gui_new_entry({width  => 39,
                                                       maxlen => 15,
                                                       tip    => 'The netmask of the DHCP server assigned to this adapter'});

    $gui{d}{HON}{entryLowerBound} = &gui_new_entry({width  => 39,
                                                    maxlen => 15,
                                                    tip    => 'The lowest assignable IP address in the range'});

    $gui{d}{HON}{entryUpperBound} = &gui_new_entry({width  => 39,
                                                    maxlen => 15,
                                                    tip    => 'The highest assignable IP address in the range'});

    my $box = &gui_new_box({orientation => 'vertical'});
    $gui{d}{HON}{gridDHCP} = &gui_new_grid();
    my $notebook = Gtk3::Notebook->new();
    $notebook->append_page(my $grid = &gui_new_grid(), &gui_new_widgetlabel({text => '_Adapter'}));
    $notebook->append_page($box, &gui_new_widgetlabel({text => '_DHCP Server'}));
    $notebook->show_all();
    $box->pack_start($gui{d}{HON}{checkEnableDHCP}, TRUE, TRUE, 0);
    $box->pack_start($gui{d}{HON}{gridDHCP}, TRUE, TRUE, 0);
    $gui{d}{HON}->get_content_area()->add($notebook);
    $grid->attach(&gui_new_widgetlabel({text => '_IPv4 Address:', mnwidget => $gui{d}{HON}{entryIPV4Addr}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{HON}{entryIPV4Addr}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'IPv4 _Network:', mnwidget => $gui{d}{HON}{entryIPV4Netmask}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{HON}{entryIPV4Netmask}, 1, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'I_Pv6 Address:', mnwidget => $gui{d}{HON}{entryIPV6Addr}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{HON}{entryIPV6Addr}, 1, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'IPv6 Netmask _Length:', mnwidget => $gui{d}{HON}{entryIPV6Netmask}}), 0, 3, 1, 1);
    $grid->attach($gui{d}{HON}{entryIPV6Netmask}, 1, 3, 1, 1);
    $grid->attach($gui{d}{HON}{checkEnableDHCP}, 0, 0, 2, 1);
    $gui{d}{HON}{gridDHCP}->attach(&gui_new_widgetlabel({text => 'Server Add_ress:', mnwidget => $gui{d}{HON}{entryServerAddr}}), 0, 1, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach($gui{d}{HON}{entryServerAddr}, 1, 1, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach(&gui_new_widgetlabel({text => 'Server _Netmask:', mnwidget => $gui{d}{HON}{entryServerNetmask}}), 0, 2, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach($gui{d}{HON}{entryServerNetmask}, 1, 2, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach(&gui_new_widgetlabel({text => '_Lower Address Bound:', mnwidget => $gui{d}{HON}{entryLowerBound}}), 0, 3, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach($gui{d}{HON}{entryLowerBound}, 1, 3, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach(&gui_new_widgetlabel({text => '_Upper Address Bound:', mnwidget => $gui{d}{HON}{entryUpperBound}}), 0, 4, 1, 1);
    $gui{d}{HON}{gridDHCP}->attach($gui{d}{HON}{entryUpperBound}, 1, 4, 1, 1);
}

# Build Set Group Dialog
sub build_dialogSetGroup {
    $gui{d}{SetGroup} = &gui_new_dialog({title  => 'Set Group Membership',
                                         cancel => TRUE});

    $gui{d}{SetGroup}{entryGroup} = &gui_new_entry({width  => 50,
                                                    maxlen => 255,
                                                    tip    => 'Set the group membership for the guest. Groups are dynamically created and destroyed as needed'});

    $gui{d}{SetGroup}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Group:', mnwidget => $gui{d}{SetGroup}{entryGroup}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{SetGroup}{entryGroup}, 1, 0, 1, 1);
    $grid->attach(&gui_new_markuplabel({text => "Subgroups must be separated with /\n<i>Example: /GroupA/SubGroup/SubSubGroup</i>\nNew groups are dynamically created and empty groups automatically destroyed."}), 1, 1, 1, 1);
}

# Build the VB Prefs dialog
sub build_dialogVBPrefs {
    $gui{d}{VBPrefs} = &gui_new_dialog({title  => 'VirtualBox Preferences',
                                        cancel => TRUE,
                                        ok     => 'Save'});

    $gui{d}{VBPrefs}{entryMachineFolder} = &gui_new_entry({width  => 35,
                                                           tip    => 'The default path where guests are created. This location must be accessible by the server'});

    my $buttonfolder1 = &gui_new_imgbutton({image => 'sf_16px.png',
                                            tip   => 'Choose the default machine folder'});

    $gui{d}{VBPrefs}{buttonMachineReset} = &gui_new_imgbutton({image => 'reset_defmacfolder_16px.png',
                                                               tip   => 'Reset the machine folder to the default value'});

    $gui{d}{VBPrefs}{entryDatabaseFolder} = &gui_new_entry({width  => 35,
                                                            tip    => "Folder containing the autostart database.\n* Server configuration is required for this option. See the RemoteBox manual\n* The autostart database folder should be set the same as the server's configuration"});

    my $buttonfolder2 = &gui_new_imgbutton({image => 'sf_16px.png',
                                            tip   => 'Choose the autostart database folder'});

    $gui{d}{VBPrefs}{entryVRDPLib} = &gui_new_entry({width  => 35,
                                                     tip    => "The default VRDP (Remote Display) authentication library to use. The library must be accessible by the server\n* Do not specify the .dll or .so suffix.\n* If unsure, specify VBoxAuth"});

    $gui{d}{VBPrefs}{buttonVRDPLibReset} = &gui_new_imgbutton({image => 'reset_defmacfolder_16px.png',
                                                               tip   => 'Reset the VRDP Authentication Library to the default'});

    $gui{d}{VBPrefs}{checkExclusive} = &gui_new_check({text   => '_Hardware Virtualization Exclusive to VirtualBox',
                                                       active => FALSE,
                                                       tip    => "Permits the use of alternative hypervisors alongside VirtualBox\n* Disable if your server runs other hypervisors\n* Enable if your server only runs VirtualBox"});

    $gui{d}{VBPrefs}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Default _Machine Folder:', mnwidget => $gui{d}{VBPrefs}{entryMachineFolder}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{entryMachineFolder}, 1, 0, 1, 1);
    $grid->attach($buttonfolder1, 2, 0, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{buttonMachineReset}, 3, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Autostart Database Folder:', mnwidget => $gui{d}{VBPrefs}{entryDatabaseFolder}}), 0, 1, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{entryDatabaseFolder}, 1, 1, 1, 1);
    $grid->attach($buttonfolder2, 2, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_VRDP Authentication Library:', mnwidget => $gui{d}{VBPrefs}{entryVRDPLib}}), 0, 2, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{entryVRDPLib}, 1, 2, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{buttonVRDPLibReset}, 2, 2, 1, 1);
    $grid->attach($gui{d}{VBPrefs}{checkExclusive}, 1, 3, 3, 1);

    $buttonfolder1->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Machine Folder',
                                                                            entrywidget => \$gui{d}{VBPrefs}{entryMachineFolder},
                                                                            mode        => 'dir',
                                                                            filter      => ' ^',
                                                                            callback    => \&handle_remote_folder_entry});

    $buttonfolder2->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Autostart Database Folder',
                                                                            entrywidget => \$gui{d}{VBPrefs}{entryDatabaseFolder},
                                                                            mode        => 'dir',
                                                                            filter      => ' ^',
                                                                            callback    => \&handle_remote_folder_entry});

    $gui{d}{VBPrefs}{buttonMachineReset}->signal_connect('clicked' => \&vbprefs_reset);
    $gui{d}{VBPrefs}{buttonVRDPLibReset}->signal_connect('clicked' => \&vbprefs_reset);
}

# Build the Snapshot Dialog
sub build_dialogSnapshot {
    $gui{d}{Snapshot} = &gui_new_dialog({title  => 'Snapshot Properties',
                                         cancel => TRUE,
                                         ok     => 'Save'});

    $gui{d}{Snapshot}{Name} = &gui_new_entry({width  => 50,
                                              maxlen => 255,
                                              tip    => 'The name of the snapshot'});

    $gui{d}{Snapshot}{tbDescription} = &gui_new_textbuffer(undef);

    my $tv1 = &gui_new_textview({editable => TRUE,
                                 buffer   => $gui{d}{Snapshot}{tbDescription},
                                 tip      => 'The snapshot description'});

    $gui{d}{Snapshot}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => 'Snapshot _Name:', mnwidget => $gui{d}{Snapshot}{Name}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{Snapshot}{Name}, 1, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Description:', mnwidget => $tv1}), 0, 1, 1, 1);
    $grid->attach(my $scrollwin1 = &gui_new_scrolledwindow(), 1, 1, 1, 1);
    $scrollwin1->add_with_viewport($tv1);
}

# Build the Create HD Dialog
sub build_dialogCreateHD {
    $gui{d}{CreateHD} = &gui_new_dialog({title   => 'Create Hard Disk Image',
                                         cancel  => TRUE,
                                         ok      => 'Create',
                                         okimage => &gui_new_img_from_file('dialog_create_hd_16px.png')});

    $gui{d}{CreateHD}{entryImage} = &gui_new_entry({width  => 35,
                                                    tip    => 'The hard disk image filename, without extension'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the destination and file name'});

    $gui{d}{CreateHD}{sbSize} = &gui_new_spinbutton({lo        => 4.00,
                                                     hi        => 2097152.00,
                                                     inc       => 1.00,
                                                     decplaces => 2,
                                                     numeric   => FALSE,
                                                     tip       => 'The size of the hard disk'});

    $gui{d}{CreateHD}{cboxFormat} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{hd_img_formats}),
                                                             active => 0,
                                                             tip    => "Disk image format to use\n* If unsure, select VDI (VirtualBox Format)"});

    $gui{d}{CreateHD}{radioDynamic} = &gui_new_radio({text   => 'Dynamically _allocated',
                                                      group  => undef,
                                                      active => TRUE,
                                                      tip    => "The Hard disk image is thin provisioned. The image will increase in size as the guest consumes space but does not require the entire disk to be allocated from the start\n* If unsure, choose dynamically allocated"});

    $gui{d}{CreateHD}{radioFixed} = &gui_new_radio({text   => 'F_ixed size',
                                                    group  => $gui{d}{CreateHD}{radioDynamic},
                                                    active => FALSE,
                                                    tip    => "Allocates the entire disk size from the start. The image takes longer to create but can be faster to use than dynamic images\n* Recommended when maximum disk performance is required"});

    $gui{d}{CreateHD}{radioSplit} = &gui_new_radio({text   => 'Split into _2GB files',
                                                    group  => $gui{d}{CreateHD}{radioDynamic},
                                                    active => FALSE,
                                                    tip    => "Splits the hard disk image into 2GB chunks.\n* Only recommended if the hard disk image will be stored on a filesystem that doesn't support files larger than 2GB"});

    $gui{d}{CreateHD}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_new_harddisk.png'), 0, 0, 1, 7);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => '_Disk Image:', mnwidget => $gui{d}{CreateHD}{entryImage}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{CreateHD}{entryImage}, 2, 0, 1, 1);
    $grid->attach($buttonfolder, 3, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Size:', mnwidget => $gui{d}{CreateHD}{sbSize}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{CreateHD}{sbSize}, 2, 1, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Format:', mnwidget => $gui{d}{CreateHD}{cboxFormat}}), 1, 2, 1, 1);
    $grid->attach($gui{d}{CreateHD}{cboxFormat}, 2, 2, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Allocation Mode:'}), 1, 3, 1, 3);
    $grid->attach($gui{d}{CreateHD}{radioDynamic}, 2, 3, 2, 1);
    $grid->attach($gui{d}{CreateHD}{radioFixed}, 2, 4, 2, 1);
    $grid->attach($gui{d}{CreateHD}{radioSplit}, 2, 5, 2, 1);
    $grid->attach(&gui_new_layout(), 4, 6, 1, 1);
    $gui{d}{CreateHD}{cboxFormat}->signal_connect('changed' => \&storage_sens_create_hd);
    $gui{d}{CreateHD}{sbSize}->signal_connect('input' => \&spinbox_bytes_in);
    $gui{d}{CreateHD}{sbSize}->signal_connect('output' => \&spinbox_bytes_out);

    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Destination Hard Disk Image File',
                                                                           entrywidget => \$gui{d}{CreateHD}{entryImage},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build the Copy HD Dialog
sub build_dialogCopyHD {
    $gui{d}{CopyHD} = &gui_new_dialog({title   => 'Copy & Convert Hard Disk Image',
                                       cancel  => TRUE,
                                       ok      => 'Copy',
                                       okimage => &gui_new_img_from_file('hd_copy_16px.png')});

    $gui{d}{CopyHD}{entrySource} = &gui_new_entry({width  => 35,
                                                   tip    => 'The source hard disk image'});

    $gui{d}{CopyHD}{entryDest} = &gui_new_entry({width  => 35,
                                                 tip    => 'The file name of the new hard disk image, without file extension'});

    my $buttonfolder = &gui_new_imgbutton({image => 'sf_16px.png',
                                           tip   => 'Choose the destination and file name of the new hard disk image'});


    $gui{d}{CopyHD}{cboxFormat} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{hd_img_formats}),
                                                           active => 0,
                                                           tip    => "Disk image format to use\n* If unsure, select VDI (VirtualBox Format)"});

    $gui{d}{CopyHD}{radioDynamic} = &gui_new_radio({text   => 'Dynamically _allocated',
                                                    group  => undef,
                                                    active => TRUE,
                                                    tip    => "The Hard disk image is thin provisioned. The image will increase in size as the guest consumes space but does not require the entire disk to be allocated from the start\n* If unsure, choose dynamically allocated"});

    $gui{d}{CopyHD}{radioFixed} = &gui_new_radio({text   => 'F_ixed size',
                                                  group  => $gui{d}{CopyHD}{radioDynamic},
                                                  active => FALSE,
                                                  tip    => "Allocates the entire disk size from the start. The image takes longer to create but can be faster to use than dynamic images\n* Recommended when maximum disk performance is required"});

    $gui{d}{CopyHD}{radioSplit} = &gui_new_radio({text   => 'Split into _2GB files',
                                                  group  => $gui{d}{CopyHD}{radioDynamic},
                                                  active => FALSE,
                                                  tip    => "Splits the hard disk image into 2GB chunks.\n* Only recommended if the hard disk image will be stored on a filesystem that doesn't support files larger than 2GB"});

    $gui{d}{CopyHD}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_new_harddisk.png'), 0, 0, 1, 7);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => 'Source _Disk:', mnwidget => $gui{d}{CopyHD}{entrySource}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{CopyHD}{entrySource}, 2, 0, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_New Disk:', mnwidget => $gui{d}{CopyHD}{entryDest}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{CopyHD}{entryDest}, 2, 1, 1, 1);
    $grid->attach($buttonfolder, 3, 1, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'New _Format:', mnwidget => $gui{d}{CopyHD}{cboxFormat}}), 1, 2, 1, 1);
    $grid->attach($gui{d}{CopyHD}{cboxFormat}, 2, 2, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Allocation Mode:'}), 1, 3, 1, 3);
    $grid->attach($gui{d}{CopyHD}{radioDynamic}, 2, 3, 2, 1);
    $grid->attach($gui{d}{CopyHD}{radioFixed}, 2, 4, 2, 1);
    $grid->attach($gui{d}{CopyHD}{radioSplit}, 2, 5, 2, 1);
    $grid->attach(&gui_new_layout(), 4, 6, 1, 1);
    $gui{d}{CopyHD}{cboxFormat}->signal_connect('changed' => \&sens_copyhdformat);
    $buttonfolder->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'New Hard Disk Image',
                                                                           entrywidget => \$gui{d}{CopyHD}{entryDest},
                                                                           mode        => 'file',
                                                                           filter      => '.*',
                                                                           callback    => \&handle_remote_file_entry});
}

# Build the Progress Dialog
sub build_dialogProgress {
    # We can probably optimise this now with the new dialog function
    $gui{d}{Progress} = Gtk3::Dialog->new('Please wait...', undef, 'GTK_DIALOG_MODAL'); # Transient is determined automatically
    $gui{d}{Progress}->set_type_hint('GDK_WINDOW_TYPE_HINT_DIALOG');
    $gui{d}{Progress}->set_skip_taskbar_hint(TRUE);
    $gui{d}{Progress}{buttonCancel} = $gui{d}{Progress}->add_button('Cancel', 'cancel');
    $gui{d}{Progress}->set_position('GTK_WIN_POS_CENTER_ON_PARENT');
    $gui{d}{Progress}->set_deletable(FALSE);
    $gui{d}{Progress}->set_default_response('cancel');
    $gui{d}{Progress}->set_icon_name("$sharedir/icons/remotebox.png");
    $gui{d}{Progress}->signal_connect('hide' => \&transwin_sens_on, $gui{d}{Progress});
    $gui{d}{Progress}->signal_connect('show' => \&transwin_sens_off, $gui{d}{Progress});
    my $spinner = Gtk3::Spinner->new();
    $spinner->set_hexpand(TRUE);
    $spinner->start();
    $spinner->show();
    $gui{d}{Progress}{bar} = Gtk3::ProgressBar->new();
    $gui{d}{Progress}{bar}->set_hexpand(TRUE);
    $gui{d}{Progress}{bar}->set_pulse_step(0.1);
    $gui{d}{Progress}{bar}->show();
    $gui{d}{Progress}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach($gui{d}{Progress}{img} = &gui_new_img_from_file('progress_refresh_90px.png'), 0, 0, 1, 4);
    $gui{d}{Progress}{img}->set_alignment(0.0, 0.0);
    $grid->attach($gui{d}{Progress}{label} = &gui_new_markuplabel({text => 'Please Wait...'}), 1, 0, 1, 1);
    $grid->attach($spinner, 1, 1, 1, 1);
    $grid->attach($gui{d}{Progress}{bar}, 1, 2, 1, 1);
}

# Build the ServerInfo Dialog
sub build_dialogServerInfo {
    $gui{d}{ServerInfo} = &gui_new_dialog({title => 'Server Information'});
    $gui{d}{ServerInfo}->set_default_size(600,800);
    $gui{d}{ServerInfo}->get_content_area()->add(my $scrollwin1 = &gui_new_scrolledwindow());
    $gui{d}{ServerInfo}{lstoreInfo} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::Uint', 'Glib::Double']);
    my $treeview = &gui_new_treeview({model   => $gui{d}{ServerInfo}{lstoreInfo},
                                      headers => FALSE,
                                      tip     => 'Information about the VirtualBox server'});

    $treeview->get_selection->set_mode('GTK_SELECTION_NONE');
    $treeview->append_column(&gui_new_treeviewcolumn({title   => 'Field',
                                        type    => 'text',
                                        typecol => 0}));

    $treeview->append_column(&gui_new_treeviewcolumn({title   => 'Value',
                                        type    => 'text',
                                        typecol => 1}));

    $scrollwin1->set_propagate_natural_height(TRUE);
    $scrollwin1->set_propagate_natural_width(TRUE);
    $scrollwin1->add_with_viewport($treeview);
}

# Build the Host Network Manager dialog
sub build_dialogHostNetMan {
    $gui{d}{HostNetMan} = &gui_new_dialog({title => 'Network Manager'});
    $gui{d}{HostNetMan}->set_default_size(400,400);
    my $notebook = Gtk3::Notebook->new();
    $notebook->append_page(my $grid1 = &gui_new_grid(), &gui_new_widgetlabel({text => '_Host-Only Networks'}));
    $notebook->append_page(my $grid2 = &gui_new_grid(), &gui_new_widgetlabel({text => '_NAT Networks_'}));
    $notebook->show_all();
    my $bb1 = &gui_new_buttonbox({orientation => 'vertical'});
    $bb1->add(my $buttonAddHON = &gui_new_imgbutton({image => 'add_host_iface_16px.png',
                                                     tip   => 'Add a Host-Only network'}));

    $bb1->add($gui{d}{HostNetMan}{buttonDelHON} = &gui_new_imgbutton({image => 'remove_host_iface_16px.png',
                                                                      tip   => 'Delete Host-Only network'}));

    $bb1->add($gui{d}{HostNetMan}{buttonEditHON}= &gui_new_imgbutton({image => 'host_iface_edit_16px.png',
                                                                      tip   => 'Edit Host-Only network'}));

    my $bb2 = &gui_new_buttonbox({orientation => 'vertical'});
    $bb2->add(my $buttonAddNAT = &gui_new_imgbutton({image => 'add_host_iface_16px.png',
                                                     tip   => 'Add a NAT network'}));

    $bb2->add($gui{d}{HostNetMan}{buttonDelNAT} = &gui_new_imgbutton({image => 'remove_host_iface_16px.png',
                                                                      tip   => 'Delete NAT network'}));

    $bb2->add($gui{d}{HostNetMan}{buttonEditNAT} = &gui_new_imgbutton({image => 'host_iface_edit_16px.png',
                                                                       tip   => 'Edit NAT network'}));

    $gui{d}{HostNetMan}{lstoreHON} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String']);
    $gui{d}{HostNetMan}{treeviewHON} = &gui_new_treeview({model   => $gui{d}{HostNetMan}{lstoreHON},
                                                          headers => TRUE,
                                                          tip     => 'The list of available Host-Only networks'});

    $gui{d}{HostNetMan}{treeviewHON}->append_column(&gui_new_treeviewcolumn({title   => 'Host-Only Networks',
                                                                             type    => 'text',
                                                                             typecol => 0}));

    $gui{d}{HostNetMan}{treeviewNAT} = &gui_new_treeview({model => $gui{d}{HostNetMan}{lstoreNAT} = &gui_new_lstore(undef, ['Glib::Boolean', 'Glib::String', 'Glib::String']),
                                                          tip   => 'The list of available NAT networks'});

    my ($col, $celltoggle) = &gui_new_treeviewcolumntoggle({title   => 'Enabled',
                                                            type    => 'active',
                                                            typecol => 0});
    $gui{d}{HostNetMan}{treeviewNAT}->append_column($col);
    $gui{d}{HostNetMan}{treeviewNAT}->append_column(&gui_new_treeviewcolumn({title  => '',
                                                                             type    => 'text',
                                                                             typecol => 1}));

    $gui{d}{HostNetMan}->get_content_area()->add($notebook);
    $grid1->attach(my $scrollwin1 = &gui_new_scrolledwindow(), 0, 0, 1, 1);
    $scrollwin1->add_with_viewport($gui{d}{HostNetMan}{treeviewHON});
    $grid1->attach($bb1, 1, 0, 1, 1);
    $grid2->attach(my $scrollwin2 = &gui_new_scrolledwindow(), 0, 0, 1, 1);
    $scrollwin2->add_with_viewport($gui{d}{HostNetMan}{treeviewNAT});
    $grid2->attach($bb2, 1, 0, 1, 1);
    $buttonAddHON->signal_connect('clicked' => \&vbprefs_createhon);
    $gui{d}{HostNetMan}{buttonDelHON}->signal_connect('clicked' => \&vbprefs_removehon);
    $gui{d}{HostNetMan}{buttonEditHON}->signal_connect('clicked' => \&show_dialog_edithon);
    $buttonAddNAT->signal_connect('clicked' => \&vbprefs_createnat);
    $gui{d}{HostNetMan}{buttonDelNAT}->signal_connect('clicked' => \&vbprefs_removenat);
    $gui{d}{HostNetMan}{buttonEditNAT}->signal_connect('clicked' => \&show_dialog_editnat);
    $signal{HostNetMan_treeviewHON_cursorChanged} = $gui{d}{HostNetMan}{treeviewHON}->signal_connect('cursor-changed' => \&onsel_list_vbprefshon);
    $signal{HostNetMan_treeviewNAT_cursorChanged} = $gui{d}{HostNetMan}{treeviewNAT}->signal_connect('cursor-changed' => \&onsel_list_vbprefsnat),
    $gui{d}{HostNetMan}{treeviewHON}->signal_connect('row-activated' => \&show_dialog_edithon);
    $gui{d}{HostNetMan}{treeviewNAT}->signal_connect('row-activated' => \&show_dialog_editnat);
    $celltoggle->signal_connect('toggled' => \&vbprefs_togglenat);
}

# Build the guest log diaglog
sub build_dialogGuestLog {
    $gui{d}{GuestLog} = &gui_new_dialog({title => 'Guest Log Viewer'});
    $gui{d}{GuestLog}->set_default_size(600,600);
    my $toolbar = &gui_new_toolbar();
    $toolbar->insert(my $toolbutton1 = &gui_new_toolbutton({image => 'log_viewer_save_32px.png',
                                                            label => '_Save',
                                                            tip   => 'Save the log to a text file'}), 0);

    $toolbar->insert(my $toolbutton2 = &gui_new_toolbutton({image => 'log_viewer_refresh_32px.png',
                                                            label => '_Refresh',
                                                            tip  => 'Refresh the guest logs'}), 1);

    $gui{d}{GuestLog}{lstoreLog0} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::Uint']); #Log, Category, Value Weight
    $gui{d}{GuestLog}{lstoreLog1} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::Uint']); #Log, Category, Value Weight
    $gui{d}{GuestLog}{lstoreLog2} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::Uint']); #Log, Category, Value Weight
    $gui{d}{GuestLog}{lstoreLog3} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::Uint']); #Log, Category, Value Weight

    my $treeview1 = &gui_new_treeview({model   => $gui{d}{GuestLog}{lstoreLog0},
                                       headers => FALSE,
                                       tip     => 'VirtualBox Guest Log 0'});

    $treeview1->get_selection->set_mode('GTK_SELECTION_NONE');
    $treeview1->append_column(&gui_new_treeviewcolumn({title   => 'Category',
                                                       type    => 'text',
                                                       typecol => 1}));

    $treeview1->append_column(&gui_new_treeviewcolumn({title   => 'Value',
                                                       type    => 'text',
                                                       typecol => 0}));

    my $treeview2 = &gui_new_treeview({model   => $gui{d}{GuestLog}{lstoreLog1},
                                       headers => FALSE,
                                       tip     => 'VirtualBox Guest Log 1'});

    $treeview2->get_selection->set_mode('GTK_SELECTION_NONE');
    $treeview2->append_column(&gui_new_treeviewcolumn({title   => 'Category',
                                                       type    => 'text',
                                                       typecol => 1}));

    $treeview2->append_column(&gui_new_treeviewcolumn({title   => 'Value',
                                                       type    => 'text',
                                                       typecol => 0}));

    my $treeview3 = &gui_new_treeview({model   => $gui{d}{GuestLog}{lstoreLog2},
                                       headers => FALSE,
                                       tip     => 'VirtualBox Guest Log 2'});

    $treeview3->get_selection->set_mode('GTK_SELECTION_NONE');
    $treeview3->append_column(&gui_new_treeviewcolumn({title   => 'Category',
                                                       type    => 'text',
                                                       typecol => 1}));

    $treeview3->append_column(&gui_new_treeviewcolumn({title   => 'Value',
                                                       type    => 'text',
                                                       typecol => 0}));

    my $treeview4 = &gui_new_treeview({model   => $gui{d}{GuestLog}{lstoreLog3},
                                       headers => FALSE,
                                       tip     => 'VirtualBox Guest Log 3'});

    $treeview4->get_selection->set_mode('GTK_SELECTION_NONE');
    $treeview4->append_column(&gui_new_treeviewcolumn({title   => 'Category',
                                                       type    => 'text',
                                                       typecol => 1}));

    $treeview4->append_column(&gui_new_treeviewcolumn({title   => 'Value',
                                                       type    => 'text',
                                                       typecol => 0}));

    $gui{d}{GuestLog}{notebookLog} = Gtk3::Notebook->new();
    $gui{d}{GuestLog}{notebookLog}->append_page(my $scrollwin1 = &gui_new_scrolledwindow(), &gui_new_widgetlabel({text => 'Log _0'}));
    $scrollwin1->set_propagate_natural_height(TRUE);
    $scrollwin1->set_propagate_natural_width(TRUE);
    $scrollwin1->add_with_viewport($treeview1);
    $gui{d}{GuestLog}{notebookLog}->append_page(my $scrollwin2 = &gui_new_scrolledwindow(), &gui_new_widgetlabel({text => 'Log _1'}));
    $scrollwin2->set_propagate_natural_height(TRUE);
    $scrollwin2->set_propagate_natural_width(TRUE);
    $scrollwin2->add_with_viewport($treeview2);
    $gui{d}{GuestLog}{notebookLog}->append_page(my $scrollwin3 = &gui_new_scrolledwindow(), &gui_new_widgetlabel({text => 'Log _2'}));
    $scrollwin3->set_propagate_natural_height(TRUE);
    $scrollwin3->set_propagate_natural_width(TRUE);
    $scrollwin3->add_with_viewport($treeview3);
    $gui{d}{GuestLog}{notebookLog}->append_page(my $scrollwin4 = &gui_new_scrolledwindow(), &gui_new_widgetlabel({text => 'Log _3'}));
    $scrollwin4->set_propagate_natural_height(TRUE);
    $scrollwin4->set_propagate_natural_width(TRUE);
    $scrollwin4->add_with_viewport($treeview4);
    $gui{d}{GuestLog}{notebookLog}->show_all();
    $gui{d}{GuestLog}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach($toolbar, 0, 0, 1, 1);
    $grid->attach($gui{d}{GuestLog}{notebookLog}, 0, 1, 1, 1);
    $toolbutton1->signal_connect('clicked' => \&guest_log_save);
    $toolbutton2->signal_connect('clicked' => \&refresh_guest_logs);
}

# Build the Profiles dialog
sub build_dialogProfile {
    $gui{d}{Profile} = &gui_new_dialog({title => 'Connection Profile Manager'});
    $gui{d}{Profile}{treeviewProfile} = &gui_new_treeview({model   => $gui{d}{Connect}{lstoreProfile}, # Note, is correct as it's shared with the connection dialog
                                                           headers => FALSE,
                                                           tip     => 'List of connection profiles'});

    $gui{d}{Profile}{treeviewProfile}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                              type    => 'text',
                                                                              typecol => 0}));

    $gui{d}{Profile}{entryName} = &gui_new_entry({width  => 60,
                                                  maxlen => 255,
                                                  tip    => 'The name to assign the connection profile'});

    $gui{d}{Profile}{entryURL} = &gui_new_entry({width => 60,
                                                 tip   => 'The URL of the VirtualBox server. For example http://myserver:18083'});

    $gui{d}{Profile}{entryUser} = &gui_new_entry({width => 60,
                                                  tip   => 'The user to connect as. Leave blank if authentication is disabled on the server'});

    $gui{d}{Profile}{entryPass} = &gui_new_entry({width => 60,
                                                  tip   => 'The user password. Leave blank if authentication is disabled on the server',
                                                  pass  => TRUE});

    $gui{d}{Profile}{checkAutoConnect} = &gui_new_check({text   => 'Auto-_Connect on Start',
                                                         active => FALSE,
                                                         tip    => 'Automatically connect with this profile when RemoteBox starts'});

    $gui{d}{Profile}->get_content_area()->add(my $box = &gui_new_box({orientation => 'horizontal'}));
    $box->pack_start(my $grid = &gui_new_grid(), TRUE, TRUE, 0);
    $box->pack_start($gui{d}{Profile}{gridProfile} = &gui_new_grid(), TRUE, TRUE, 0);
    $grid->attach(my $scrollwin1 = &gui_new_scrolledwindow(), 0, 0, 2, 5);
    $scrollwin1->set_propagate_natural_height(TRUE);
    $scrollwin1->set_propagate_natural_width(TRUE);
    $scrollwin1->add_with_viewport($gui{d}{Profile}{treeviewProfile});
    $grid->attach(my $button = &gui_new_button({label => '_Add Profile', tip => 'Add a new connection profile'}), 0, 6, 1, 1);
    $grid->attach($gui{d}{Profile}{buttonDelete} = &gui_new_button({label => '_Delete Profile', tip => 'Delete selected connection profile'}), 1, 6, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach(&gui_new_widgetlabel({text => 'P_rofile Name:', mnwidget => $gui{d}{Profile}{entryName}}), 0, 0, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach($gui{d}{Profile}{entryName}, 1, 0, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach(&gui_new_widgetlabel({text => '_URL:', mnwidget => $gui{d}{Profile}{entryURL}}), 0, 1, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach($gui{d}{Profile}{entryURL}, 1, 1, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach(&gui_new_widgetlabel({text => 'User_name:', mnwidget => $gui{d}{Profile}{entryUser}}), 0, 2, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach($gui{d}{Profile}{entryUser}, 1, 2, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach(&gui_new_widgetlabel({text => '_Password:', mnwidget => $gui{d}{Profile}{entryPass}}), 0, 3, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach($gui{d}{Profile}{entryPass}, 1, 3, 1, 1);
    $gui{d}{Profile}{gridProfile}->attach($gui{d}{Profile}{checkAutoConnect}, 1, 4, 1, 1);
    $gui{d}{Profile}{treeviewProfile}->signal_connect('cursor-changed' => \&onsel_list_profile);
    $button->signal_connect('clicked' => \&addrow_profile);
    $gui{d}{Profile}{buttonDelete}->signal_connect('clicked' => \&remove_profile);
    $gui{d}{Profile}{checkAutoConnect}->signal_connect('toggled' => \&profile_autoconn_change);

}

# Build the new guest dialog
sub build_dialogNew {
    $gui{d}{New} = &gui_new_dialog({title   => 'Create New Guest',
                                    cancel  => TRUE,
                                    ok      => 'Create',
                                    okimage => &gui_new_img_from_file('dialog_create_new_guest_16px.png')});

    $gui{d}{New}{entryName} = &gui_new_entry({width  => 50,
                                              maxlen => 255,
                                              tip    => 'The unique name of the guest'});

    $gui{d}{New}{cboxISO} = &gui_new_simplecombobox({model  => $gui{d}{New}{lstoreISO} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String']), # New Guest ISO 'ISO Name', 'IMedium'
                                                     active => 0,
                                                     tip    => 'Attach an ISO image to use with installation'});

    $gui{d}{New}{cboxFamily} = &gui_new_imgcombobox({model  => $gui{d}{New}{lstoreFamily} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']),
                                                     imgcol => 2,
                                                     active => 0,
                                                     tip    => 'The operating system family the guest will run'});

    $gui{d}{New}{cboxVersion} = &gui_new_imgcombobox({model => $gui{d}{New}{lstoreVersion} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']),
                                                     imgcol => 3,
                                                     active => 0,
                                                     tip    => 'The version of the operating system the guest will run'});

    $gui{d}{New}{sbMemory} = &gui_new_spinbutton({lo        => 4.00,
                                                  hi        => 2097152.00,
                                                  inc       => 1.00,
                                                  decplaces => 2,
                                                  numeric   => FALSE,
                                                  tip       => 'The amount of memory to assign the guest'});

    $gui{d}{New}{scaleMemory} = &gui_new_scale({adj => $gui{d}{New}{sbMemory}->get_adjustment()});

    $gui{d}{New}{checkStartupDisk} = &gui_new_check({text   => 'Start-up _Disk',
                                                     active => TRUE,
                                                     tip    => 'Provide the guest with a start-up hard disk'});

    $gui{d}{New}{radioNewDisk} = &gui_new_radio({text => '_Create a new hard disk',
                                                 group  => undef,
                                                 active => TRUE,
                                                 tip    => 'Create a new hard disk image'});

    $gui{d}{New}{radioExistingDisk} = &gui_new_radio({text => '_Use an existing hard disk',
                                                 group  => $gui{d}{New}{radioNewDisk},
                                                 active => FALSE,
                                                 tip    => 'Use an existing hard disk image'});

    $gui{d}{New}{sbSize} = &gui_new_spinbutton({lo        => 4.00,
                                                hi        => 2097152.00,
                                                inc       => 1.00,
                                                decplaces => 2,
                                                numeric   => FALSE,
                                                tip       => 'The size of the hard disk'});

    $gui{d}{New}{cboxFormat} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{hd_img_formats}),
                                                        active => 0,
                                                        tip    => "Disk image format to use\n* If unsure, select VDI (VirtualBox Format)"});

    $gui{d}{New}{radioDynamic} = &gui_new_radio({text   => 'Dynamically _allocated',
                                                 group  => undef,
                                                 active => TRUE,
                                                 tip    => "The Hard disk image is thin provisioned. The image will increase in size as the guest consumes space but does not require the entire disk to be allocated from the start\n* If unsure, choose dynamically allocated"});

    $gui{d}{New}{radioFixed} = &gui_new_radio({text   => 'F_ixed size',
                                               group  => $gui{d}{New}{radioDynamic},
                                               active => FALSE,
                                               tip    => "Allocates the entire disk size from the start. The image takes longer to create but can be faster to use than dynamic images\n* Recommended when maximum disk performance is required"});

    $gui{d}{New}{radioSplit} = &gui_new_radio({text   => 'Split into _2GB files',
                                               group  => $gui{d}{New}{radioDynamic},
                                               active => FALSE,
                                               tip    => "Splits the hard disk image into 2GB chunks.\n* Only recommended if the hard disk image will be stored on a filesystem that doesn't support files larger than 2GB"});

    $gui{d}{New}{cboxExistingDisk} = &gui_new_simplecombobox({model  => $gui{d}{New}{lstoreExistingDisk} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String']),
                                                     active => -1,
                                                     tip    => 'The hard disk image to attach to the guest'});

    $gui{d}{New}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_new_welcome.png'), 0, 0, 1, 11);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => '_Name:', mnwidget => $gui{d}{New}{entryName}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{New}{entryName}, 2, 0, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_ISO Image:', mnwidget => $gui{d}{New}{cboxISO}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{New}{cboxISO}, 2, 1, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_OS Family:', mnwidget => $gui{d}{New}{cboxFamily}}), 1, 2, 1, 1);
    $grid->attach($gui{d}{New}{cboxFamily}, 2, 2, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Version:', mnwidget => $gui{d}{New}{cboxVersion}}), 1, 3, 1, 1);
    $grid->attach($gui{d}{New}{cboxVersion}, 2, 3, 2, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_Memory:', mnwidget => $gui{d}{New}{sbMemory}}), 1, 4, 1, 1);
    $grid->attach($gui{d}{New}{scaleMemory}, 2, 4, 1, 1);
    $grid->attach($gui{d}{New}{sbMemory}, 3, 4, 1, 1);
    $grid->attach(&gui_new_separator(), 1, 5, 3, 1);
    $grid->attach($gui{d}{New}{checkStartupDisk}, 1, 6, 3, 1);
    $grid->attach($gui{d}{New}{radioNewDisk}, 1, 7, 3, 1);
    $grid->attach($gui{d}{New}{HD} = &gui_new_grid(), 1, 8, 3, 1);
    $gui{d}{New}{HD}->attach(&gui_new_widgetlabel({text => '_Size:', mnwidget => $gui{d}{New}{sbSize}}), 0, 0, 1, 1);
    $gui{d}{New}{HD}->attach($gui{d}{New}{sbSize}, 1, 0, 1, 1);
    $gui{d}{New}{HD}->attach(&gui_new_widgetlabel({text => '_Image Format:', mnwidget => $gui{d}{New}{cboxFormat}}), 0, 1, 1, 1);
    $gui{d}{New}{HD}->attach($gui{d}{New}{cboxFormat}, 1, 1, 1, 1);
    $gui{d}{New}{HD}->attach(&gui_new_widgetlabel({text => 'Allocation Mode:'}), 0, 4, 1, 1);
    $gui{d}{New}{HD}->attach($gui{d}{New}{radioDynamic}, 1, 3, 1, 1);
    $gui{d}{New}{HD}->attach($gui{d}{New}{radioFixed}, 1, 4, 1, 1);
    $gui{d}{New}{HD}->attach($gui{d}{New}{radioSplit}, 1, 5, 1, 1);
    $grid->attach($gui{d}{New}{radioExistingDisk}, 1, 9, 3, 1);
    $grid->attach($gui{d}{New}{cboxExistingDisk}, 1, 10, 3, 1);
    $gui{d}{New}{sbMemory}->signal_connect('input' => \&spinbox_bytes_in);
    $gui{d}{New}{sbMemory}->signal_connect('output' => \&spinbox_bytes_out);
    $gui{d}{New}{sbSize}->signal_connect('input' => \&spinbox_bytes_in);
    $gui{d}{New}{sbSize}->signal_connect('output' => \&spinbox_bytes_out);
    $gui{d}{New}{checkStartupDisk}->signal_connect('toggled' => \&toggle_newstartupdisk);
    $gui{d}{New}{radioNewDisk}->signal_connect('toggled' => \&newstor_new_exist);
    $gui{d}{New}{cboxFormat}->signal_connect('changed' => \&sens_hdformatchanged);
    $signal{New_cboxFamily_changed} = $gui{d}{New}{cboxFamily}->signal_connect('changed' => \&newgen_osfam, $gui{d}{New}{cboxVersion});
    $signal{New_cboxVersion_changed} = $gui{d}{New}{cboxVersion}->signal_connect('changed' => \&newgen_osver, $gui{d}{New}{cboxFamily});
}

# Build the Modify HD Dialog
sub build_dialogModifyHD {
    $gui{d}{ModifyHD} = &gui_new_dialog({title   => 'Modify & Resize Hard Disk',
                                         cancel  => TRUE,
                                         ok      => 'Apply'});

    $gui{d}{ModifyHD}{entryHD} = &gui_new_entry({width  => 35,
                                                 tip    => 'The hard disk image to modify'});

    $gui{d}{ModifyHD}{cboxType} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{media_state_types}),
                                                           active => -1,
                                                           tip    => "Modify the medium type:\n* Normal - Standard format for hard disks\n* Immutable - Changes to disk are discarded on guest start\n* Writethrough - Directly attached, snapshots are not taken\n* Shareable - Enables concurrent use (eg clustered disks)\n* Multi-Attach - Like Immutable but guests maintain their changesDisk image format to use\n* If unsure, select VDI (VirtualBox Format)"});


    $gui{d}{ModifyHD}{checkResize} = &gui_new_check({text   => '_Resize Hard Disk Image',
                                              active => TRUE,
                                              tip    => "Increase the virtual hard disk size\n* Shrinking the hard disk size is not supported\n* You may still need to increase the file system in the guest"});

    $gui{d}{ModifyHD}{sbSize} = &gui_new_spinbutton({lo        => 4.00,
                                                     hi        => 2097152.00,
                                                     inc       => 1.00,
                                                     decplaces => 2,
                                                     numeric   => FALSE,
                                                     tip       => 'The new size of the hard disk'});

    $gui{d}{ModifyHD}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(my $img = &gui_new_img_from_file('wizard_new_harddisk.png'), 0, 0, 1, 5);
    $img->set_alignment(0.0, 0.0);
    $grid->attach(&gui_new_widgetlabel({text => '_Disk Image:', mnwidget => $gui{d}{ModifyHD}{entryHD}}), 1, 0, 1, 1);
    $grid->attach($gui{d}{ModifyHD}{entryHD}, 2, 0, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => 'Image _Type:', mnwidget => $gui{d}{ModifyHD}{cboxType}}), 1, 1, 1, 1);
    $grid->attach($gui{d}{ModifyHD}{cboxType}, 2, 1, 1, 1);
    $grid->attach($gui{d}{ModifyHD}{checkResize}, 2, 2, 1, 1);
    $grid->attach(&gui_new_widgetlabel({text => '_New Disk Size:', mnwidget => $gui{d}{ModifyHD}{sbSize}}), 1, 3, 1, 1);
    $grid->attach($gui{d}{ModifyHD}{sbSize}, 2, 3, 1, 1);
    $grid->attach(&gui_new_layout(), 2, 4, 1, 1);
    $gui{d}{ModifyHD}{checkResize}->signal_connect('toggled' => \&vmm_modify_sens_resize);
    $gui{d}{ModifyHD}{sbSize}->signal_connect('input' => \&spinbox_bytes_in),
    $gui{d}{ModifyHD}{sbSize}->signal_connect('output' => \&spinbox_bytes_out),
}

# Build the RemoteBox Preferences Dialog
sub build_dialogPrefs {
    $gui{d}{Prefs} = &gui_new_dialog({title  => 'RemoteBox Preferences',
                                      ok     => 'Save',
                                      cancel => TRUE});

    $gui{d}{Prefs}{cboxStop} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{stop_types}),
                                                        active => 0,
                                                        tip    => 'Default action to take when the guest stop button is pressed'});

    $gui{d}{Prefs}{checkAdditions} = &gui_new_check({text   => '_Add the guest additions ISO to the Virtual Media Manager on connection',
                                                     active => TRUE,
                                                     tip    => 'Automatically add the guest additions ISO to the Virtual Media Manager when connecting to a server'});

    $gui{d}{Prefs}{checkSortGuest} = &gui_new_check({text   => '_Sort guest list alphabetically',
                                                     active => TRUE,
                                                     tip    => 'Sort the guest list alphabetically or use natural order'});

    $gui{d}{Prefs}{entryRDP} = &gui_new_entry({width  => 100,
                                               tip    => "The command to call when making RDP connections to guests.\n* Choose a preset or customise your own command\n* Consult the documentation for details of % variable substitutions"});

    $gui{d}{Prefs}{buttonRDPPresets} = &gui_new_button({label => 'Presets',
                                                        tip => 'Select an RDP client preset, or customise your own command'});

    $gui{d}{Prefs}{entryVNC} = &gui_new_entry({width  => 100,
                                               tip    => "The command to call when making VNC connections to guests.\n* Choose a preset or customise your own command\n* Consult the documentation for details of % variable substitutions"});

    $gui{d}{Prefs}{buttonVNCPresets} = &gui_new_button({label => 'Presets',
                                                        tip => 'Select a VNC client preset, or customise your own command'});

    $gui{d}{Prefs}{checkOpenDisplay} = &gui_new_check({text   => "_Open the guest's display at power on",
                                                    active => TRUE,
                                                    tip    => 'When a guest is started, automatically open its display'});

    $gui{d}{Prefs}{checkAutoHint} = &gui_new_check({text   => '_Auto-Hint resolution',
                                                    active => FALSE,
                                                    tip    => 'Sends a resolution hint to the guest in order to set the screen resolution to the desired size. In general this method is unreliable and the best place to set the screen resolution is by using %X and %Y substitutions with the RDP client'});

    $gui{d}{Prefs}{sbWidth} = &gui_new_spinbutton({lo        => 320,
                                                   hi        => 10000.00,
                                                   inc       => 1,
                                                   decplaces => 0,
                                                   numeric   => TRUE,
                                                   tip       => 'Desired display width. This value is used for auto-hints and with the %X substitution'});

    $gui{d}{Prefs}{sbHeight} = &gui_new_spinbutton({lo        => 240,
                                                    hi        => 10000,
                                                    inc       => 1,
                                                    decplaces => 0,
                                                    numeric   => TRUE,
                                                    tip       => 'Desired display height. This value is used for auto-hints and with the %Y substitution'});

    $gui{d}{Prefs}{cboxDepth} = &gui_new_simplecombobox({model  => &gui_new_lstore(undef, ['Glib::String', 'Glib::String'], [0, 1], $lists{custom_video_d}),
                                                         active => 2,
                                                         tip    => 'Desired display depth. A higher depth provides more colours but may be slower and use more bandwidth. This value is used for auto-hints and with the %D substitution'});

    my $notebook = Gtk3::Notebook->new();
    $notebook->append_page(my $grid1 = &gui_new_grid(), &gui_new_imglabel({text => '_General', img => 'machine_16px.png'}));
    $notebook->append_page(my $grid2 = &gui_new_grid(), &gui_new_imglabel({text => 'Guest _Display', img => 'vrdp_16px.png'}));
    $notebook->show_all();
    $gui{d}{Prefs}->get_content_area()->add($notebook);
    $grid1->attach(&gui_new_widgetlabel({text => 'Default Stop _Action:', mnwidget => $gui{d}{Prefs}{cboxStop}}), 0, 0, 1, 1);
    $grid1->attach($gui{d}{Prefs}{cboxStop}, 1, 0, 1, 1);
    $grid1->attach($gui{d}{Prefs}{checkAdditions}, 1, 1, 1, 1);
    $grid1->attach($gui{d}{Prefs}{checkSortGuest}, 1, 2, 1, 1);
    $grid2->attach(&gui_new_markuplabel({text => "<small><b>Server hostname</b> %h, <b>Guest name</b> %n, <b>Guest OS</b> %o, <b>RDP / VNC Port</b> %p,\n<b>Password</b> %P, <b>Username</b> %U, <b>Auto-Hint Resolution (X, Y, Depth)</b> %X, %Y, %D</small>"}), 1, 0, 4, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_RDP Client:', mnwidget => $gui{d}{Prefs}{entryRDP}}), 0, 1, 1, 1);
    $grid2->attach($gui{d}{Prefs}{entryRDP}, 1, 1, 3, 1);
    $grid2->attach($gui{d}{Prefs}{buttonRDPPresets}, 4, 1, 1, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_VNC Client:', mnwidget => $gui{d}{Prefs}{entryVNC}}), 0, 2, 1, 1);
    $grid2->attach($gui{d}{Prefs}{entryVNC}, 1, 2, 3, 1);
    $grid2->attach($gui{d}{Prefs}{buttonVNCPresets}, 4, 2, 1, 1);
    $grid2->attach($gui{d}{Prefs}{checkOpenDisplay}, 1, 3, 3, 1);
    $grid2->attach($gui{d}{Prefs}{checkAutoHint}, 1, 4, 3, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_Width (%X):', mnwidget => $gui{d}{Prefs}{sbWidth}}), 0, 5, 1, 1);
    $grid2->attach($gui{d}{Prefs}{sbWidth}, 1, 5, 1, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_Height (%Y):', mnwidget => $gui{d}{Prefs}{sbHeight}}), 2, 5, 1, 1);
    $grid2->attach($gui{d}{Prefs}{sbHeight}, 3, 5, 1, 1);
    $grid2->attach(&gui_new_widgetlabel({text => '_Depth (%D):', mnwidget => $gui{d}{Prefs}{cboxDepth}}), 0, 6, 1, 1);
    $grid2->attach($gui{d}{Prefs}{cboxDepth}, 1, 6, 3, 1);
    $gui{d}{Prefs}{buttonRDPPresets}->signal_connect('button-release-event' => \&show_rdppreset_menu);
    $gui{d}{Prefs}{buttonVNCPresets}->signal_connect('button-release-event' => \&show_vncpreset_menu);
}

# Built the NAT Details Dialog
sub build_dialogNAT {
    $gui{d}{NAT} = &gui_new_dialog({title  => 'NAT Network Manager',
                                    cancel => TRUE});

    $gui{d}{NAT}->set_default_size(600,500);
    $gui{d}{NAT}{entryName} = &gui_new_entry({width  => 50,
                                              maxlen => 255,
                                              tip    => 'The name assigned to this NAT network'});

    $gui{d}{NAT}{entryCIDR} = &gui_new_entry({width  => 50,
                                              maxlen => 18,
                                              tip    => 'Network and mask definition in CIDR format'});

    $gui{d}{NAT}{checkDHCP} = &gui_new_check({text   => '_Supports DHCP',
                                              active => FALSE,
                                              tip    => 'Enable DHCP support on this network'});

    $gui{d}{NAT}{checkIPv6} = &gui_new_check({text   => '_Supports IPv6',
                                              active => FALSE,
                                              tip    => 'Enable IPv6 on this network'});

    $gui{d}{NAT}{checkRoute} = &gui_new_check({text   => 'Advertise default IPv6 _route',
                                               active => FALSE,
                                               tip    => 'Advertise the default route for IPv6 if it is enabled'});

    $gui{d}{NAT}{treeviewIPv4} = &gui_new_treeview({model => $gui{d}{NAT}{lstoreIPv4} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']),
                                                    tip   => 'Active IPv4 portfordwarding rules on this network'});

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                       type    => 'text',
                                                                       typecol => 0}));

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Protocol',
                                                                       type    => 'text',
                                                                       typecol => 1}));

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Host IP',
                                                                       type    => 'text',
                                                                       typecol => 2}));

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Host Port',
                                                                       type    => 'text',
                                                                       typecol => 3}));

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Guest IP',
                                                                       type    => 'text',
                                                                       typecol => 4}));

    $gui{d}{NAT}{treeviewIPv4}->append_column(&gui_new_treeviewcolumn({title   => 'Guest Port',
                                                                       type    => 'text',
                                                                       typecol => 5}));

    $gui{d}{NAT}{treeviewIPv6} = &gui_new_treeview({model => $gui{d}{NAT}{lstoreIPv6} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']),
                                                    tip   => 'Active IPv6 portfordwarding rules on this network'});

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                       type    => 'text',
                                                                       typecol => 0}));

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Protocol',
                                                                       type    => 'text',
                                                                       typecol => 1}));

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Host IP',
                                                                       type    => 'text',
                                                                       typecol => 2}));

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Host Port',
                                                                       type    => 'text',
                                                                       typecol => 3}));

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Guest IP',
                                                                       type    => 'text',
                                                                       typecol => 4}));

    $gui{d}{NAT}{treeviewIPv6}->append_column(&gui_new_treeviewcolumn({title   => 'Guest Port',
                                                                       type    => 'text',
                                                                       typecol => 5}));

    my $notebook = Gtk3::Notebook->new();
    $notebook->append_page(my $grid2 = &gui_new_grid(), &gui_new_widgetlabel({text => 'IPv_4'}));
    $notebook->append_page(my $grid3 = &gui_new_grid(), &gui_new_widgetlabel({text => 'IPv_6'}));
    $notebook->show_all();
    my $bb1 = &gui_new_buttonbox({orientation => 'vertical'});
    $bb1->add(my $buttonAdd4 = &gui_new_imgbutton({image => 'rule_add_16px.png',
                                                   tip   => 'Add an IPv4 Port Forwarding Rule'}));

    $bb1->add($gui{d}{NAT}{buttonEdit4} = &gui_new_imgbutton({image => 'rule_edit_16px.png',
                                                              tip   => 'Edit an IPv4 Port Forwarding Rule'}));

    $bb1->add($gui{d}{NAT}{buttonRemove4} = &gui_new_imgbutton({image => 'rule_remove_16px.png',
                                                                tip   => 'Remove an  IPv4 Port Forwarding Rule'}));

    my $bb2 = &gui_new_buttonbox({orientation => 'vertical'});
    $bb2->add(my $buttonAdd6 = &gui_new_imgbutton({image => 'rule_add_16px.png',
                                                   tip   => 'Add an IPv6 Port Forwarding Rule'}));

    $bb2->add($gui{d}{NAT}{buttonEdit6} = &gui_new_imgbutton({image => 'rule_edit_16px.png',
                                                              tip   => 'Edit an IPv6 Port Forwarding Rule'}));

    $bb2->add($gui{d}{NAT}{buttonRemove6} = &gui_new_imgbutton({image => 'rule_remove_16px.png',
                                                                tip   => 'Remove an  IPv6 Port Forwarding Rule'}));

    my $frame = &gui_new_frame({label => 'Port Forwarding Rules'});
    $frame->add($notebook);
    $gui{d}{NAT}->get_content_area()->add(my $grid1 = &gui_new_grid());
    $grid1->attach(&gui_new_widgetlabel({text => 'Network _Name:', mnwidget => $gui{d}{NAT}{entryName}}), 0, 0, 1, 1);
    $grid1->attach($gui{d}{NAT}{entryName}, 1, 0, 1, 1);
    $grid1->attach(&gui_new_widgetlabel({text => 'Network _CIDR:', mnwidget => $gui{d}{NAT}{entryCIDR}}), 0, 1, 1, 1);
    $grid1->attach($gui{d}{NAT}{entryCIDR}, 1, 1, 1, 1);
    $grid1->attach(&gui_new_widgetlabel({text => 'Network Options:'}), 0, 3, 1, 1);
    $grid1->attach($gui{d}{NAT}{checkDHCP}, 1, 2, 1, 1);
    $grid1->attach($gui{d}{NAT}{checkIPv6}, 1, 3, 1, 1);
    $grid1->attach($gui{d}{NAT}{checkRoute}, 1, 4, 1, 1);
    $grid1->attach($frame, 0, 5, 2, 1);
    $grid2->attach(my $scrollwin1 = &gui_new_scrolledwindow(), 0, 0, 1, 1);
    $scrollwin1->add_with_viewport($gui{d}{NAT}{treeviewIPv4});
    $grid2->attach($bb1, 1, 0, 1, 1);
    $grid3->attach(my $scrollwin2 = &gui_new_scrolledwindow(), 0, 0, 1, 1);
    $scrollwin2->add_with_viewport($gui{d}{NAT}{treeviewIPv6});
    $grid3->attach($bb2, 1, 0, 1, 1);
    $signal{NAT_treeviewIPv4_cursor_changed} = $gui{d}{NAT}{treeviewIPv4}->signal_connect('cursor-changed' => \&onsel_list_pf4);
    $signal{NAT_treeviewIPv6_cursor_changed} = $gui{d}{NAT}{treeviewIPv6}->signal_connect('cursor-changed' => \&onsel_list_pf6);
    $buttonAdd4->signal_connect('clicked' => \&show_dialog_pf4, 'ADD');
    $buttonAdd6->signal_connect('clicked' => \&show_dialog_pf6, 'ADD');
    $gui{d}{NAT}{buttonEdit4}->signal_connect('clicked' => \&show_dialog_pf4, 'EDIT');
    $gui{d}{NAT}{buttonEdit6}->signal_connect('clicked' => \&show_dialog_pf6, 'EDIT');
    $gui{d}{NAT}{buttonRemove4}->signal_connect('clicked' => \&remove_pf_rule4);
    $gui{d}{NAT}{buttonRemove6}->signal_connect('clicked' => \&remove_pf_rule6);
}

# Build the remote file chooser dialog
sub build_dialogRemoteFileChooser {
    $gui{d}{RemoteFileChooser} = &gui_new_dialog({title  => 'Choose File...',
                                                  cancel => TRUE});

    $gui{d}{RemoteFileChooser}->set_default_size(500,500);
    $gui{d}{RemoteFileChooser}{entryLocation} = &gui_new_entry({width => 35,
                                                                tip   => 'Current directory location on the remote server'});

    my $button1 = &gui_new_imgbutton({image => 'sf_parent_16px.png',
                                      tip   => 'Change to the parent directory'});

    my $button2 = &gui_new_imgbutton({image => 'refresh_16px.png',
                                      tip   => 'Refresh the contents of the current directory'});

    $gui{d}{RemoteFileChooser}{treeviewFile} = &gui_new_treeview({model => $gui{d}{RemoteFileChooser}{lstoreFile} = &gui_new_lstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf']),
                                                                  tip   => 'Files in the current directory'});

    $gui{d}{RemoteFileChooser}{treeviewFile}->append_column(&gui_new_treeviewcolumn({title   => '',
                                                                                     type    => 'pixbuf',
                                                                                     typecol => 4}));

    $gui{d}{RemoteFileChooser}{treeviewFile}->append_column(&gui_new_treeviewcolumn({title   => 'Type',
                                                                                     type    => 'text',
                                                                                     typecol => 0}));

    $gui{d}{RemoteFileChooser}{treeviewFile}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                                     type    => 'text',
                                                                                     typecol => 1}));

    $gui{d}{RemoteFileChooser}{treeviewFile}->append_column(&gui_new_treeviewcolumn({title   => 'Size',
                                                                                     type    => 'text',
                                                                                     typecol => 2}));

    $gui{d}{RemoteFileChooser}{treeviewFile}->append_column(&gui_new_treeviewcolumn({title   => 'Mode',
                                                                                     type    => 'text',
                                                                                     typecol => 3}));

    $gui{d}{RemoteFileChooser}{entryFile} = &gui_new_entry({tip   => 'Current directory location on the remote server'});
    $gui{d}{RemoteFileChooser}{entryFilter} = &gui_new_entry({tip   => 'Current directory location on the remote server'});
    $gui{d}{RemoteFileChooser}->get_content_area()->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_widgetlabel({text => '_Location:', mnwidget => $gui{d}{RemoteFileChooser}{entryLocation}}), 0, 0, 1, 1);
    $grid->attach($gui{d}{RemoteFileChooser}{entryLocation}, 1, 0, 3, 1);
    $grid->attach(my $box = &gui_new_box({orientation => 'horizontal'}), 4, 0, 1, 1);
    $box->pack_start($button1, TRUE, TRUE, 0);
    $box->pack_start($button2, TRUE, TRUE, 0);
    $grid->attach(my $scrollwin = &gui_new_scrolledwindow(), 0, 1, 5, 1);
    $scrollwin->add_with_viewport($gui{d}{RemoteFileChooser}{treeviewFile});
    $grid->attach($gui{d}{RemoteFileChooser}{boxFile} = &gui_new_box({orientation => 'horizontal'}), 0, 2, 5, 1);
    $gui{d}{RemoteFileChooser}{boxFile}->pack_start(&gui_new_widgetlabel({text => '_File:', mnwidget => $gui{d}{RemoteFileChooser}{entryLocation}}), TRUE, TRUE, 0);
    $gui{d}{RemoteFileChooser}{boxFile}->pack_start($gui{d}{RemoteFileChooser}{entryFile}, TRUE, TRUE, 0);
    $gui{d}{RemoteFileChooser}{boxFile}->pack_start($gui{d}{RemoteFileChooser}{entryFilter}, TRUE, TRUE, 0);
    $gui{d}{RemoteFileChooser}{entryLocation}->signal_connect('activate' => \&refresh_remotefilechooser);
    $button1->signal_connect('clicked' => \&cdup_remotefilechooser);
    $button2->signal_connect('clicked' => \&refresh_remotefilechooser);
    $signal{RemoteFileChooser_treeviewRemoteFileChooser_cursorChanged} = $gui{d}{RemoteFileChooser}{treeviewFile}->signal_connect('cursor-changed' => \&onsel_list_remotefiles_single);
    $gui{d}{RemoteFileChooser}{treeviewFile}->signal_connect('row-activated' => \&onsel_list_remotefiles);
}

# Build the VMM dialog
sub build_dialogVMM {
    $gui{d}{VMM} = &gui_new_dialog({title  => 'Virtual Media Manager'});
    $gui{d}{VMM}->set_default_size(800,600);
    $gui{d}{VMM}{imgHDAdd} = &gui_new_img_from_file('hd_add_32px.png');
    $gui{d}{VMM}{imgHDCopy} = &gui_new_img_from_file('hd_copy_32px.png');
    $gui{d}{VMM}{imgHDCreate} = &gui_new_img_from_file('hd_create_32px.png');
    $gui{d}{VMM}{imgHDModify} = &gui_new_img_from_file('hd_modify_32px.png');
    $gui{d}{VMM}{imgHDMove} = &gui_new_img_from_file('hd_move_32px.png');
    $gui{d}{VMM}{imgHDRelease} = &gui_new_img_from_file('hd_release_32px.png');
    $gui{d}{VMM}{imgHDRemove} = &gui_new_img_from_file('hd_remove_32px.png');
    $gui{d}{VMM}{imgCompact} = &gui_new_img_from_file('compact_32px.png');
    $gui{d}{VMM}{imgRefresh} = &gui_new_img_from_file('refresh_32px.png');
    $gui{d}{VMM}{imgFDAdd} = &gui_new_img_from_file('fd_add_32px.png');
    $gui{d}{VMM}{imgFDCopy} = &gui_new_img_from_file('fd_copy_32px.png');
    $gui{d}{VMM}{imgFDCreate} = &gui_new_img_from_file('fd_create_32px.png');
    $gui{d}{VMM}{imgFDModify} = &gui_new_img_from_file('fd_modify_32px.png');
    $gui{d}{VMM}{imgFDMove} = &gui_new_img_from_file('fd_move_32px.png');
    $gui{d}{VMM}{imgFDRelease} = &gui_new_img_from_file('fd_release_32px.png');
    $gui{d}{VMM}{imgFDRemove} = &gui_new_img_from_file('fd_remove_32px.png');
    $gui{d}{VMM}{imgDVDAdd} = &gui_new_img_from_file('cd_add_32px.png');
    $gui{d}{VMM}{imgDVDCopy} = &gui_new_img_from_file('cd_copy_32px.png');
    $gui{d}{VMM}{imgDVDCreate} = &gui_new_img_from_file('cd_create_32px.png');
    $gui{d}{VMM}{imgDVDModify} = &gui_new_img_from_file('cd_modify_32px.png');
    $gui{d}{VMM}{imgDVDMove} = &gui_new_img_from_file('cd_move_32px.png');
    $gui{d}{VMM}{imgDVDRelease} = &gui_new_img_from_file('cd_release_32px.png');
    $gui{d}{VMM}{imgDVDRemove} = &gui_new_img_from_file('cd_remove_32px.png');
    my $toolbar = &gui_new_toolbar();
    $toolbar->insert($gui{d}{VMM}{buttonAdd} = &gui_new_toolbutton({image => 'hd_add_32px.png',
                                                                    label => '_Add',
                                                                    tip   => 'Add a medium to the VMM on the server'}), 0);

    $toolbar->insert($gui{d}{VMM}{buttonCreate} = &gui_new_toolbutton({image => 'hd_create_32px.png',
                                                                       label => '_Create',
                                                                       tip  => 'Create a new disk image'}), 1);

    $toolbar->insert($gui{d}{VMM}{buttonCopy} = &gui_new_toolbutton({image => 'hd_create_32px.png',
                                                                     label => 'C_opy & Convert',
                                                                     tip  => 'Copy an existing hard disk image and optionally change its format'}), 2);

    $toolbar->insert($gui{d}{VMM}{buttonMove} = &gui_new_toolbutton({image => 'hd_move_32px.png',
                                                                     label => '_Move',
                                                                     tip  => 'Move a storage medium to a different location'}), 3);

    $toolbar->insert($gui{d}{VMM}{buttonModify} = &gui_new_toolbutton({image => 'hd_modify_32px.png',
                                                                       label => 'Modify & Resi_ze',
                                                                       tip  => 'Modify the low-level hard disk type or resize the hard disk'}), 4);

    $toolbar->insert($gui{d}{VMM}{buttonRemove} = &gui_new_toolbutton({image => 'hd_remove_32px.png',
                                                                       label => 'R_emove',
                                                                       tip  => 'Remove the medium from VirtualBox'}), 5);

    $toolbar->insert($gui{d}{VMM}{buttonRelease} = &gui_new_toolbutton({image => 'hd_release_32px.png',
                                                                        label => 'Re_lease',
                                                                        tip  => 'Release medium from guests. Media associated with snapshots will not be released'}), 6);

    $toolbar->insert($gui{d}{VMM}{buttonCompact} = &gui_new_toolbutton({image => 'compact_32px.png',
                                                                        label => 'Com_pact',
                                                                        tip  => 'Attempt to compact the hard disk image, making it physically smaller'}), 7);

    $toolbar->insert($gui{d}{VMM}{buttonRefresh} = &gui_new_toolbutton({image => 'refresh_32px.png',
                                                                        label => '_Refresh',
                                                                        tip  => 'Refresh the media list in the VMM'}), 8);

    $gui{d}{VMM}{notebook} = Gtk3::Notebook->new();
    $gui{d}{VMM}{notebook}->append_page(my $scrollwin1 = &gui_new_scrolledwindow(), &gui_new_imglabel({text => '_Hard Disks', img => 'hd_16px.png'}));
    $gui{d}{VMM}{notebook}->append_page(my $scrollwin2 = &gui_new_scrolledwindow(), &gui_new_imglabel({text => '_Optical Discs', img => 'cd_16px.png'}));
    $gui{d}{VMM}{notebook}->append_page(my $scrollwin3 = &gui_new_scrolledwindow(), &gui_new_imglabel({text => '_Floppy Disks', img => 'fd_16px.png'}));
    $gui{d}{VMM}{notebook}->show_all();
    $gui{d}{VMM}{treeviewHD} = &gui_new_treeview({model   => $gui{d}{VMM}{tstoreHD} = &gui_new_tstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String']),
                                                  headers => TRUE,
                                                  tip     => 'Hard Disk Images'});

    $gui{d}{VMM}{treeviewHD}->append_column(&gui_new_treeviewcolumn({title   => '',
                                                                     type    => 'pixbuf',
                                                                     typecol => 4}));

    $gui{d}{VMM}{treeviewHD}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                     type    => 'text',
                                                                     typecol => 0}));

    $gui{d}{VMM}{treeviewHD}->append_column(&gui_new_treeviewcolumn({title   => 'Virtual Size',
                                                                     type    => 'text',
                                                                     typecol => 3}));

    $gui{d}{VMM}{treeviewHD}->append_column(&gui_new_treeviewcolumn({title   => 'Actual Size',
                                                                     type    => 'text',
                                                                     typecol => 2}));

    $scrollwin1->add_with_viewport($gui{d}{VMM}{treeviewHD});
    $gui{d}{VMM}{treeviewDVD} = &gui_new_treeview({model   => $gui{d}{VMM}{tstoreDVD} = &gui_new_tstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String']),
                                                   headers => TRUE,
                                                   tip     => 'Optical Disc Images'});

    $gui{d}{VMM}{treeviewDVD}->append_column(&gui_new_treeviewcolumn({title   => '',
                                                                      type    => 'pixbuf',
                                                                      typecol => 3}));

    $gui{d}{VMM}{treeviewDVD}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                      type    => 'text',
                                                                      typecol => 0}));

    $gui{d}{VMM}{treeviewDVD}->append_column(&gui_new_treeviewcolumn({title   => 'Size',
                                                                      type    => 'text',
                                                                      typecol => 2}));

    $scrollwin2->add_with_viewport($gui{d}{VMM}{treeviewDVD});
    $gui{d}{VMM}{treeviewFD} = &gui_new_treeview({model   => $gui{d}{VMM}{tstoreFD} = &gui_new_tstore(undef, ['Glib::String', 'Glib::String', 'Glib::String', 'Gtk3::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String']),
                                                  headers => TRUE,
                                                  tip     => 'Floppy Disk Images'});

    $gui{d}{VMM}{treeviewFD}->append_column(&gui_new_treeviewcolumn({title   => '',
                                                                     type    => 'pixbuf',
                                                                     typecol => 3}));

    $gui{d}{VMM}{treeviewFD}->append_column(&gui_new_treeviewcolumn({title   => 'Name',
                                                                     type    => 'text',
                                                                     typecol => 0}));

    $gui{d}{VMM}{treeviewFD}->append_column(&gui_new_treeviewcolumn({title   => 'Size',
                                                                     type    => 'text',
                                                                     typecol => 2}));

    $scrollwin3->add_with_viewport($gui{d}{VMM}{treeviewFD});
    my $frame = &gui_new_frame({label => 'Details'});
    $frame->add(my $grid = &gui_new_grid());
    $grid->attach(&gui_new_markuplabel({text => '<b>Type:</b>', xalign => 1.0}), 0, 0, 1, 1);
    $grid->attach($gui{d}{VMM}{labelType} = &gui_new_markuplabel({text => 'Field', xalign => 0.0}), 1, 0, 1, 1);
    $grid->attach(&gui_new_markuplabel({text => '<b>Location:</b>', xalign => 1.0}), 0, 1, 1, 1);
    $grid->attach($gui{d}{VMM}{labelLocation} = &gui_new_markuplabel({text => 'Field', xalign => 0.0}), 1, 1, 1, 1);
    $grid->attach(&gui_new_markuplabel({text => '<b>Attached To:</b>', xalign => 1.0}), 0, 2, 1, 1);
    $grid->attach($gui{d}{VMM}{labelAttachedTo} = &gui_new_markuplabel({text => 'Field', xalign => 0.0}), 1, 2, 1, 1);
    $grid->attach(&gui_new_markuplabel({text => '<b>Encryption Key:</b>', xalign => 1.0}), 0, 3, 1, 1);
    $grid->attach($gui{d}{VMM}{labelEncrypted} = &gui_new_markuplabel({text => 'Field', xalign => 0.0}), 1, 3, 1, 1);
    $grid->attach(&gui_new_markuplabel({text => '<b>UUID:</b>', xalign => 1.0}), 0, 4, 1, 1);
    $grid->attach($gui{d}{VMM}{labelUUID} = &gui_new_markuplabel({text => 'Field', xalign => 0.0}), 1, 4, 1, 1);
    $gui{d}{VMM}->get_content_area()->add(my $box = &gui_new_box({orientation => 'vertical'}));
    $box->pack_start($toolbar, FALSE, FALSE, 0);
    $box->pack_start($gui{d}{VMM}{notebook}, TRUE, TRUE, 0);
    $box->pack_start($frame, FALSE, FALSE, 0);
    $gui{d}{VMM}{buttonAdd}->signal_connect('clicked' => \&show_remote_filechooser, {title       => 'Choose Media Images',
                                                                                     entrywidget => '',
                                                                                     mode        => 'multifile',
                                                                                     filter      => '.*',
                                                                                     callback    => \&vmm_add});

    $gui{d}{VMM}{buttonCreate}->signal_connect('clicked' => \&vmm_create_broker);
    $gui{d}{VMM}{buttonCopy}->signal_connect('clicked' => \&vmm_copy_broker);
    $gui{d}{VMM}{buttonMove}->signal_connect('clicked' => \&vmm_move_broker);
    $gui{d}{VMM}{buttonModify}->signal_connect('clicked' => \&show_dialog_vmm_modify);
    $gui{d}{VMM}{buttonRemove}->signal_connect('clicked' => \&vmm_rem);
    $gui{d}{VMM}{buttonRelease}->signal_connect('clicked' => \&vmm_release);
    $gui{d}{VMM}{buttonCompact}->signal_connect('clicked' => \&vmm_compact);
    $gui{d}{VMM}{buttonRefresh}->signal_connect('clicked' => \&vmm_refresh_broker);
    $gui{d}{VMM}{notebook}->signal_connect('switch-page', => \&vmm_tabchanged);
    $gui{d}{VMM}{treeviewHD}->signal_connect('row-activated' => \&show_dialog_vmm_modify);
    $signal{VMM_treeviewHD_cursorChanged} = $gui{d}{VMM}{treeviewHD}->signal_connect('cursor-changed' => \&onsel_list_vmmhd);
    $signal{VMM_treeviewDVD_cursorChanged} = $gui{d}{VMM}{treeviewDVD}->signal_connect('cursor-changed' => \&onsel_list_vmmdvd);
    $gui{d}{VMM}{treeviewFD}->signal_connect('row-activated' => \&show_dialog_vmm_modify);
    $signal{VMM_treeviewFD_cursorChanged} = $gui{d}{VMM}{treeviewFD}->signal_connect('cursor-changed' => \&onsel_list_vmmfloppy);
}

&build_dialogAbout();
&build_messageDialogsAll();
&build_filechooserDialogsAll();
&build_dialogCustomResolution();
&build_dialogConnect();
&build_dialogDecPassword();
&build_dialogSharedFolders();
&build_dialogCopyFloppy();
&build_dialogMoveMedium();
&build_dialogCreateFloppy();
&build_dialogUSBFilter();
&build_dialogImportAppl();
&build_dialogExportAppl();
&build_dialogClone();
&build_dialogPFRule4();
&build_dialogPFRule6();
&build_dialogHON();
&build_dialogSetGroup();
&build_dialogVBPrefs();
&build_dialogSnapshot();
&build_dialogCreateHD();
&build_dialogCopyHD();
&build_dialogProgress();
&build_dialogServerInfo();
&build_dialogHostNetMan();
&build_dialogHostNetMan();
&build_dialogGuestLog();
&build_dialogProfile();
&build_dialogNew();
&build_dialogModifyHD();
&build_dialogPrefs();
&build_dialogNAT();
&build_dialogRemoteFileChooser;
&build_dialogVMM();

# 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{d}{RemoteFileChooser}->set_title($$data{title} . " $endpoint");
    $gui{d}{RemoteFileChooser}{entryFilter}->set_text($$data{filter});

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

        if ($$data{entrywidget}) {
            my ($vol, $dir, $file) = &rsplitpath($entrywidget->get_text());
            $basedir = $vol . $dir;
            $gui{d}{RemoteFileChooser}{entryFile}->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{d}{RemoteFileChooser}->run();
    $gui{d}{RemoteFileChooser}->hide();
    IManagedObjectRef_release($gui{IVFSExplorer});
    IManagedObjectRef_release($IAppliance);

    if ($response eq 'ok') {
        my $location = $gui{d}{RemoteFileChooser}{entryLocation}->get_text();
        my $filename = $gui{d}{RemoteFileChooser}{entryFile}->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{d}{RemoteFileChooser}{entryLocation}->get_text();
}

# Refreshes the contents of the file chooser
sub refresh_remotefilechooser {
    &fill_list_remotefiles($gui{d}{RemoteFileChooser}{entryLocation}->get_text(), $gui{d}{RemoteFileChooser}{entryFilter}->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{d}{RemoteFileChooser}{entryFilter}->get_text());
}

# 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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
sub gui_new_tstore {
    my ($parent, $coldef) = @_;
    my $tstore = Gtk3::TreeStore->new($coldef);
    $parent->set_model($tstore) if ($parent);
    return $tstore;
}

# Creates a standard label for the left side of widget
# text : text to place on the label
# mnwidget : The associated mnemonic widget for the label
# xalign : The xalignment (optional)
sub gui_new_widgetlabel {
    my ($p) = @_;
    my $label = Gtk3::Label->new_with_mnemonic($$p{text});
    $label->set_justify('GTK_JUSTIFY_LEFT');
    $label->set_mnemonic_widget($$p{mnwidget}) if ($$p{mnwidget});
    $$p{xalign} ? $label->set_xalign($$p{xalign}) : $label->set_xalign(1);
    $label->set_yalign(0.5);
    $label->set_margin_right(5);
    $label->set_vexpand(FALSE);
    $label->show();
    return $label;
}

# Creates a dialog title label
# text : text to place on the label
sub gui_new_titlelabel {
    my ($p) = @_;
    my $label = Gtk3::Label->new();
    $label->set_markup("<b><big>$$p{text}</big></b>");
    $label->set_margin_bottom(5);
    $label->show();
    return $label;
}

# Creates a markup label
# text : Text to place on the lbale
sub gui_new_markuplabel {
    my ($p) = @_;
    my $label = Gtk3::Label->new();
    $label->set_markup($$p{text});
    $label->set_vexpand(FALSE);
    defined($$p{xalign}) ? $label->set_xalign($$p{xalign}) : $label->set_xalign(0.5);
    $label->set_justify('GTK_JUSTIFY_CENTER');
    $label->set_margin_bottom(5);
    $label->show();
    return $label;
}

# Create a standard Grid
sub gui_new_grid {
    my $grid = Gtk3::Grid->new();
    $grid->set_row_spacing(5);
    $grid->set_column_spacing(5);
    $grid->set_margin_top(10);
    $grid->set_margin_bottom(10);
    $grid->set_margin_right(10);
    $grid->set_margin_left(10);
    $grid->show_all();
    return $grid;
}

# Create a standard box
# oritentation: Whether vertical or horizontal
sub gui_new_box{
    my ($p) = @_;
    my $box = Gtk3::Box->new($$p{orientation}, 2);
    $box->show_all();
    return $box;
}

# Create a standard spinbutton
# lo = Lowest value for range - May get overriden by an adjustment
# hi = highest value for range - May get overriden by an adjustment
# inc = Amount to increment by - May get overriden by an adjustment
# maxlen = Maximum length in chars - May get overriden by an adjustment
# decplaces = Amount of decimal places (optional)
# adj = An adjustment widget (optional)
# numeric : Whether numeric only or not
sub gui_new_spinbutton {
    my ($p) = @_;
    my $spinbutton = Gtk3::SpinButton->new_with_range($$p{lo}, $$p{hi}, $$p{inc});
    $spinbutton->set_digits($$p{decplaces}) if ($$p{decplaces});
    $spinbutton->set_tooltip_text($$p{tip});
    defined($$p{numeric}) ? $spinbutton->set_numeric($$p{numeric}) : $spinbutton->set_numeric(TRUE);
    $spinbutton->set_hexpand(TRUE);
    $spinbutton->set_max_length($$p{maxlen}) if ($$p{maxlen});
    $spinbutton->set_adjustment($$p{adj}) if ($$p{adj});
    $spinbutton->set_update_policy('if-valid');
    $spinbutton->show();
    return $spinbutton
}

# Create a standard entry field
# width : Width of entry in chars
# maxlen : Maximum length of contents in chars
# pass : If present, sets it to a password entry
sub gui_new_entry {
    my ($p) = @_;
    my $entry = Gtk3::Entry->new();
    $entry->set_tooltip_text($$p{tip});
    $entry->set_hexpand(TRUE);
    $entry->set_vexpand(FALSE);
    $entry->set_width_chars($$p{width}) if ($$p{width});
    $entry->set_max_length($$p{maxlen}) if ($$p{maxlen});

    if ($$p{pass}) {
        $entry->set_visibility(FALSE);
        $entry->set_input_purpose('GTK_INPUT_PURPOSE_PASSWORD');
    }

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

# Create a standard image only button
# image : The image filename to add to the button
sub gui_new_imgbutton {
    my ($p) = @_;
    my $button = Gtk3::Button->new();
    $button->set_image(&gui_new_img_from_file($$p{image}));
    $button->set_tooltip_text($$p{tip});
    $button->set_hexpand(FALSE);
    $button->set_hexpand(FALSE);
    $button->show();
    return $button
}

# Create a standard text button
# image : The image filename to add to the button
sub gui_new_button {
    my ($p) = @_;
    my $button = Gtk3::Button->new_with_mnemonic($$p{label});
    $button->set_tooltip_text($$p{tip});
    $button->set_hexpand(FALSE);
    $button->set_hexpand(FALSE);
    $button->show();
    return $button
}

# Create a standard image only button
# image : The image filename to add to the button
# label : The label for the button
sub gui_new_toolbutton {
    my ($p) = @_;
    my $button = Gtk3::ToolButton->new(&gui_new_img_from_file($$p{image}), $$p{label});
    $button->set_tooltip_text($$p{tip});
    $button->set_hexpand(FALSE);
    $button->set_hexpand(FALSE);
    $button->set_use_underline(TRUE);
    $button->show();
    return $button
}

# Create a standard toolbar
sub gui_new_toolbar {
    my $toolbar = Gtk3::Toolbar->new();
    $toolbar->set_hexpand(TRUE);
    $toolbar->set_vexpand(FALSE);
    $toolbar->set_style('GTK_TOOLBAR_BOTH');
    $toolbar->show();
    return $toolbar
}

# Creates a new standard dialog
# title: Title of the dialog
# ok : Specify an alternative name for the OK button : optional
# okimage : Specify an image to show on the OK button : optional
sub gui_new_dialog {
    my ($p) = @_;
	my $dialog = Gtk3::Dialog->new($$p{title}, undef, 'GTK_DIALOG_MODAL'); # Transient is determined automatically
    $dialog->set_type_hint('GDK_WINDOW_TYPE_HINT_DIALOG');
    $dialog->set_skip_taskbar_hint(TRUE);
    $dialog->add_button('Cancel', 'cancel') if ($$p{cancel});
    my $okbutton = $$p{ok} ? $dialog->add_button($$p{ok}, 'ok') : $dialog->add_button('OK', 'ok');

    if ($$p{okimage}) {
        $okbutton->set_always_show_image(TRUE);
        $okbutton->set_image($$p{okimage});
        $okbutton->set_image_position('GTK_POS_LEFT');
    }

    $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_deletable(FALSE);
    $dialog->set_default_response('ok');
    $dialog->set_icon_name("$sharedir/icons/remotebox.png");
    $dialog->signal_connect('hide' => \&transwin_sens_on, $dialog);
    $dialog->signal_connect('show' => \&transwin_sens_off, $dialog);
    return $dialog;
}

# Create a standard layout widget
sub gui_new_layout {
    my $layout = Gtk3::Layout->new();
    $layout->set_vexpand(TRUE);
    $layout->show_all();
    return $layout;
}

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

# Create a cell renderer
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
sub gui_new_menu {
    my $menu = Gtk3::Menu->new();
    $menu->set_reserve_toggle_size(TRUE);
    return $menu;
}

# Menu Item with optional image
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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;
}

# Create standard menu separator
sub gui_new_menu_sep {
    my $sep = Gtk3::SeparatorMenuItem->new();
    $sep->show();
    return $sep;
}

# Creates an adjustment and optionally attaches it
# FIXME - Needs to use $pp{param} once Gtkbuilder deps removed
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;
}

# Creates a new simple text only combobox
# model : The liststore to attach (optional)
# active : The item index to make default, otheriwse -1 will be
sub gui_new_simplecombobox {
    my ($p) = @_;
    my $combobox = Gtk3::ComboBox->new();

    if ($$p{model}) {
        $combobox->set_model($$p{model});
        defined($$p{active}) ? $combobox->set_active($$p{active}) : $combobox->set_active(-1);
    }
    my $cellrenderer = Gtk3::CellRendererText->new();
    $combobox->pack_start($cellrenderer, TRUE);
    $combobox->add_attribute($cellrenderer, 'text', 0);
    $combobox->set_tooltip_text($$p{tip});
    $combobox->set_hexpand(TRUE);
    $combobox->set_vexpand(FALSE);
    $combobox->show();
    return $combobox;
}

# Creates a new image combobox
# model : The liststore to attach (optional)
# active : The item index to make default, otheriwse -1 will be
sub gui_new_imgcombobox {
    my ($p) = @_;
    my $combobox = Gtk3::ComboBox->new();

    if ($$p{model}) {
        $combobox->set_model($$p{model});
        defined($$p{active}) ? $combobox->set_active($$p{active}) : $combobox->set_active(-1);
    }

    my $cellrenderertext = Gtk3::CellRendererText->new();
    $cellrenderertext->set_alignment(0.0, 0.5);
    my $cellrendererpb = Gtk3::CellRendererPixbuf->new();
    $cellrendererpb->set_alignment(0.0, 0.5);
    $combobox->pack_start($cellrendererpb, TRUE);
    $combobox->add_attribute($cellrendererpb, 'pixbuf', $$p{imgcol});
    $combobox->pack_start($cellrenderertext, TRUE);
    $combobox->add_attribute($cellrenderertext, 'text', 0);
    $combobox->set_tooltip_text($$p{tip});
    $combobox->set_hexpand(TRUE);
    $combobox->set_vexpand(FALSE);
    $combobox->show();
    return $combobox;
}

# Creates a new standard treeview
# model : The liststore / treestore to attach (optional)
sub gui_new_treeview {
    my ($p) = @_;
    my $treeview = $$p{model} ? Gtk3::TreeView->new_with_model($$p{model}) : Gtk3::TreeView->new();
    $treeview->set_tooltip_text($$p{tip});
    $treeview->set_hexpand(TRUE);
    $treeview->set_vexpand(TRUE);
    $treeview->set_headers_visible($$p{headers}) if (defined($$p{headers}));
    $treeview->show();
    return $treeview;
}

# Creates a new standard treeviewcolumn
# model : The liststore / treestore to attach (optional)
# type : The type such as text
# typecol : The column in the model to pull it from
sub gui_new_treeviewcolumn {
    my ($p) = @_;
    my $cellrenderer;

    if ($$p{type} eq 'pixbuf') {
        $cellrenderer = Gtk3::CellRendererPixbuf->new();
    }
    else {
        $cellrenderer = Gtk3::CellRendererText->new();
    }

    # Could probably be optionmuised by using new with attributes
    my $treeviewcol = Gtk3::TreeViewColumn->new();
    $treeviewcol->set_title($$p{title});
    $treeviewcol->set_sizing('GTK_TREE_VIEW_COLUMN_AUTOSIZE');
    $treeviewcol->set_resizable(TRUE);
    $treeviewcol->pack_start($cellrenderer, TRUE);
    $treeviewcol->add_attribute($cellrenderer, $$p{type}, $$p{typecol});
    $treeviewcol->set_clickable(TRUE);
    return $treeviewcol;
}

# Creates a new standard toggle treeviewcolumn
# model : The liststore / treestore to attach (optional)
# type : The type such as text
# typecol : The column in the model to pull it from
# toggle : True if the celltendered should be a toggle type (optional)
sub gui_new_treeviewcolumntoggle {
    my ($p) = @_;
    my $cellrenderer = Gtk3::CellRendererToggle->new();
    # Could probably be optionmuised by using new with attributes
    my $treeviewcol = Gtk3::TreeViewColumn->new();
    $treeviewcol->set_title($$p{title});
    $treeviewcol->set_sizing('GTK_TREE_VIEW_COLUMN_AUTOSIZE');
    $treeviewcol->set_resizable(TRUE);
    $treeviewcol->pack_start($cellrenderer, FALSE);
    $treeviewcol->add_attribute($cellrenderer, $$p{type}, $$p{typecol});
    $treeviewcol->set_clickable(TRUE);
    return ($treeviewcol, $cellrenderer);
}

# Creates a standard frame
# label - Title label for the frame
sub gui_new_frame {
    my ($p) = @_;
    my $frame = Gtk3::Frame->new($$p{label});
    $frame->set_label_align(0.0, 0.5);
    $frame->set_shadow_type('GTK_SHADOW_ETCHED_IN');
    $frame->show_all();
    return $frame
}

# Create a standard check widget
# text : The text next to the checkmark
# active : If the checkmark should be set active or not
sub gui_new_check {
    my ($p) = @_;
    my $check = Gtk3::CheckButton->new_with_mnemonic($$p{text});
    $check->set_active($$p{active});
    $check->set_tooltip_text($$p{tip});
    $check->set_vexpand(FALSE);
    $check->show();
    return $check;
}

# Creates a standard radio button
# text : The text to display next to the radio button
# group : The radio button group
# active: Whether it is active or not
sub gui_new_radio {
    my ($p) = @_;
    my $radiobutton = Gtk3::RadioButton->new_with_mnemonic($$p{group}, $$p{text});
    $radiobutton->set_active($$p{active});
    $radiobutton->set_tooltip_text($$p{tip});
    $radiobutton->set_vexpand(FALSE);
    $radiobutton->show_all();
    return $radiobutton
}

# Creates a standard scrolled window
sub gui_new_scrolledwindow {
    my ($p) = @_;
    my $scrollwin = Gtk3::ScrolledWindow->new();
    $scrollwin->set_propagate_natural_height(TRUE);
    $scrollwin->set_propagate_natural_width(TRUE);
    $scrollwin->show_all();
    return $scrollwin;
}

# Creates a standard textview
# editable - Whether it is editable
# buffer - The textbuffer object
sub gui_new_textview {
    my ($p) = @_;
    my $textview = Gtk3::TextView->new_with_buffer($$p{buffer});
    $textview->set_editable($$p{editable});
    $textview->set_tooltip_text($$p{tip});
    $textview->set_wrap_mode('word');
    $textview->show();
    $textview->set_hexpand(TRUE);
    $textview->set_vexpand(TRUE);
    return $textview;
}

# Creates a standard button box
# oritentation - Whether vertical or horizontal
sub gui_new_buttonbox {
    my ($p) = @_;
    my $bb = Gtk3::ButtonBox->new($$p{orientation});
    $bb->set_hexpand(FALSE);
    $bb->set_vexpand(FALSE);
    $bb->set_layout('GTK_BUTTONBOX_CENTER');
    $bb->show();
    return $bb;
}

# Creates a standhard horizontal separator
sub gui_new_separator {
    my $sep = Gtk3::Separator->new('horizontal');
    $sep->set_hexpand(TRUE);
    $sep->set_vexpand(FALSE);
    $sep->set_margin_top(10);
    $sep->set_margin_bottom(10);
    $sep->set_margin_right(0);
    $sep->set_margin_left(0);
    $sep->show();
    return $sep;
}

# Creates a standhard horizontal scale
# adj : The adjustment to attach
sub gui_new_scale {
    my ($p) = @_;
    my $scale = Gtk3::Scale->new('horizontal', $$p{adj});
    $scale->set_hexpand(TRUE);
    $scale->set_vexpand(FALSE);
    $scale->set_show_fill_level(TRUE);
    $scale->set_restrict_to_fill_level(TRUE);
    $scale->set_draw_value(FALSE);
    $scale->show();
    return $scale;
}

# Creates a standard label and image for a notebook tab
# text : text to place on the label
# img : The xalignment (optional)
sub gui_new_imglabel {
    my ($p) = @_;
    my $box = &gui_new_box({orientation => 'horizontal'});
    my $label = Gtk3::Label->new_with_mnemonic($$p{text});
    $label->set_justify('GTK_JUSTIFY_LEFT');
    $$p{xalign} ? $label->set_xalign($$p{xalign}) : $label->set_xalign(1);
    $label->set_yalign(0.5);
    $label->set_hexpand(FALSE);
    $label->set_vexpand(FALSE);
    $label->show();
    $box->pack_start(&gui_new_img_from_file($$p{img}), TRUE, TRUE, 0);
    $box->pack_start($label, TRUE, TRUE, 0);
    return $box;
}


1;
