Merge branch 'dk_desktop'

This commit is contained in:
Lukas Matena 2024-12-13 13:58:41 +01:00
commit c1c49c2d6f
7 changed files with 115 additions and 14 deletions

View File

@ -59,10 +59,10 @@ std::optional<std::string> get_env(std::string_view key) {
return std::string{result}; return std::string{result};
} }
namespace Slic3r { namespace {
std::optional<boost::filesystem::path> get_home_config_dir() { std::optional<boost::filesystem::path> get_home_dir(const std::string& subfolder) {
if (auto result{get_env("HOME")}) { if (auto result{get_env("HOME")}) {
return *result + "/.config"; return *result + subfolder;
} else { } else {
std::optional<std::string> user_name{get_env("USER")}; std::optional<std::string> user_name{get_env("USER")};
if (!user_name) { if (!user_name) {
@ -78,13 +78,23 @@ std::optional<boost::filesystem::path> get_home_config_dir() {
who = getpwuid(getuid()); who = getpwuid(getuid());
} }
if (who) { if (who) {
return std::string{who->pw_dir} + "/.config"; return std::string{who->pw_dir} + subfolder;
} }
} }
return std::nullopt; return std::nullopt;
} }
} }
namespace Slic3r {
std::optional<boost::filesystem::path> get_home_config_dir() {
return get_home_dir("/.config");
}
std::optional<boost::filesystem::path> get_home_local_dir() {
return get_home_dir("/.local");
}
}
std::string GetDataDir() std::string GetDataDir()
{ {
if (auto result{get_env("XDG_CONFIG_HOME")}) { if (auto result{get_env("XDG_CONFIG_HOME")}) {

View File

@ -14,6 +14,7 @@ namespace Slic3r {
// Only defined on linux. // Only defined on linux.
std::optional<boost::filesystem::path> get_home_config_dir(); std::optional<boost::filesystem::path> get_home_config_dir();
std::optional<boost::filesystem::path> get_home_local_dir();
std::string get_default_datadir(); std::string get_default_datadir();

View File

@ -14,10 +14,10 @@
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/Platform.hpp" #include "libslic3r/Platform.hpp"
#include "libslic3r/Config.hpp" #include "libslic3r/Config.hpp"
#include "libslic3r/Utils/DirectoriesUtils.hpp"
#include <boost/nowide/fstream.hpp> // IWYU pragma: keep #include <boost/nowide/fstream.hpp> // IWYU pragma: keep
#include <boost/nowide/convert.hpp> #include <boost/nowide/convert.hpp>
#include <boost/filesystem.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/dll/runtime_symbol_info.hpp> #include <boost/dll/runtime_symbol_info.hpp>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
@ -224,6 +224,7 @@ 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. // methods that actually do / undo desktop integration. Static to be accesible from anywhere.
bool DesktopIntegrationDialog::is_integrated() bool DesktopIntegrationDialog::is_integrated()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
const AppConfig *app_config = wxGetApp().app_config; const AppConfig *app_config = wxGetApp().app_config;
std::string path(app_config->get("desktop_integration_app_path")); std::string path(app_config->get("desktop_integration_app_path"));
BOOST_LOG_TRIVIAL(debug) << "Desktop integration desktop file path: " << path; BOOST_LOG_TRIVIAL(debug) << "Desktop integration desktop file path: " << path;
@ -237,10 +238,12 @@ bool DesktopIntegrationDialog::is_integrated()
} }
bool DesktopIntegrationDialog::integration_possible() bool DesktopIntegrationDialog::integration_possible()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
return true; return true;
} }
void DesktopIntegrationDialog::perform_desktop_integration() void DesktopIntegrationDialog::perform_desktop_integration()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
BOOST_LOG_TRIVIAL(debug) << "performing desktop integration."; BOOST_LOG_TRIVIAL(debug) << "performing desktop integration.";
// Path to appimage // Path to appimage
const char *appimage_env = std::getenv("APPIMAGE"); const char *appimage_env = std::getenv("APPIMAGE");
@ -446,8 +449,9 @@ void DesktopIntegrationDialog::perform_desktop_integration()
} }
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess); wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess);
} }
void DesktopIntegrationDialog::undo_desktop_intgration() void DesktopIntegrationDialog::undo_desktop_integration()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
const AppConfig *app_config = wxGetApp().app_config; const AppConfig *app_config = wxGetApp().app_config;
// slicer .desktop // slicer .desktop
std::string path = std::string(app_config->get("desktop_integration_app_path")); std::string path = std::string(app_config->get("desktop_integration_app_path"));
@ -634,6 +638,7 @@ void DesktopIntegrationDialog::perform_downloader_desktop_integration()
} }
void DesktopIntegrationDialog::undo_downloader_registration() void DesktopIntegrationDialog::undo_downloader_registration()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
const AppConfig *app_config = wxGetApp().app_config; const AppConfig *app_config = wxGetApp().app_config;
std::string path = std::string(app_config->get("desktop_integration_URL_path")); std::string path = std::string(app_config->get("desktop_integration_URL_path"));
if (!path.empty()) { if (!path.empty()) {
@ -644,6 +649,7 @@ void DesktopIntegrationDialog::undo_downloader_registration()
} }
void DesktopIntegrationDialog::undo_downloader_registration_rigid() void DesktopIntegrationDialog::undo_downloader_registration_rigid()
{ {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
// Try ro find any PrusaSlicerURLProtocol.desktop files including alpha and beta and get rid of them // Try ro find any PrusaSlicerURLProtocol.desktop files including alpha and beta and get rid of them
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
@ -655,7 +661,7 @@ void DesktopIntegrationDialog::undo_downloader_registration_rigid()
target_candidates.emplace_back(GUI::into_u8(wxFileName::GetHomeDir()) + "/.local/share"); target_candidates.emplace_back(GUI::into_u8(wxFileName::GetHomeDir()) + "/.local/share");
resolve_path_from_var("XDG_DATA_HOME", target_candidates); resolve_path_from_var("XDG_DATA_HOME", target_candidates);
resolve_path_from_var("XDG_DATA_DIRS", target_candidates); resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
for (const std::string cand : target_candidates) { for (const std::string& cand : target_candidates) {
boost::filesystem::path apps_path = get_existing_dir(cand, "applications"); boost::filesystem::path apps_path = get_existing_dir(cand, "applications");
if (apps_path.empty()) { if (apps_path.empty()) {
continue; continue;
@ -675,6 +681,57 @@ void DesktopIntegrationDialog::undo_downloader_registration_rigid()
} }
} }
void DesktopIntegrationDialog::find_all_desktop_files(std::vector<boost::filesystem::path>& results)
{
// Try ro find any PrusaSlicer.desktop and PrusaSlicerGcodeViewer.desktop and PrusaSlicerURLProtocol.desktop files including alpha and beta
// For regular apps (f.e. appimage) this is true:
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
// If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.
// $XDG_DATA_DIRS defines the preference-ordered set of base directories to search for data files in addition to the $XDG_DATA_HOME base directory.
// 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.
// But flatpak resets XDG_DATA_HOME and XDG_DATA_DIRS, so we do not look into them
// Lets look into $HOME/.local/share, /usr/local/share/, /usr/share/
std::vector<std::string> target_candidates;
if (auto home_config_dir = Slic3r::get_home_local_dir(); home_config_dir) {
target_candidates.emplace_back((*home_config_dir).string() + "/share");
}
target_candidates.emplace_back("usr/local/share/");
target_candidates.emplace_back("usr/share/");
for (const std::string& cand : target_candidates) {
boost::filesystem::path apps_path = get_existing_dir(cand, "applications");
if (apps_path.empty()) {
continue;
}
for (const std::string& filename : {"PrusaSlicer","PrusaSlicerGcodeViewer","PrusaSlicerURLProtocol"}) {
for (const std::string& suffix : {"" , "-beta", "-alpha", "_beta", "_alpha"}) {
boost::filesystem::path file_path = apps_path / GUI::format("%1%%2%.desktop", filename, suffix);
boost::system::error_code ec;
if (!boost::filesystem::exists(file_path, ec) || ec) {
continue;
}
BOOST_LOG_TRIVIAL(debug) << "Desktop File found: " << file_path;
results.emplace_back(std::move(file_path));
}
}
}
}
void DesktopIntegrationDialog::remove_desktop_file_list(const std::vector<boost::filesystem::path>& list, std::vector<boost::filesystem::path>& fails)
{
for (const boost::filesystem::path& entry : list) {
boost::system::error_code ec;
if (!boost::filesystem::remove(entry, ec) || ec) {
BOOST_LOG_TRIVIAL(error) << "Failed to remove file " << entry << " ec: " << ec.message();
fails.emplace_back(entry);
continue;
}
BOOST_LOG_TRIVIAL(info) << "Desktop File removed: " << entry;
}
}
DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent) DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent)
: wxDialog(parent, wxID_ANY, _(L("Desktop Integration")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) : wxDialog(parent, wxID_ANY, _(L("Desktop Integration")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
{ {
@ -705,7 +762,7 @@ DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent)
if (can_undo){ if (can_undo){
wxButton *btn_undo = new wxButton(this, wxID_ANY, _L("Undo")); wxButton *btn_undo = new wxButton(this, wxID_ANY, _L("Undo"));
btn_szr->Add(btn_undo, 0, wxALL, 10); btn_szr->Add(btn_undo, 0, wxALL, 10);
btn_undo->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { DesktopIntegrationDialog::undo_desktop_intgration(); EndModal(wxID_ANY); }); btn_undo->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { DesktopIntegrationDialog::undo_desktop_integration(); EndModal(wxID_ANY); });
} }
wxButton *btn_cancel = new wxButton(this, wxID_ANY, _L("Cancel")); wxButton *btn_cancel = new wxButton(this, wxID_ANY, _L("Cancel"));
btn_szr->Add(btn_cancel, 0, wxALL, 10); btn_szr->Add(btn_cancel, 0, wxALL, 10);
@ -718,7 +775,6 @@ DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent)
DesktopIntegrationDialog::~DesktopIntegrationDialog() DesktopIntegrationDialog::~DesktopIntegrationDialog()
{ {
} }
} // namespace GUI } // namespace GUI

View File

@ -7,6 +7,8 @@
#define slic3r_DesktopIntegrationDialog_hpp_ #define slic3r_DesktopIntegrationDialog_hpp_
#include <wx/dialog.h> #include <wx/dialog.h>
#include <boost/filesystem.hpp>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -35,13 +37,13 @@ public:
// Regiters PrusaSlicer to start on prusaslicer:// URL // Regiters PrusaSlicer to start on prusaslicer:// URL
static void perform_desktop_integration(); static void perform_desktop_integration();
// Deletes Desktop files and icons for both PrusaSlicer and GcodeViewer at paths stored in App Config. // Deletes Desktop files and icons for both PrusaSlicer and GcodeViewer at paths stored in App Config.
static void undo_desktop_intgration(); static void undo_desktop_integration();
static void perform_downloader_desktop_integration(); static void perform_downloader_desktop_integration();
static void undo_downloader_registration(); static void undo_downloader_registration();
static void undo_downloader_registration_rigid(); static void undo_downloader_registration_rigid();
private: static void find_all_desktop_files(std::vector<boost::filesystem::path>& results);
static void remove_desktop_file_list(const std::vector<boost::filesystem::path>& list, std::vector<boost::filesystem::path>& fails);
}; };
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -1311,6 +1311,31 @@ static int get_app_font_pt_size(const AppConfig* app_config)
return (font_pt_size > max_font_pt_size) ? max_font_pt_size : font_pt_size; return (font_pt_size > max_font_pt_size) ? max_font_pt_size : font_pt_size;
} }
#if defined(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
void GUI_App::remove_desktop_files_dialog()
{
// Find all old existing desktop file
std::vector<boost::filesystem::path> found_desktop_files;
DesktopIntegrationDialog::find_all_desktop_files(found_desktop_files);
if(found_desktop_files.empty()) {
return;
}
// Delete files.
std::vector<boost::filesystem::path> fails;
DesktopIntegrationDialog::remove_desktop_file_list(found_desktop_files, fails);
if (fails.empty()) {
return;
}
// Inform about fails.
std::string text = "Failed to remove desktop files:";
text += "\n";
for (const boost::filesystem::path& entry : fails) {
text += GUI::format("%1%\n",entry.string());
}
BOOST_LOG_TRIVIAL(error) << text;
}
#endif //(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
bool GUI_App::on_init_inner() bool GUI_App::on_init_inner()
{ {
// TODO: remove this when all asserts are gone. // TODO: remove this when all asserts are gone.
@ -1569,6 +1594,10 @@ bool GUI_App::on_init_inner()
// Call this check only after appconfig was loaded to mainframe, otherwise there will be duplicity error. // Call this check only after appconfig was loaded to mainframe, otherwise there will be duplicity error.
legacy_app_config_vendor_check(); legacy_app_config_vendor_check();
#if defined(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
remove_desktop_files_dialog();
#endif //(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
sidebar().obj_list()->init_objects(); // propagate model objects to object list sidebar().obj_list()->init_objects(); // propagate model objects to object list
update_mode(); // mode sizer doesn't exist anymore, so we came update mode here, before load_current_presets update_mode(); // mode sizer doesn't exist anymore, so we came update mode here, before load_current_presets
SetTopWindow(mainframe); SetTopWindow(mainframe);

View File

@ -453,6 +453,9 @@ private:
void app_updater(bool from_user); void app_updater(bool from_user);
// inititate read of version file online in separate thread // inititate read of version file online in separate thread
void app_version_check(bool from_user); void app_version_check(bool from_user);
#if defined(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
void remove_desktop_files_dialog();
#endif //(__linux__) && !defined(SLIC3R_DESKTOP_INTEGRATION)
bool m_wifi_config_dialog_shown { false }; bool m_wifi_config_dialog_shown { false };
bool m_wifi_config_dialog_was_declined { false }; bool m_wifi_config_dialog_was_declined { false };