merge s kocikdav fork removable_drives branch
This commit is contained in:
commit
2ecc8a1b6f
6 changed files with 403 additions and 1 deletions
|
@ -111,6 +111,8 @@ set(SLIC3R_GUI_SOURCES
|
||||||
GUI/WipeTowerDialog.hpp
|
GUI/WipeTowerDialog.hpp
|
||||||
GUI/RammingChart.cpp
|
GUI/RammingChart.cpp
|
||||||
GUI/RammingChart.hpp
|
GUI/RammingChart.hpp
|
||||||
|
GUI/RemovableDriveManager.cpp
|
||||||
|
GUI/RemovableDriveManager.hpp
|
||||||
GUI/BonjourDialog.cpp
|
GUI/BonjourDialog.cpp
|
||||||
GUI/BonjourDialog.hpp
|
GUI/BonjourDialog.hpp
|
||||||
GUI/ButtonsDescription.cpp
|
GUI/ButtonsDescription.cpp
|
||||||
|
|
|
@ -357,6 +357,7 @@ void AppConfig::update_skein_dir(const std::string &dir)
|
||||||
|
|
||||||
std::string AppConfig::get_last_output_dir(const std::string &alt) const
|
std::string AppConfig::get_last_output_dir(const std::string &alt) const
|
||||||
{
|
{
|
||||||
|
|
||||||
const auto it = m_storage.find("");
|
const auto it = m_storage.find("");
|
||||||
if (it != m_storage.end()) {
|
if (it != m_storage.end()) {
|
||||||
const auto it2 = it->second.find("last_output_path");
|
const auto it2 = it->second.find("last_output_path");
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "SysInfoDialog.hpp"
|
#include "SysInfoDialog.hpp"
|
||||||
#include "KBShortcutsDialog.hpp"
|
#include "KBShortcutsDialog.hpp"
|
||||||
#include "UpdateDialogs.hpp"
|
#include "UpdateDialogs.hpp"
|
||||||
|
#include "RemovableDriveManager.hpp"
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
#include <Shlobj.h>
|
#include <Shlobj.h>
|
||||||
|
@ -269,6 +270,8 @@ bool GUI_App::on_init_inner()
|
||||||
|
|
||||||
this->obj_manipul()->update_if_dirty();
|
this->obj_manipul()->update_if_dirty();
|
||||||
|
|
||||||
|
RemovableDriveManager::get_instance().update(wxGetLocalTime());
|
||||||
|
|
||||||
// Preset updating & Configwizard are done after the above initializations,
|
// Preset updating & Configwizard are done after the above initializations,
|
||||||
// and after MainFrame is created & shown.
|
// and after MainFrame is created & shown.
|
||||||
// The extra CallAfter() is needed because of Mac, where this is the only way
|
// The extra CallAfter() is needed because of Mac, where this is the only way
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
#include "../Utils/FixModelByWin10.hpp"
|
#include "../Utils/FixModelByWin10.hpp"
|
||||||
#include "../Utils/UndoRedo.hpp"
|
#include "../Utils/UndoRedo.hpp"
|
||||||
#include "../Utils/Thread.hpp"
|
#include "../Utils/Thread.hpp"
|
||||||
|
#include "RemovableDriveManager.hpp"
|
||||||
|
|
||||||
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
||||||
#include "WipeTowerDialog.hpp"
|
#include "WipeTowerDialog.hpp"
|
||||||
|
@ -4555,7 +4556,13 @@ void Plater::export_gcode()
|
||||||
}
|
}
|
||||||
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
||||||
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
|
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
|
||||||
|
if (GUI::RemovableDriveManager::get_instance().update())
|
||||||
|
{
|
||||||
|
if (!RemovableDriveManager::get_instance().is_path_on_removable_drive(start_dir))
|
||||||
|
{
|
||||||
|
start_dir = RemovableDriveManager::get_instance().get_last_drive_path();
|
||||||
|
}
|
||||||
|
}
|
||||||
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
|
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
|
||||||
start_dir,
|
start_dir,
|
||||||
from_path(default_output_file.filename()),
|
from_path(default_output_file.filename()),
|
||||||
|
|
339
src/slic3r/GUI/RemovableDriveManager.cpp
Normal file
339
src/slic3r/GUI/RemovableDriveManager.cpp
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
#include "RemovableDriveManager.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include "boost/nowide/convert.hpp"
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,
|
||||||
|
0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
|
||||||
|
#else
|
||||||
|
//linux includes
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
//std::vector<DriveData> RemovableDriveManager::m_current_drives;
|
||||||
|
//std::vector<std::function<void()>> RemovableDriveManager::m_callbacks;
|
||||||
|
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
void RemovableDriveManager::search_for_drives()
|
||||||
|
{
|
||||||
|
m_current_drives.clear();
|
||||||
|
m_current_drives.reserve(26);
|
||||||
|
DWORD drives_mask = GetLogicalDrives();
|
||||||
|
for (size_t i = 0; i < 26; i++)
|
||||||
|
{
|
||||||
|
if(drives_mask & (1 << i))
|
||||||
|
{
|
||||||
|
std::string path (1,(char)('A' + i));
|
||||||
|
path+=":";
|
||||||
|
UINT drive_type = GetDriveTypeA(path.c_str());
|
||||||
|
//std::cout << "found drive" << (char)('A' + i) << ": type:" <<driveType << "\n";
|
||||||
|
if (drive_type == DRIVE_REMOVABLE)
|
||||||
|
{
|
||||||
|
// get name of drive
|
||||||
|
std::wstring wpath = std::wstring(path.begin(), path.end());
|
||||||
|
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));
|
||||||
|
if(error != 0)
|
||||||
|
{
|
||||||
|
if (volume_name == L"")
|
||||||
|
{
|
||||||
|
volume_name = L"REMOVABLE DRIVE";
|
||||||
|
}
|
||||||
|
if (file_system_name != L"")
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER free_space;
|
||||||
|
GetDiskFreeSpaceExA(path.c_str(), &free_space, NULL, NULL);
|
||||||
|
//std::cout << std::string(volumeName.begin(), volumeName.end()) << " " << std::string(fileSystemName.begin(), fileSystemName.end()) << " " << freeSpace.QuadPart << "\n";
|
||||||
|
if (free_space.QuadPart > 0)
|
||||||
|
{
|
||||||
|
path += "\\";
|
||||||
|
m_current_drives.push_back(DriveData(boost::nowide::narrow(volume_name), path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cout << "found drives:" << m_current_drives.size() << "\n";
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::eject_drive(const std::string &path)
|
||||||
|
{
|
||||||
|
|
||||||
|
//if (!update() || !is_drive_mounted(path))
|
||||||
|
if(m_current_drives.empty())
|
||||||
|
return;
|
||||||
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it).path == path)
|
||||||
|
{
|
||||||
|
std::string mpath = "\\\\.\\" + path;
|
||||||
|
mpath = mpath.substr(0, mpath.size() - 1);
|
||||||
|
std::cout << "Ejecting " << mpath << "\n";
|
||||||
|
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);
|
||||||
|
BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
||||||
|
CloseHandle(handle);
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
std::cerr << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError() << " \n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_current_drives.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::register_window()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
WNDCLASSEX wndClass;
|
||||||
|
|
||||||
|
wndClass.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
|
||||||
|
wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback);
|
||||||
|
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);
|
||||||
|
wndClass.lpszClassName = L"SlicerWindowClass";
|
||||||
|
wndClass.lpszMenuName = NULL;
|
||||||
|
wndClass.hIconSm = wndClass.hIcon;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void RemovableDriveManager::search_for_drives()
|
||||||
|
{
|
||||||
|
|
||||||
|
m_current_drives.clear();
|
||||||
|
m_current_drives.reserve(26);
|
||||||
|
|
||||||
|
//search /media/* folder
|
||||||
|
search_path("/media/*", "/media");
|
||||||
|
|
||||||
|
std::string path(std::getenv("USER"));
|
||||||
|
std::string pp(path);
|
||||||
|
//std::cout << "user: "<< path << "\n";
|
||||||
|
if(path == "root"){ //if program is run with sudo, we have to search for all users
|
||||||
|
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);
|
||||||
|
|
||||||
|
//search /run/media/USERNAME/* folder
|
||||||
|
path = "/run" + path;
|
||||||
|
pp = "/run"+pp;
|
||||||
|
search_path(path, pp);
|
||||||
|
}
|
||||||
|
endpwent();
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
//search /media/USERNAME/* folder
|
||||||
|
pp = "/media/"+pp;
|
||||||
|
path = "/media/" + path + "/*";
|
||||||
|
search_path(path, pp);
|
||||||
|
|
||||||
|
//search /run/media/USERNAME/* folder
|
||||||
|
path = "/run" + path;
|
||||||
|
pp = "/run"+pp;
|
||||||
|
search_path(path, pp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cout << "found drives:" <<m_current_drives.size() << "\n";
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::search_path(const std::string &path,const std::string &parent_path)
|
||||||
|
{
|
||||||
|
glob_t globbuf;
|
||||||
|
globbuf.gl_offs = 2;
|
||||||
|
int error = glob(path.c_str(), GLOB_TILDE, NULL, &globbuf);
|
||||||
|
if(error == 0)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < globbuf.gl_pathc; i++)
|
||||||
|
{
|
||||||
|
//if not same file system - could be removable drive
|
||||||
|
if(!compare_filesystem_id(globbuf.gl_pathv[i], parent_path))
|
||||||
|
{
|
||||||
|
std::string name = basename(globbuf.gl_pathv[i]);
|
||||||
|
m_current_drives.push_back(DriveData(name,globbuf.gl_pathv[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
//if error - path probably doesnt exists so function just exits
|
||||||
|
//std::cout<<"glob error "<< error<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&globbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::eject_drive(const std::string &path)
|
||||||
|
{
|
||||||
|
if (m_current_drives.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
||||||
|
{
|
||||||
|
if((*it).path == path)
|
||||||
|
{
|
||||||
|
std::cout<<"Ejecting "<<(*it).name<<" from "<< (*it).path<<"\n";
|
||||||
|
std::string command = "umount ";
|
||||||
|
command += (*it).path;
|
||||||
|
int err = system(command.c_str());
|
||||||
|
if(err)
|
||||||
|
{
|
||||||
|
std::cerr<<"Ejecting failed\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_current_drives.erase(it);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if(compare_filesystem_id(path, (*it).path))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bool RemovableDriveManager::update(long time)
|
||||||
|
{
|
||||||
|
static long last_update = 0;
|
||||||
|
if(last_update == 0)
|
||||||
|
{
|
||||||
|
//add_callback(std::bind(&RemovableDriveManager::print, RemovableDriveManager::getInstance()));
|
||||||
|
add_callback([](void) { RemovableDriveManager::get_instance().print(); });
|
||||||
|
#if _WIN32
|
||||||
|
register_window();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(time != 0) //time = 0 is forced update
|
||||||
|
{
|
||||||
|
long diff = last_update - time;
|
||||||
|
if(diff <= -2)
|
||||||
|
{
|
||||||
|
last_update = time;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
return false; // return value shouldnt matter if update didnt run
|
||||||
|
}
|
||||||
|
}
|
||||||
|
search_for_drives();
|
||||||
|
check_and_notify();
|
||||||
|
return !m_current_drives.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RemovableDriveManager::is_drive_mounted(const std::string &path)
|
||||||
|
{
|
||||||
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it).path == path)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RemovableDriveManager::get_last_drive_path()
|
||||||
|
{
|
||||||
|
if (!m_current_drives.empty())
|
||||||
|
{
|
||||||
|
//#if _WIN32
|
||||||
|
// return m_current_drives.back().path + "\\";
|
||||||
|
//#else
|
||||||
|
return m_current_drives.back().path;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::vector<DriveData> RemovableDriveManager::get_all_drives()
|
||||||
|
{
|
||||||
|
return m_current_drives;
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::check_and_notify()
|
||||||
|
{
|
||||||
|
//std::cout<<"drives count: "<<m_drives_count;
|
||||||
|
if(m_drives_count != m_current_drives.size())
|
||||||
|
{
|
||||||
|
//std::cout<<" vs "<< m_current_drives.size();
|
||||||
|
for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it)
|
||||||
|
{
|
||||||
|
(*it)();
|
||||||
|
}
|
||||||
|
m_drives_count = m_current_drives.size();
|
||||||
|
}
|
||||||
|
//std::cout<<"\n";
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::add_callback(std::function<void()> callback)
|
||||||
|
{
|
||||||
|
m_callbacks.push_back(callback);
|
||||||
|
}
|
||||||
|
void RemovableDriveManager::print()
|
||||||
|
{
|
||||||
|
std::cout << "notified\n";
|
||||||
|
}
|
||||||
|
}}//namespace Slicer::Gui::
|
50
src/slic3r/GUI/RemovableDriveManager.hpp
Normal file
50
src/slic3r/GUI/RemovableDriveManager.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef slic3r_GUI_RemovableDriveManager_hpp_
|
||||||
|
#define slic3r_GUI_RemovableDriveManager_hpp_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
struct DriveData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string path;
|
||||||
|
DriveData(std::string n, std::string p):name(n),path(p){}
|
||||||
|
};
|
||||||
|
class RemovableDriveManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static RemovableDriveManager& get_instance()
|
||||||
|
{
|
||||||
|
static RemovableDriveManager instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
RemovableDriveManager(RemovableDriveManager const&) = delete;
|
||||||
|
void operator=(RemovableDriveManager const&) = delete;
|
||||||
|
|
||||||
|
//update() searches for removable devices, returns false if empty.
|
||||||
|
bool update(long time = 0); //time = 0 is forced update
|
||||||
|
bool is_drive_mounted(const std::string &path);
|
||||||
|
void eject_drive(const std::string &path);
|
||||||
|
std::string get_last_drive_path();
|
||||||
|
std::vector<DriveData> get_all_drives();
|
||||||
|
bool is_path_on_removable_drive(const std::string &path);
|
||||||
|
void add_callback(std::function<void()> callback);
|
||||||
|
void print();
|
||||||
|
private:
|
||||||
|
RemovableDriveManager():m_drives_count(0){}
|
||||||
|
void search_for_drives();
|
||||||
|
void check_and_notify();
|
||||||
|
std::vector<DriveData> m_current_drives;
|
||||||
|
std::vector<std::function<void()>> m_callbacks;
|
||||||
|
size_t m_drives_count;
|
||||||
|
#if _WIN32
|
||||||
|
void register_window();
|
||||||
|
#else
|
||||||
|
void search_path(const std::string &path, const std::string &parent_path);
|
||||||
|
bool compare_filesystem_id(const std::string &path_a, const std::string &path_b);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue