Desktop integration changes
empty catch block fix internal namespace fix wrong app config var Desktop integration for regular executables cmake option SLIC3R_DESKTOP_INTEGRATION cmake dependent option escape executable path in desktop file by adding /' Error messages instead of notifications.
This commit is contained in:
parent
a3b089eceb
commit
12328a74f7
@ -3,6 +3,7 @@ project(PrusaSlicer)
|
||||
|
||||
include("version.inc")
|
||||
include(GNUInstallDirs)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
|
||||
file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
|
||||
@ -32,6 +33,8 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
||||
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
||||
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
|
||||
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
|
||||
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 0 "NOT SLIC3R_FHS" 0)
|
||||
|
||||
set(OPENVDB_FIND_MODULE_PATH "" CACHE PATH "Path to OpenVDB installation's find modules.")
|
||||
|
||||
@ -71,6 +74,10 @@ if (SLIC3R_GUI)
|
||||
add_definitions(-DSLIC3R_GUI)
|
||||
endif ()
|
||||
|
||||
if(SLIC3R_DESKTOP_INTEGRATION)
|
||||
add_definitions(-DSLIC3R_DESKTOP_INTEGRATION)
|
||||
endif ()
|
||||
|
||||
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(IS_CLANG_CL TRUE)
|
||||
|
||||
|
@ -1,15 +1,18 @@
|
||||
#ifdef __linux__
|
||||
#include "DesktopIntegrationDialog.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "format.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "NotificationManager.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Platform.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/dll/runtime_symbol_info.hpp>
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/stattext.h>
|
||||
@ -17,9 +20,9 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
namespace integrate_desktop_internal{
|
||||
namespace {
|
||||
// Disects path strings stored in system variable divided by ':' and adds into vector
|
||||
static void resolve_path_from_var(const std::string& var, std::vector<std::string>& paths)
|
||||
void resolve_path_from_var(const std::string& var, std::vector<std::string>& paths)
|
||||
{
|
||||
wxString wxdirs;
|
||||
if (! wxGetEnv(boost::nowide::widen(var), &wxdirs) || wxdirs.empty() )
|
||||
@ -34,7 +37,7 @@ static void resolve_path_from_var(const std::string& var, std::vector<std::strin
|
||||
paths.push_back(dirs);
|
||||
}
|
||||
// Return true if directory in path p+dir_name exists
|
||||
static bool contains_path_dir(const std::string& p, const std::string& dir_name)
|
||||
bool contains_path_dir(const std::string& p, const std::string& dir_name)
|
||||
{
|
||||
if (p.empty() || dir_name.empty())
|
||||
return false;
|
||||
@ -47,7 +50,7 @@ static bool contains_path_dir(const std::string& p, const std::string& dir_name)
|
||||
return false;
|
||||
}
|
||||
// Creates directory in path if not exists yet
|
||||
static void create_dir(const boost::filesystem::path& path)
|
||||
void create_dir(const boost::filesystem::path& path)
|
||||
{
|
||||
if (boost::filesystem::exists(path))
|
||||
return;
|
||||
@ -58,7 +61,7 @@ static void create_dir(const boost::filesystem::path& path)
|
||||
BOOST_LOG_TRIVIAL(error)<< "create directory failed: " << ec.message();
|
||||
}
|
||||
// Starts at basic_path (excluded) and creates all directories in dir_path
|
||||
static void create_path(const std::string& basic_path, const std::string& dir_path)
|
||||
void create_path(const std::string& basic_path, const std::string& dir_path)
|
||||
{
|
||||
if (basic_path.empty() || dir_path.empty())
|
||||
return;
|
||||
@ -76,7 +79,7 @@ static void create_path(const std::string& basic_path, const std::string& dir_pa
|
||||
create_dir(path);
|
||||
}
|
||||
// Calls our internal copy_file function to copy file at icon_path to dest_path
|
||||
static bool copy_icon(const std::string& icon_path, const std::string& dest_path)
|
||||
bool copy_icon(const std::string& icon_path, const std::string& dest_path)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) <<"icon from "<< icon_path;
|
||||
BOOST_LOG_TRIVIAL(debug) <<"icon to "<< dest_path;
|
||||
@ -90,7 +93,7 @@ static bool copy_icon(const std::string& icon_path, const std::string& dest_path
|
||||
return true;
|
||||
}
|
||||
// Creates new file filled with data.
|
||||
static bool create_desktop_file(const std::string& path, const std::string& data)
|
||||
bool create_desktop_file(const std::string& path, const std::string& data)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) <<".desktop to "<< path;
|
||||
std::ofstream output(path);
|
||||
@ -109,10 +112,6 @@ static bool create_desktop_file(const std::string& path, const std::string& data
|
||||
// methods that actually do / undo desktop integration. Static to be accesible from anywhere.
|
||||
bool DesktopIntegrationDialog::is_integrated()
|
||||
{
|
||||
const char *appimage_env = std::getenv("APPIMAGE");
|
||||
if (!appimage_env)
|
||||
return false;
|
||||
|
||||
const AppConfig *app_config = wxGetApp().app_config;
|
||||
std::string path(app_config->get("desktop_integration_app_path"));
|
||||
BOOST_LOG_TRIVIAL(debug) << "Desktop integration desktop file path: " << path;
|
||||
@ -126,10 +125,6 @@ bool DesktopIntegrationDialog::is_integrated()
|
||||
}
|
||||
bool DesktopIntegrationDialog::integration_possible()
|
||||
{
|
||||
|
||||
const char *appimage_env = std::getenv("APPIMAGE");
|
||||
if (!appimage_env)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
@ -143,13 +138,25 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
try {
|
||||
appimage_path = boost::filesystem::canonical(boost::filesystem::path(appimage_env)).string();
|
||||
} catch (std::exception &) {
|
||||
}
|
||||
} else {
|
||||
// not appimage - not performing
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - not Appimage executable.";
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - boost::filesystem::canonical did not return appimage path.";
|
||||
show_error(nullptr, _L("Performing desktop integration failed - boost::filesystem::canonical did not return appimage path."));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// not appimage - find executable
|
||||
appimage_path = boost::dll::program_location().string();
|
||||
//appimage_path = wxStandardPaths::Get().GetExecutablePath().string();
|
||||
BOOST_LOG_TRIVIAL(debug) << "non-appimage path to executable: " << appimage_path;
|
||||
if (appimage_path.empty())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - no executable found.";
|
||||
show_error(nullptr, _L("Performing desktop integration failed - Could not find executable."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Escape ' characters in appimage, other special symbols will be esacaped in desktop file by 'appimage_path'
|
||||
//appimage_path = std::regex_replace(appimage_path, std::regex("\'"), "\\\'");
|
||||
|
||||
// Find directories icons and applications
|
||||
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
|
||||
@ -158,8 +165,8 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
// The directories in $XDG_DATA_DIRS should be seperated with a colon ':'.
|
||||
// If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.
|
||||
std::vector<std::string>target_candidates;
|
||||
integrate_desktop_internal::resolve_path_from_var("XDG_DATA_HOME", target_candidates);
|
||||
integrate_desktop_internal::resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
|
||||
resolve_path_from_var("XDG_DATA_HOME", target_candidates);
|
||||
resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
|
||||
|
||||
AppConfig *app_config = wxGetApp().app_config;
|
||||
// suffix string to create different desktop file for alpha, beta.
|
||||
@ -186,7 +193,6 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
icon_theme_dirs = "/hicolor/96x96/apps";
|
||||
}
|
||||
|
||||
|
||||
std::string target_dir_icons;
|
||||
std::string target_dir_desktop;
|
||||
|
||||
@ -194,24 +200,24 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
// iterate thru target_candidates to find icons folder
|
||||
for (size_t i = 0; i < target_candidates.size(); ++i) {
|
||||
// Copy icon PrusaSlicer.png from resources_dir()/icons to target_dir_icons/icons/
|
||||
if (integrate_desktop_internal::contains_path_dir(target_candidates[i], "icons")) {
|
||||
if (contains_path_dir(target_candidates[i], "icons")) {
|
||||
target_dir_icons = target_candidates[i];
|
||||
std::string icon_path = GUI::format("%1%/icons/PrusaSlicer.png",resources_dir());
|
||||
std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
|
||||
if (integrate_desktop_internal::copy_icon(icon_path, dest_path))
|
||||
if (copy_icon(icon_path, dest_path))
|
||||
break; // success
|
||||
else
|
||||
target_dir_icons.clear(); // copying failed
|
||||
// if all failed - try creating default home folder
|
||||
if (i == target_candidates.size() - 1) {
|
||||
// create $HOME/.local/share
|
||||
integrate_desktop_internal::create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
|
||||
// copy icon
|
||||
target_dir_icons = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
|
||||
std::string icon_path = GUI::format("%1%/icons/PrusaSlicer.png",resources_dir());
|
||||
std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
|
||||
if (!integrate_desktop_internal::contains_path_dir(target_dir_icons, "icons")
|
||||
|| !integrate_desktop_internal::copy_icon(icon_path, dest_path)) {
|
||||
if (!contains_path_dir(target_dir_icons, "icons")
|
||||
|| !copy_icon(icon_path, dest_path)) {
|
||||
// every attempt failed - icon wont be present
|
||||
target_dir_icons.clear();
|
||||
}
|
||||
@ -228,7 +234,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
// iterate thru target_candidates to find applications folder
|
||||
for (size_t i = 0; i < target_candidates.size(); ++i)
|
||||
{
|
||||
if (integrate_desktop_internal::contains_path_dir(target_candidates[i], "applications")) {
|
||||
if (contains_path_dir(target_candidates[i], "applications")) {
|
||||
target_dir_desktop = target_candidates[i];
|
||||
// Write slicer desktop file
|
||||
std::string desktop_file = GUI::format(
|
||||
@ -236,7 +242,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
"Name=PrusaSlicer%1%\n"
|
||||
"GenericName=3D Printing Software\n"
|
||||
"Icon=PrusaSlicer%2%\n"
|
||||
"Exec=%3% %%F\n"
|
||||
"Exec=\'%3%\' %%F\n"
|
||||
"Terminal=false\n"
|
||||
"Type=Application\n"
|
||||
"MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n"
|
||||
@ -246,23 +252,23 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
"StartupWMClass=prusa-slicer", name_suffix, version_suffix, appimage_path);
|
||||
|
||||
std::string path = GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (integrate_desktop_internal::create_desktop_file(path, desktop_file)){
|
||||
if (create_desktop_file(path, desktop_file)){
|
||||
BOOST_LOG_TRIVIAL(debug) << "PrusaSlicer.desktop file installation success.";
|
||||
break;
|
||||
} else {
|
||||
// write failed - try another path
|
||||
BOOST_LOG_TRIVIAL(error) << "PrusaSlicer.desktop file installation failed.";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Attempt to PrusaSlicer.desktop file installation failed. failed path: " << target_candidates[i];
|
||||
target_dir_desktop.clear();
|
||||
}
|
||||
// if all failed - try creating default home folder
|
||||
if (i == target_candidates.size() - 1) {
|
||||
// create $HOME/.local/share
|
||||
integrate_desktop_internal::create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
// create desktop file
|
||||
target_dir_desktop = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
|
||||
std::string path = GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (integrate_desktop_internal::contains_path_dir(target_dir_desktop, "applications")) {
|
||||
if (!integrate_desktop_internal::create_desktop_file(path, desktop_file)) {
|
||||
if (contains_path_dir(target_dir_desktop, "applications")) {
|
||||
if (!create_desktop_file(path, desktop_file)) {
|
||||
// Desktop file not written - end desktop integration
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create desktop file";
|
||||
return;
|
||||
@ -278,7 +284,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
if(target_dir_desktop.empty()) {
|
||||
// Desktop file not written - end desktop integration
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not find applications directory";
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
|
||||
show_error(nullptr, _L("Performing desktop integration failed - could not find applications directory."));
|
||||
return;
|
||||
}
|
||||
// save path to desktop file
|
||||
@ -290,7 +296,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
{
|
||||
std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir());
|
||||
std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
|
||||
if (integrate_desktop_internal::copy_icon(icon_path, dest_path))
|
||||
if (copy_icon(icon_path, dest_path))
|
||||
// save path to icon
|
||||
app_config->set("desktop_integration_icon_viewer_path", dest_path);
|
||||
else
|
||||
@ -303,7 +309,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
"Name=Prusa Gcode Viewer%1%\n"
|
||||
"GenericName=3D Printing Software\n"
|
||||
"Icon=PrusaSlicer-gcodeviewer%2%\n"
|
||||
"Exec=%3% --gcodeviwer %%F\n"
|
||||
"Exec=\'%3%\' --gcodeviwer %%F\n"
|
||||
"Terminal=false\n"
|
||||
"Type=Application\n"
|
||||
"MimeType=text/x.gcode;\n"
|
||||
@ -312,23 +318,17 @@ void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
"StartupNotify=false", name_suffix, version_suffix, appimage_path);
|
||||
|
||||
std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (integrate_desktop_internal::create_desktop_file(desktop_path, desktop_file))
|
||||
if (create_desktop_file(desktop_path, desktop_file))
|
||||
// save path to desktop file
|
||||
app_config->set("desktop_integration_app_viewer_path", desktop_path);
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could create gcode viewer desktop file";
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file";
|
||||
show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully."));
|
||||
}
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess);
|
||||
}
|
||||
void DesktopIntegrationDialog::undo_desktop_intgration()
|
||||
{
|
||||
const char *appimage_env = std::getenv("APPIMAGE");
|
||||
if (!appimage_env) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Undo desktop integration failed - not Appimage executable.";
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::UndoDesktopIntegrationFail);
|
||||
return;
|
||||
}
|
||||
const AppConfig *app_config = wxGetApp().app_config;
|
||||
// slicer .desktop
|
||||
std::string path = std::string(app_config->get("desktop_integration_app_path"));
|
||||
|
@ -1806,10 +1806,10 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
||||
local_menu->Append(config_id_base + ConfigMenuSnapshots, _L("&Configuration Snapshots") + dots, _L("Inspect / activate configuration snapshots"));
|
||||
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot"));
|
||||
local_menu->Append(config_id_base + ConfigMenuUpdate, _L("Check for updates"), _L("Check for configuration updates"));
|
||||
#ifdef __linux__
|
||||
if (DesktopIntegrationDialog::integration_possible())
|
||||
#if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
|
||||
//if (DesktopIntegrationDialog::integration_possible())
|
||||
local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration"));
|
||||
#endif
|
||||
#endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
|
||||
local_menu->AppendSeparator();
|
||||
}
|
||||
local_menu->Append(config_id_base + ConfigMenuPreferences, _L("&Preferences") + dots +
|
||||
|
Loading…
Reference in New Issue
Block a user