2019-11-26 14:19:29 +01:00
#include "RemovableDriveManager.hpp"
#include <iostream>
2019-11-27 11:33:36 +01:00
#include "boost/nowide/convert.hpp"
2019-11-26 14:19:29 +01:00
2019-11-26 15:52:18 +01:00
#if _WIN32
#include <windows.h>
#include <tchar.h>
2019-11-27 11:33:36 +01:00
#include <winioctl.h>
2019-11-27 13:30:45 +01:00
#include <shlwapi.h>
2019-12-05 14:07:02 +01:00
2019-12-06 16:51:04 +01:00
#include <Dbt.h>
GUID WceusbshGUID = { 0x25dbce51 , 0x6c8f , 0x4a72 ,
0x8a , 0x6d , 0xb5 , 0x4c , 0x2b , 0x4f , 0xc8 , 0x35 };
2019-12-05 14:07:02 +01:00
2019-11-26 15:52:18 +01:00
#else
//linux includes
#include <errno.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <glob.h>
#include <libgen.h>
2019-11-28 16:35:22 +01:00
#include <pwd.h>
2019-11-26 15:52:18 +01:00
#endif
2019-11-26 14:19:29 +01:00
namespace Slic3r {
2019-12-03 10:09:53 +01:00
namespace GUI {
2019-11-26 15:52:18 +01:00
#if _WIN32
2019-12-06 16:51:04 +01:00
INT_PTR WINAPI WinProcCallback ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam );
2019-11-27 11:33:36 +01:00
void RemovableDriveManager :: search_for_drives ()
2019-11-26 14:19:29 +01:00
{
2019-11-27 11:33:36 +01:00
m_current_drives . clear ();
2019-12-13 11:52:08 +01:00
//get logical drives flags by letter in alphabetical order
2019-11-27 14:30:10 +01:00
DWORD drives_mask = GetLogicalDrives ();
2019-11-26 14:19:29 +01:00
for ( size_t i = 0 ; i < 26 ; i ++ )
{
2019-11-27 14:30:10 +01:00
if ( drives_mask & ( 1 << i ))
2019-11-26 14:19:29 +01:00
{
std :: string path ( 1 ,( char )( 'A' + i ));
path += ":" ;
2019-11-27 14:30:10 +01:00
UINT drive_type = GetDriveTypeA ( path . c_str ());
2019-12-13 11:52:08 +01:00
// DRIVE_REMOVABLE on W are sd cards and usb thumbnails (not usb harddrives)
2019-11-27 14:30:10 +01:00
if ( drive_type == DRIVE_REMOVABLE )
2019-11-26 14:19:29 +01:00
{
// get name of drive
2019-12-13 18:02:25 +01:00
std :: wstring wpath = boost :: nowide :: widen ( path ); //std::wstring(path.begin(), path.end());
2019-11-27 14:30:10 +01:00
std :: wstring volume_name ;
volume_name . resize ( 1024 );
std :: wstring file_system_name ;
file_system_name . resize ( 1024 );
LPWSTR lp_volume_name_buffer = new wchar_t ;
BOOL error = GetVolumeInformationW ( wpath . c_str (), & volume_name [ 0 ], sizeof ( volume_name ), NULL , NULL , NULL , & file_system_name [ 0 ], sizeof ( file_system_name ));
2019-11-26 14:19:29 +01:00
if ( error != 0 )
{
2019-12-13 18:02:25 +01:00
volume_name . erase ( std :: find ( volume_name . begin (), volume_name . end (), '\0' ), volume_name . end ());
2019-12-13 11:52:08 +01:00
/*
2019-11-27 14:30:10 +01:00
if (volume_name == L"")
2019-11-26 14:19:29 +01:00
{
2019-11-27 14:30:10 +01:00
volume_name = L"REMOVABLE DRIVE";
2019-11-26 14:19:29 +01:00
}
2019-12-13 11:52:08 +01:00
*/
2019-11-27 14:30:10 +01:00
if ( file_system_name != L "" )
2019-11-26 14:19:29 +01:00
{
2019-11-27 14:30:10 +01:00
ULARGE_INTEGER free_space ;
GetDiskFreeSpaceExA ( path . c_str (), & free_space , NULL , NULL );
if ( free_space . QuadPart > 0 )
2019-11-26 14:19:29 +01:00
{
2019-12-03 10:55:38 +01:00
path += " \\ " ;
2019-11-27 14:30:10 +01:00
m_current_drives . push_back ( DriveData ( boost :: nowide :: narrow ( volume_name ), path ));
2019-11-26 14:19:29 +01:00
}
}
}
}
}
}
}
2019-11-27 11:33:36 +01:00
void RemovableDriveManager :: eject_drive ( const std :: string & path )
2019-11-26 14:19:29 +01:00
{
2019-11-27 11:33:36 +01:00
if ( m_current_drives . empty ())
2019-11-26 14:19:29 +01:00
return ;
2019-11-27 11:33:36 +01:00
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
2019-11-26 14:19:29 +01:00
{
if (( * it ). path == path )
{
2019-12-13 11:52:08 +01:00
// get handle to device
2019-11-27 11:33:36 +01:00
std :: string mpath = " \\\\ . \\ " + path ;
2019-12-03 10:55:38 +01:00
mpath = mpath . substr ( 0 , mpath . size () - 1 );
2019-11-27 11:33:36 +01:00
HANDLE handle = CreateFileA ( mpath . c_str (), GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE , nullptr , OPEN_EXISTING , 0 , nullptr );
if ( handle == INVALID_HANDLE_VALUE )
{
std :: cerr << "Ejecting " << mpath << " failed " << GetLastError () << " \n " ;
return ;
}
DWORD deviceControlRetVal ( 0 );
2019-12-13 11:52:08 +01:00
//these 3 commands should eject device safely but they dont, the device does disappear from file explorer but the "device was safely remove" notification doesnt trigger.
//sd cards does trigger WM_DEVICECHANGE messege, usb drives dont
2019-12-11 17:02:12 +01:00
DeviceIoControl ( handle , FSCTL_LOCK_VOLUME , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr );
DeviceIoControl ( handle , FSCTL_DISMOUNT_VOLUME , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr );
2019-12-13 11:52:08 +01:00
// some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here but it returns error to me
2019-11-27 11:33:36 +01:00
BOOL error = DeviceIoControl ( handle , IOCTL_STORAGE_EJECT_MEDIA , nullptr , 0 , nullptr , 0 , & deviceControlRetVal , nullptr );
2019-11-27 14:30:10 +01:00
if ( error == 0 )
{
2019-12-11 17:02:12 +01:00
CloseHandle ( handle );
2019-11-27 11:33:36 +01:00
std :: cerr << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError () << " \n " ;
2019-12-03 10:09:53 +01:00
return ;
2019-11-27 14:30:10 +01:00
}
2019-12-11 17:02:12 +01:00
CloseHandle ( handle );
2019-12-16 13:53:12 +01:00
m_did_eject = true ;
2019-11-27 11:33:36 +01:00
m_current_drives . erase ( it );
2019-11-26 14:19:29 +01:00
break ;
}
}
}
2019-11-27 14:30:10 +01:00
bool RemovableDriveManager :: is_path_on_removable_drive ( const std :: string & path )
{
if ( m_current_drives . empty ())
return false ;
int letter = PathGetDriveNumberA ( path . c_str ());
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
{
char drive = ( * it ). path [ 0 ];
if ( drive == ( 'A' + letter ))
return true ;
}
return false ;
}
2019-12-05 14:07:02 +01:00
std :: string RemovableDriveManager :: get_drive_from_path ( const std :: string & path )
{
int letter = PathGetDriveNumberA ( path . c_str ());
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
{
char drive = ( * it ). path [ 0 ];
if ( drive == ( 'A' + letter ))
return ( * it ). path ;
}
return "" ;
}
2019-11-28 13:38:08 +01:00
void RemovableDriveManager :: register_window ()
{
2019-12-12 14:56:30 +01:00
//creates new unvisible window that is recieving callbacks from system
2019-12-13 11:52:08 +01:00
// structure to register
2019-11-28 13:38:08 +01:00
WNDCLASSEX wndClass ;
wndClass . cbSize = sizeof ( WNDCLASSEX );
wndClass . style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW ;
wndClass . hInstance = reinterpret_cast < HINSTANCE > ( GetModuleHandle ( 0 ));
2019-12-13 11:52:08 +01:00
wndClass . lpfnWndProc = reinterpret_cast < WNDPROC > ( WinProcCallback ); //this is callback
2019-11-28 13:38:08 +01:00
wndClass . cbClsExtra = 0 ;
wndClass . cbWndExtra = 0 ;
wndClass . hIcon = LoadIcon ( 0 , IDI_APPLICATION );
wndClass . hbrBackground = CreateSolidBrush ( RGB ( 192 , 192 , 192 ));
wndClass . hCursor = LoadCursor ( 0 , IDC_ARROW );
2019-12-05 14:07:02 +01:00
wndClass . lpszClassName = L "PrusaSlicer_aux_class" ;
2019-11-28 13:38:08 +01:00
wndClass . lpszMenuName = NULL ;
wndClass . hIconSm = wndClass . hIcon ;
2019-12-06 16:51:04 +01:00
if ( ! RegisterClassEx ( & wndClass ))
{
DWORD err = GetLastError ();
return ;
}
2019-12-05 14:07:02 +01:00
HWND hWnd = CreateWindowEx (
2019-12-06 16:51:04 +01:00
WS_EX_NOACTIVATE ,
2019-12-05 14:07:02 +01:00
L "PrusaSlicer_aux_class" ,
L "PrusaSlicer_aux_wnd" ,
2019-12-06 16:51:04 +01:00
WS_DISABLED , // style
2019-12-05 14:07:02 +01:00
CW_USEDEFAULT , 0 ,
640 , 480 ,
NULL , NULL ,
2019-12-06 16:51:04 +01:00
GetModuleHandle ( NULL ),
2019-12-05 14:07:02 +01:00
NULL );
2019-12-06 16:51:04 +01:00
if ( hWnd == NULL )
{
DWORD err = GetLastError ();
}
//ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow ( hWnd );
2019-11-28 13:38:08 +01:00
}
2019-12-06 16:51:04 +01:00
2019-12-05 14:07:02 +01:00
INT_PTR WINAPI WinProcCallback ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
2019-12-13 11:52:08 +01:00
// here we need to catch messeges about device removal
// problem is that when ejecting usb (how is it implemented above) there is no messege dispached. Only after physical removal of the device.
//uncomment register_window() in init() to register and comment update() in GUI_App.cpp (only for windows!) to stop recieving periodical updates
2019-12-05 14:07:02 +01:00
LRESULT lRet = 1 ;
static HDEVNOTIFY hDeviceNotify ;
2019-12-06 16:51:04 +01:00
2019-12-05 14:07:02 +01:00
switch ( message )
{
case WM_CREATE :
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter ;
ZeroMemory ( & NotificationFilter , sizeof ( NotificationFilter ));
NotificationFilter . dbcc_size = sizeof ( DEV_BROADCAST_DEVICEINTERFACE );
NotificationFilter . dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE ;
NotificationFilter . dbcc_classguid = WceusbshGUID ;
2019-12-12 14:56:30 +01:00
hDeviceNotify = RegisterDeviceNotification ( hWnd , & NotificationFilter , DEVICE_NOTIFY_WINDOW_HANDLE );
2019-12-05 14:07:02 +01:00
break ;
2019-12-11 17:02:12 +01:00
2019-12-05 14:07:02 +01:00
case WM_DEVICECHANGE :
{
2019-12-13 11:52:08 +01:00
// here is the important
2019-12-06 16:51:04 +01:00
if ( wParam == DBT_DEVICEREMOVECOMPLETE )
2019-12-05 14:07:02 +01:00
{
2019-12-11 14:53:28 +01:00
- RemovableDriveManager :: get_instance (). update ( 0 , true );
2019-12-05 14:07:02 +01:00
}
}
break ;
2019-12-11 17:02:12 +01:00
2019-12-05 14:07:02 +01:00
default :
// Send all other messages on to the default windows handler.
lRet = DefWindowProc ( hWnd , message , wParam , lParam );
break ;
}
return lRet ;
}
2019-12-06 16:51:04 +01:00
2019-11-26 15:52:18 +01:00
#else
2019-11-27 11:33:36 +01:00
void RemovableDriveManager :: search_for_drives ()
2019-11-26 15:52:18 +01:00
{
2019-12-11 17:39:34 +01:00
m_current_drives . clear ();
2019-12-09 15:33:10 +01:00
#if __APPLE__
2019-12-13 11:52:08 +01:00
// if on macos obj-c class will enumerate
2019-12-10 14:10:47 +01:00
if ( m_rdmmm )
{
m_rdmmm -> list_devices ();
}
#else
2019-12-11 17:39:34 +01:00
2019-11-26 15:52:18 +01:00
//search /media/* folder
2019-11-28 16:35:22 +01:00
search_path ( "/media/*" , "/media" );
2019-11-26 15:52:18 +01:00
2019-12-10 14:41:49 +01:00
/*
2019-12-04 10:05:18 +01:00
//search /Volumes/* folder (OSX)
search_path("/Volumes/*", "/Volumes");
2019-12-10 14:41:49 +01:00
*/
2019-11-28 16:35:22 +01:00
std :: string path ( std :: getenv ( "USER" ));
std :: string pp ( path );
//std::cout << "user: "<< path << "\n";
2019-12-04 11:47:47 +01:00
//if program is run with sudo, we have to search for all users
// but do we want that?
/*
if(path == "root"){
2019-11-28 16:35:22 +01:00
while (true) {
passwd* entry = getpwent();
if (!entry) {
break;
}
path = entry->pw_name;
pp = path;
//search /media/USERNAME/* folder
pp = "/media/"+pp;
path = "/media/" + path + "/*";
search_path(path, pp);
2019-11-26 15:52:18 +01:00
2019-11-28 16:35:22 +01:00
//search /run/media/USERNAME/* folder
path = "/run" + path;
pp = "/run"+pp;
search_path(path, pp);
}
endpwent();
}else
2019-12-04 11:47:47 +01:00
*/
2019-11-28 16:35:22 +01:00
{
//search /media/USERNAME/* folder
pp = "/media/" + pp ;
path = "/media/" + path + "/*" ;
search_path ( path , pp );
2019-11-26 15:52:18 +01:00
2019-11-28 16:35:22 +01:00
//search /run/media/USERNAME/* folder
path = "/run" + path ;
pp = "/run" + pp ;
search_path ( path , pp );
2019-11-26 15:52:18 +01:00
2019-11-28 16:35:22 +01:00
}
2019-12-10 14:10:47 +01:00
#endif
2019-11-26 15:52:18 +01:00
}
2019-11-28 16:35:22 +01:00
void RemovableDriveManager :: search_path ( const std :: string & path , const std :: string & parent_path )
2019-11-26 15:52:18 +01:00
{
glob_t globbuf ;
globbuf . gl_offs = 2 ;
int error = glob ( path . c_str (), GLOB_TILDE , NULL , & globbuf );
2019-11-28 16:35:22 +01:00
if ( error == 0 )
2019-11-26 15:52:18 +01:00
{
2019-11-27 14:30:10 +01:00
for ( size_t i = 0 ; i < globbuf . gl_pathc ; i ++ )
2019-11-26 15:52:18 +01:00
{
2019-12-10 14:41:49 +01:00
inspect_file ( globbuf . gl_pathv [ i ], parent_path );
2019-11-26 15:52:18 +01:00
}
2019-11-28 16:35:22 +01:00
} else
{
//if error - path probably doesnt exists so function just exits
//std::cout<<"glob error "<< error<< "\n";
2019-11-26 15:52:18 +01:00
}
2019-11-27 14:30:10 +01:00
2019-11-26 15:52:18 +01:00
globfree ( & globbuf );
}
2019-12-10 14:10:47 +01:00
void RemovableDriveManager :: inspect_file ( const std :: string & path , const std :: string & parent_path )
{
2019-12-13 11:52:08 +01:00
//confirms if the file is removable drive and adds it to vector
2019-12-10 14:10:47 +01:00
//if not same file system - could be removable drive
2019-12-10 14:41:49 +01:00
if ( ! compare_filesystem_id ( path , parent_path ))
2019-12-10 14:10:47 +01:00
{
//user id
struct stat buf ;
2019-12-10 14:41:49 +01:00
stat ( path . c_str (), & buf );
2019-12-10 14:10:47 +01:00
uid_t uid = buf . st_uid ;
std :: string username ( std :: getenv ( "USER" ));
struct passwd * pw = getpwuid ( uid );
if ( pw != 0 )
{
if ( pw -> pw_name == username )
{
2019-12-10 14:41:49 +01:00
std :: string name = basename ( const_cast < char *> ( path . c_str ()));
m_current_drives . push_back ( DriveData ( name , path ));
2019-12-10 14:10:47 +01:00
}
}
}
}
2019-11-28 16:35:22 +01:00
bool RemovableDriveManager :: compare_filesystem_id ( const std :: string & path_a , const std :: string & path_b )
{
struct stat buf ;
stat ( path_a . c_str () , & buf );
dev_t id_a = buf . st_dev ;
stat ( path_b . c_str () , & buf );
dev_t id_b = buf . st_dev ;
return id_a == id_b ;
}
2019-11-27 11:33:36 +01:00
void RemovableDriveManager :: eject_drive ( const std :: string & path )
2019-11-26 15:52:18 +01:00
{
2019-11-27 11:33:36 +01:00
if ( m_current_drives . empty ())
2019-11-26 15:52:18 +01:00
return ;
2019-11-27 11:33:36 +01:00
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
2019-11-26 15:52:18 +01:00
{
if (( * it ). path == path )
{
2019-12-04 13:10:08 +01:00
std :: string correct_path ( path );
for ( size_t i = 0 ; i < correct_path . size (); ++ i )
{
if ( correct_path [ i ] == ' ' )
{
2019-12-04 13:18:08 +01:00
correct_path = correct_path . insert ( i , 1 , '\\' );
2019-12-04 13:13:18 +01:00
i ++ ;
2019-12-04 13:10:08 +01:00
}
}
2019-12-04 13:21:41 +01:00
std :: cout << "Ejecting " << ( * it ). name << " from " << correct_path << " \n " ;
2019-12-13 11:52:08 +01:00
// there is no usable command in c++ so terminal command is used instead
// but neither triggers "succesful safe removal messege"
2019-12-04 13:30:25 +01:00
std :: string command = "" ;
#if __APPLE__
2019-12-17 13:08:17 +01:00
//m_rdmmm->eject_device(path);
2019-12-04 13:30:25 +01:00
command = "diskutil unmount " ;
#else
command = "umount " ;
#endif
2019-12-04 13:18:08 +01:00
command += correct_path ;
2019-12-03 10:09:53 +01:00
int err = system ( command . c_str ());
if ( err )
2019-11-26 15:52:18 +01:00
{
2019-12-03 10:09:53 +01:00
std :: cerr << "Ejecting failed \n " ;
return ;
2019-11-26 15:52:18 +01:00
}
2019-12-17 13:08:17 +01:00
2019-12-16 13:53:12 +01:00
m_did_eject = true ;
2019-11-27 11:33:36 +01:00
m_current_drives . erase ( it );
2019-12-03 10:09:53 +01:00
2019-11-26 15:52:18 +01:00
break ;
}
}
}
2019-11-27 14:30:10 +01:00
bool RemovableDriveManager :: is_path_on_removable_drive ( const std :: string & path )
{
if ( m_current_drives . empty ())
return false ;
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
{
2019-11-28 16:35:22 +01:00
if ( compare_filesystem_id ( path , ( * it ). path ))
2019-11-27 14:30:10 +01:00
return true ;
}
return false ;
}
2019-12-05 14:07:02 +01:00
std :: string RemovableDriveManager :: get_drive_from_path ( const std :: string & path )
{
//check if same filesystem
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
{
if ( compare_filesystem_id ( path , ( * it ). path ))
return ( * it ). path ;
}
return "" ;
}
2019-11-26 15:52:18 +01:00
#endif
2019-12-11 11:00:47 +01:00
RemovableDriveManager :: RemovableDriveManager () :
m_drives_count ( 0 ),
m_last_update ( 0 ),
2019-12-13 18:02:25 +01:00
m_last_save_path ( "" ),
m_last_save_name ( "" ),
2019-12-16 17:15:27 +01:00
m_last_save_path_verified ( false ),
2019-12-16 13:53:12 +01:00
m_is_writing ( false ),
m_did_eject ( false )
2019-12-11 11:00:47 +01:00
#if __APPLE__
2019-12-11 12:28:51 +01:00
, m_rdmmm ( new RDMMMWrapper ())
2019-12-11 11:00:47 +01:00
#endif
{}
2019-12-16 13:53:12 +01:00
RemovableDriveManager ::~ RemovableDriveManager ()
{
#if __APPLE__
delete m_rdmmm ;
#endif
}
2019-12-06 16:51:04 +01:00
void RemovableDriveManager :: init ()
{
2019-12-11 14:53:28 +01:00
//add_callback([](void) { RemovableDriveManager::get_instance().print(); });
2019-12-06 16:51:04 +01:00
#if _WIN32
2019-12-12 10:48:33 +01:00
//register_window();
2019-12-10 11:17:12 +01:00
#elif __APPLE__
2019-12-11 11:00:47 +01:00
m_rdmmm -> register_window ();
2019-12-06 16:51:04 +01:00
#endif
2019-12-16 14:06:25 +01:00
update ( 0 , true );
2019-12-06 16:51:04 +01:00
}
2019-12-12 14:56:30 +01:00
bool RemovableDriveManager :: update ( const long time , const bool check )
2019-11-26 15:52:18 +01:00
{
2019-11-27 15:47:37 +01:00
if ( time != 0 ) //time = 0 is forced update
{
2019-12-04 15:27:33 +01:00
long diff = m_last_update - time ;
2019-11-27 15:47:37 +01:00
if ( diff <= - 2 )
{
2019-12-04 15:27:33 +01:00
m_last_update = time ;
2019-11-27 15:47:37 +01:00
} else
{
return false ; // return value shouldnt matter if update didnt run
}
}
2019-11-27 11:33:36 +01:00
search_for_drives ();
2019-12-11 12:28:51 +01:00
if ( check ) check_and_notify ();
2019-11-27 11:33:36 +01:00
return ! m_current_drives . empty ();
2019-11-26 15:52:18 +01:00
}
2019-11-27 11:33:36 +01:00
bool RemovableDriveManager :: is_drive_mounted ( const std :: string & path )
2019-11-26 15:52:18 +01:00
{
2019-11-27 11:33:36 +01:00
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
2019-11-26 15:52:18 +01:00
{
if (( * it ). path == path )
{
return true ;
}
}
return false ;
}
2019-12-11 14:53:28 +01:00
std :: string RemovableDriveManager :: get_drive_path ()
{
if ( m_current_drives . size () == 0 )
{
reset_last_save_path ();
return "" ;
}
2019-12-16 17:15:27 +01:00
if ( m_last_save_path_verified )
2019-12-11 14:53:28 +01:00
return m_last_save_path ;
return m_current_drives . back (). path ;
}
std :: string RemovableDriveManager :: get_last_save_path ()
2019-11-26 14:19:29 +01:00
{
2019-12-16 17:15:27 +01:00
if ( ! m_last_save_path_verified )
return "" ;
2019-12-11 12:28:51 +01:00
return m_last_save_path ;
2019-11-26 14:19:29 +01:00
}
2019-12-13 18:02:25 +01:00
std :: string RemovableDriveManager :: get_last_save_name ()
{
return m_last_save_name ;
}
2019-11-27 11:33:36 +01:00
std :: vector < DriveData > RemovableDriveManager :: get_all_drives ()
2019-11-26 14:19:29 +01:00
{
2019-11-27 11:33:36 +01:00
return m_current_drives ;
2019-11-26 14:19:29 +01:00
}
2019-11-28 13:38:08 +01:00
void RemovableDriveManager :: check_and_notify ()
{
2019-12-03 10:09:53 +01:00
if ( m_drives_count != m_current_drives . size ())
2019-11-28 13:38:08 +01:00
{
2019-12-16 17:15:27 +01:00
if ( m_callbacks . size () != 0 && m_drives_count > m_current_drives . size () && m_last_save_path_verified && ! is_drive_mounted ( m_last_save_path ))
2019-11-28 13:38:08 +01:00
{
2019-12-05 14:07:02 +01:00
for ( auto it = m_callbacks . begin (); it != m_callbacks . end (); ++ it )
{
( * it )();
}
2019-11-28 13:38:08 +01:00
}
2019-12-03 10:09:53 +01:00
m_drives_count = m_current_drives . size ();
2019-11-28 13:38:08 +01:00
}
}
void RemovableDriveManager :: add_callback ( std :: function < void () > callback )
{
m_callbacks . push_back ( callback );
}
2019-12-06 13:21:44 +01:00
void RemovableDriveManager :: erase_callbacks ()
{
m_callbacks . clear ();
}
2019-12-05 14:07:02 +01:00
void RemovableDriveManager :: set_last_save_path ( const std :: string & path )
{
2019-12-18 09:36:26 +01:00
m_last_save_path_verified = false ;
2019-12-16 17:15:27 +01:00
m_last_save_path = path ;
}
void RemovableDriveManager :: verify_last_save_path ()
{
std :: string last_drive = get_drive_from_path ( m_last_save_path );
if ( last_drive != "" )
2019-12-05 14:07:02 +01:00
{
2019-12-16 17:15:27 +01:00
m_last_save_path_verified = true ;
2019-12-05 14:07:02 +01:00
m_last_save_path = last_drive ;
2019-12-13 18:02:25 +01:00
m_last_save_name = get_drive_name ( last_drive );
2019-12-05 14:07:02 +01:00
}
}
2019-12-13 18:02:25 +01:00
std :: string RemovableDriveManager :: get_drive_name ( const std :: string & path )
{
if ( m_current_drives . size () == 0 )
return "" ;
for ( auto it = m_current_drives . begin (); it != m_current_drives . end (); ++ it )
{
if (( * it ). path == path )
{
return ( * it ). name ;
}
}
return "" ;
}
2019-12-05 14:07:02 +01:00
bool RemovableDriveManager :: is_last_drive_removed ()
{
2019-12-12 10:48:33 +01:00
//std::cout<<"is last: "<<m_last_save_path;
2019-12-16 13:53:12 +01:00
//m_drives_count = m_current_drives.size();
2019-12-16 17:15:27 +01:00
if ( ! m_last_save_path_verified )
2019-12-05 14:07:02 +01:00
{
2019-12-12 10:48:33 +01:00
//std::cout<<"\n";
2019-12-05 14:07:02 +01:00
return true ;
}
2019-12-11 12:28:51 +01:00
bool r = ! is_drive_mounted ( m_last_save_path );
if ( r ) reset_last_save_path ();
2019-12-12 10:48:33 +01:00
//std::cout<<" "<< r <<"\n";
2019-12-11 12:28:51 +01:00
return r ;
2019-12-05 14:07:02 +01:00
}
2019-12-05 16:22:54 +01:00
bool RemovableDriveManager :: is_last_drive_removed_with_update ( const long time )
{
2019-12-11 12:28:51 +01:00
update ( time , false );
2019-12-05 16:22:54 +01:00
return is_last_drive_removed ();
}
2019-12-05 14:07:02 +01:00
void RemovableDriveManager :: reset_last_save_path ()
{
2019-12-16 17:15:27 +01:00
m_last_save_path_verified = false ;
2019-12-05 14:07:02 +01:00
m_last_save_path = "" ;
2019-12-13 18:02:25 +01:00
m_last_save_name = "" ;
}
void RemovableDriveManager :: set_is_writing ( const bool b )
{
m_is_writing = b ;
2019-12-16 13:53:12 +01:00
if ( b )
{
m_did_eject = false ;
}
2019-12-13 18:02:25 +01:00
}
bool RemovableDriveManager :: get_is_writing ()
{
return m_is_writing ;
2019-12-05 14:07:02 +01:00
}
2019-12-16 13:53:12 +01:00
bool RemovableDriveManager :: get_did_eject ()
{
return m_did_eject ;
}
2019-12-18 09:56:38 +01:00
void RemovableDriveManager :: set_did_eject ( const bool b )
{
m_did_eject = b ;
}
2019-12-12 14:56:30 +01:00
}} //namespace Slicer::Gui