First draft of SendSystemInfoDialog
This commit is contained in:
parent
37219fe4f3
commit
faa808b385
@ -105,4 +105,42 @@ PlatformFlavor platform_flavor()
|
||||
return s_platform_flavor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string platform_to_string(Platform platform)
|
||||
{
|
||||
switch (platform) {
|
||||
case Platform::Uninitialized: return "Unitialized";
|
||||
case Platform::Unknown : return "Unknown";
|
||||
case Platform::Windows : return "Windows";
|
||||
case Platform::OSX : return "OSX";
|
||||
case Platform::Linux : return "Linux";
|
||||
case Platform::BSDUnix : return "BSDUnix";
|
||||
}
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string platform_flavor_to_string(PlatformFlavor pf)
|
||||
{
|
||||
switch (pf) {
|
||||
case PlatformFlavor::Uninitialized : return "Unitialized";
|
||||
case PlatformFlavor::Unknown : return "Unknown";
|
||||
case PlatformFlavor::Generic : return "Generic";
|
||||
case PlatformFlavor::GenericLinux : return "GenericLinux";
|
||||
case PlatformFlavor::LinuxOnChromium : return "LinuxOnChromium";
|
||||
case PlatformFlavor::WSL : return "WSL";
|
||||
case PlatformFlavor::WSL2 : return "WSL2";
|
||||
case PlatformFlavor::OpenBSD : return "OpenBSD";
|
||||
case PlatformFlavor::GenericOSX : return "GenericOSX";
|
||||
case PlatformFlavor::OSXOnX86 : return "OSXOnX86";
|
||||
case PlatformFlavor::OSXOnArm : return "OSXOnArm";
|
||||
}
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef SLIC3R_Platform_HPP
|
||||
#define SLIC3R_Platform_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class Platform
|
||||
@ -16,24 +18,16 @@ enum class Platform
|
||||
enum class PlatformFlavor
|
||||
{
|
||||
Uninitialized,
|
||||
Unknown,
|
||||
// For Windows and OSX, until we need to be more specific.
|
||||
Generic,
|
||||
// For Platform::Linux
|
||||
GenericLinux,
|
||||
LinuxOnChromium,
|
||||
// Microsoft's Windows on Linux (Linux kernel simulated on NTFS kernel)
|
||||
WSL,
|
||||
// Microsoft's Windows on Linux, version 2 (virtual machine)
|
||||
WSL2,
|
||||
// For Platform::BSDUnix
|
||||
OpenBSD,
|
||||
// For Platform::OSX
|
||||
GenericOSX,
|
||||
// For Apple's on Intel X86 CPU
|
||||
OSXOnX86,
|
||||
// For Apple's on Arm CPU
|
||||
OSXOnArm,
|
||||
Unknown,
|
||||
Generic, // For Windows and OSX, until we need to be more specific.
|
||||
GenericLinux, // For Platform::Linux
|
||||
LinuxOnChromium, // For Platform::Linux
|
||||
WSL, // Microsoft's Windows on Linux (Linux kernel simulated on NTFS kernel)
|
||||
WSL2, // Microsoft's Windows on Linux, version 2 (virtual machine)
|
||||
OpenBSD, // For Platform::BSDUnix
|
||||
GenericOSX, // For Platform::OSX
|
||||
OSXOnX86, // For Apple's on Intel X86 CPU
|
||||
OSXOnArm, // For Apple's on Arm CPU
|
||||
};
|
||||
|
||||
// To be called on program start-up.
|
||||
@ -42,6 +36,9 @@ void detect_platform();
|
||||
Platform platform();
|
||||
PlatformFlavor platform_flavor();
|
||||
|
||||
std::string platform_to_string(Platform platform);
|
||||
std::string platform_flavor_to_string(PlatformFlavor pf);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // SLIC3R_Platform_HPP
|
||||
|
@ -141,6 +141,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/RammingChart.hpp
|
||||
GUI/RemovableDriveManager.cpp
|
||||
GUI/RemovableDriveManager.hpp
|
||||
GUI/SendSystemInfoDialog.cpp
|
||||
GUI/SendSystemInfoDialog.hpp
|
||||
GUI/BonjourDialog.cpp
|
||||
GUI/BonjourDialog.hpp
|
||||
GUI/ButtonsDescription.cpp
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "SavePresetDialog.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "DesktopIntegrationDialog.hpp"
|
||||
#include "SendSystemInfoDialog.hpp"
|
||||
|
||||
#include "BitmapCache.hpp"
|
||||
#include "Notebook.hpp"
|
||||
@ -668,6 +669,9 @@ void GUI_App::post_init()
|
||||
if (app_config->get("show_hints") == "1" && ! is_gcode_viewer())
|
||||
plater_->get_notification_manager()->push_hint_notification(true);
|
||||
|
||||
// 'Send system info' dialog
|
||||
show_send_system_info_dialog_if_needed();
|
||||
|
||||
// The extra CallAfter() is needed because of Mac, where this is the only way
|
||||
// to popup a modal dialog on start without screwing combo boxes.
|
||||
// This is ugly but I honestly found no better way to do it.
|
||||
|
@ -27,7 +27,7 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// A safe wrapper around glGetString to report a "N/A" string in case glGetString returns nullptr.
|
||||
inline std::string gl_get_string_safe(GLenum param, const std::string& default_value)
|
||||
std::string gl_get_string_safe(GLenum param, const std::string& default_value)
|
||||
{
|
||||
const char* value = (const char*)::glGetString(param);
|
||||
return std::string((value != nullptr) ? value : default_value);
|
||||
|
@ -10,6 +10,7 @@ class wxGLContext;
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
class OpenGLManager
|
||||
{
|
||||
public:
|
||||
|
301
src/slic3r/GUI/SendSystemInfoDialog.cpp
Normal file
301
src/slic3r/GUI/SendSystemInfoDialog.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
#include "SendSystemInfoDialog.hpp"
|
||||
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/Platform.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "slic3r/Utils/Http.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// Declaration of a free function defined in OpenGLManager.cpp:
|
||||
std::string gl_get_string_safe(GLenum param, const std::string& default_value);
|
||||
|
||||
|
||||
// Read a string formatted as SLIC3R_VERSION (e.g. "2.4.0-alpha1") and get major and
|
||||
// minor versions and alpha/beta flags.
|
||||
static void extract_major_minor(std::string version,
|
||||
int& major, int& minor,
|
||||
bool* is_alpha = nullptr, bool* is_beta = nullptr)
|
||||
{
|
||||
if (is_alpha)
|
||||
*is_alpha = version.find("alpha") != std::string::npos;
|
||||
if (is_beta)
|
||||
*is_beta = version.find("beta") != std::string::npos;
|
||||
if (std::count(version.begin(), version.end(), '.') != 2)
|
||||
return;
|
||||
std::replace(version.begin(), version.end(), '.', ' ');
|
||||
std::istringstream ss{version};
|
||||
ss >> major >> minor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Last version where the info was sent / dialog dismissed is saved in appconfig.
|
||||
// Only show the dialog when this info is not found (e.g. fresh install) or when
|
||||
// current version is newer. Only major and minor versions are compared.
|
||||
static bool should_dialog_be_shown()
|
||||
{
|
||||
std::string last_sent_version = wxGetApp().app_config->get("system_info_sent_version");
|
||||
|
||||
int last_sent_major = 0;
|
||||
int last_sent_minor = 0;
|
||||
int current_major = 0;
|
||||
int current_minor = 0;
|
||||
bool alpha = false;
|
||||
bool beta = false;
|
||||
extract_major_minor(SLIC3R_VERSION, current_major, current_minor, &alpha, &beta);
|
||||
extract_major_minor(last_sent_version, last_sent_major, last_sent_minor);
|
||||
|
||||
|
||||
if (current_major == 0 // This should never happen.
|
||||
/*|| alpha
|
||||
|| beta*/)
|
||||
return false;
|
||||
|
||||
return ((current_major > last_sent_major)
|
||||
|| (current_major == last_sent_major && current_minor > last_sent_minor ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void send_info(const std::string& data)
|
||||
{
|
||||
std::cout << data << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// Following function saves current PrusaSlicer version into app config.
|
||||
// It will be later used to decide whether to open the dialog or not.
|
||||
static void save_version()
|
||||
{
|
||||
wxGetApp().app_config->set("system_info_sent_version", SLIC3R_VERSION);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Following function generates one string that will be shown in the preview
|
||||
// and later sent if confirmed by the user.
|
||||
static std::string generate_system_info_json()
|
||||
{
|
||||
// Calculate hash of datadir path so it is possible to identify duplicates.
|
||||
// The result is mod 10000 so most of the information is lost and it is
|
||||
// not possible to unhash the datadir (which usually contains username).
|
||||
// It is more than enough to help identify duplicate entries.
|
||||
size_t datadir_hash = std::hash<std::string>{}(std::string(wxGetUserId().ToUTF8().data())) % 10000;
|
||||
|
||||
// Get system language.
|
||||
std::string sys_language = "Unknown";
|
||||
const wxLanguage lang_system = wxLanguage(wxLocale::GetSystemLanguage());
|
||||
if (lang_system != wxLANGUAGE_UNKNOWN)
|
||||
sys_language = wxLocale::GetLanguageInfo(lang_system)->CanonicalName.ToUTF8().data();
|
||||
|
||||
// Build a property tree with all the information.
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
pt::ptree root;
|
||||
root.put("PrusaSlicerVersion", SLIC3R_VERSION);
|
||||
root.put("BuildID", SLIC3R_BUILD_ID);
|
||||
root.put("UsernameHash", datadir_hash);
|
||||
root.put("Platform", platform_to_string(platform()));
|
||||
root.put("PlatformFlavor", platform_flavor_to_string(platform_flavor()));
|
||||
root.put("SystemLanguage", sys_language);
|
||||
root.put("TranslationLanguage: ", wxGetApp().app_config->get("translation_language"));
|
||||
|
||||
pt::ptree hw_node;
|
||||
hw_node.put("ArchName", wxPlatformInfo::Get().GetArchName());
|
||||
hw_node.put("RAM_MB", size_t(Slic3r::total_physical_memory()/1000000));
|
||||
root.add_child("Hardware", hw_node);
|
||||
|
||||
pt::ptree opengl_node;
|
||||
opengl_node.put("Version", OpenGLManager::get_gl_info().get_version());
|
||||
opengl_node.put("GLSLVersion", OpenGLManager::get_gl_info().get_glsl_version());
|
||||
opengl_node.put("Vendor", OpenGLManager::get_gl_info().get_vendor());
|
||||
opengl_node.put("Renderer", OpenGLManager::get_gl_info().get_renderer());
|
||||
// Generate list of OpenGL extensions:
|
||||
std::string extensions_str = gl_get_string_safe(GL_EXTENSIONS, "");
|
||||
std::vector<std::string> extensions_list;
|
||||
boost::split(extensions_list, extensions_str, boost::is_any_of(" "), boost::token_compress_off);
|
||||
pt::ptree extensions_node;
|
||||
for (const std::string& s : extensions_list) {
|
||||
if (s.empty())
|
||||
continue;
|
||||
pt::ptree ext_node; // Create an unnamed node containing the value
|
||||
ext_node.put("", s);
|
||||
extensions_node.push_back(std::make_pair("", ext_node)); // Add this node to the list.
|
||||
}
|
||||
opengl_node.add_child("Extensions", extensions_node);
|
||||
root.add_child("OpenGL", opengl_node);
|
||||
|
||||
// Serialize the tree into JSON and return it.
|
||||
std::stringstream ss;
|
||||
pt::write_json(ss, root);
|
||||
return ss.str();
|
||||
|
||||
//std::cout << wxPlatformInfo::Get().GetOperatingSystemFamilyName() << std::endl; // Unix
|
||||
//std::cout << wxPlatformInfo::Get().GetOperatingSystemDescription() << std::endl; // Linux 4.15.0-142-generic x86_64
|
||||
// ? CPU, GPU, UNKNOWN, wxWidgets ???
|
||||
// tiskárny? budou už nainstalované?
|
||||
}
|
||||
|
||||
|
||||
|
||||
SendSystemInfoDialog::SendSystemInfoDialog(wxWindow* parent)
|
||||
: m_system_info_json{generate_system_info_json()},
|
||||
GUI::DPIDialog(parent, wxID_ANY, _L("Send system info"), wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
{
|
||||
int version_major = 0;
|
||||
int version_minor = 0;
|
||||
bool is_alpha = false;
|
||||
bool is_beta = false;
|
||||
extract_major_minor(SLIC3R_VERSION, version_major, version_minor, &is_alpha, &is_beta);
|
||||
std::string app_name = std::string(SLIC3R_APP_NAME) + " " + std::to_string(version_major)
|
||||
+ "." + std::to_string(version_minor) + " "
|
||||
+ (is_alpha ? "Alpha" : is_beta ? "Beta" : "");
|
||||
|
||||
const int em = GUI::wxGetApp().em_unit();
|
||||
m_min_width = MIN_WIDTH * em;
|
||||
m_min_height = MIN_HEIGHT * em;
|
||||
|
||||
|
||||
const wxFont& mono_font = GUI::wxGetApp().code_font();
|
||||
|
||||
auto *panel = new wxPanel(this);
|
||||
auto *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel->SetSizer(vsizer);
|
||||
|
||||
/*auto *topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
topsizer->Add(panel, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
|
||||
SetMinSize(wxSize(m_min_width, m_min_height));
|
||||
SetSizerAndFit(topsizer);
|
||||
*/
|
||||
std::string filename(__FILE__);
|
||||
size_t last_slash_idx = filename.find_last_of("/");
|
||||
if (last_slash_idx != std::string::npos)
|
||||
filename = filename.substr(last_slash_idx+1);
|
||||
auto* text = new wxStaticText(panel, wxID_ANY, wxEmptyString);
|
||||
text->SetLabelMarkup(
|
||||
GUI::format_wxstr(_L("This is the first time you are running %1%. We would like to "
|
||||
"ask you to send some of your system information to us. This will only "
|
||||
"happen once and we will not ask you to do this again (only after you "
|
||||
"upgrade to the next version)."), app_name )
|
||||
+ "\n\n"
|
||||
+ "<b>" + _L("Why is it needed") + "</b>"
|
||||
+ "\n"
|
||||
+ _L("If we know your hardware, operating system, etc., it will greatly help us "
|
||||
"in development, prioritization and possible deprecation of features that "
|
||||
"are no more needed (for example legacy OpenGL support). This will help "
|
||||
"us to focus our effort more efficiently and spend time on features that "
|
||||
"are needed the most.")
|
||||
+ "\n\n"
|
||||
+ "<b>" + _L("Is it safe?") + "</b>\n"
|
||||
+ GUI::format_wxstr(
|
||||
_L("We do not send any personal information nor anything that would allow us "
|
||||
"to identify you later. To detect duplicate entries, a number derived "
|
||||
"from your username is sent, but it cannot be used to recover the username. "
|
||||
"Apart from that, only general data about your OS, hardware and OpenGL "
|
||||
"installation are sent. PrusaSlicer is open source, if you want to "
|
||||
"inspect the code actually performing the communication, see %1%."),
|
||||
std::string("<i>") + filename + "</i>")
|
||||
+ "\n\n"
|
||||
+ "<b>" + _L("Verbatim data that will be sent:") + "</b>");
|
||||
vsizer->Add(text, 1, wxEXPAND);
|
||||
|
||||
|
||||
auto* txt_json = new wxTextCtrl(panel, wxID_ANY, m_system_info_json,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
|
||||
txt_json->SetFont(mono_font);
|
||||
txt_json->ShowPosition(0);
|
||||
vsizer->Add(txt_json, 0, wxEXPAND, SPACING);
|
||||
|
||||
auto* ask_later_button = new wxButton(panel, wxID_ANY, _L("Ask me next time"));
|
||||
auto* dont_send_button = new wxButton(panel, wxID_ANY, _L("Do not send anything"));
|
||||
auto* send_button = new wxButton(panel, wxID_ANY, _L("Send system info"));
|
||||
|
||||
auto* hsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
hsizer->Add(ask_later_button);
|
||||
hsizer->AddSpacer(em);
|
||||
hsizer->Add(dont_send_button);
|
||||
hsizer->AddSpacer(em);
|
||||
hsizer->Add(send_button);
|
||||
vsizer->Add(hsizer, 0, wxALIGN_CENTER_HORIZONTAL, 10);
|
||||
|
||||
const auto size = GetSize();
|
||||
SetSize(std::max(size.GetWidth(), m_min_width),
|
||||
std::max(size.GetHeight(), m_min_height));
|
||||
Layout();
|
||||
|
||||
send_button->Bind(wxEVT_BUTTON, [this](const wxEvent&)
|
||||
{
|
||||
send_info(m_system_info_json);
|
||||
save_version();
|
||||
EndModal(0);
|
||||
});
|
||||
dont_send_button->Bind(wxEVT_BUTTON, [this](const wxEvent&)
|
||||
{
|
||||
save_version();
|
||||
EndModal(0);
|
||||
});
|
||||
ask_later_button->Bind(wxEVT_BUTTON, [this](const wxEvent&) { EndModal(0); });
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SendSystemInfoDialog::on_dpi_changed(const wxRect&)
|
||||
{
|
||||
/*const int& em = em_unit();
|
||||
|
||||
msw_buttons_rescale(this, em, { p->btn_close->GetId(),
|
||||
p->btn_rescan->GetId(),
|
||||
p->btn_flash->GetId(),
|
||||
p->hex_picker->GetPickerCtrl()->GetId()
|
||||
});
|
||||
|
||||
p->min_width = MIN_WIDTH * em;
|
||||
p->min_height = MIN_HEIGHT * em;
|
||||
p->min_height_expanded = MIN_HEIGHT_EXPANDED * em;
|
||||
|
||||
const int min_height = p->spoiler->IsExpanded() ? p->min_height_expanded : p->min_height;
|
||||
SetMinSize(wxSize(p->min_width, min_height));
|
||||
Fit();
|
||||
|
||||
Refresh();*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void show_send_system_info_dialog_if_needed()
|
||||
{
|
||||
if (wxGetApp().is_gcode_viewer() || ! should_dialog_be_shown())
|
||||
return;
|
||||
|
||||
SendSystemInfoDialog dlg(wxGetApp().mainframe);
|
||||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
39
src/slic3r/GUI/SendSystemInfoDialog.hpp
Normal file
39
src/slic3r/GUI/SendSystemInfoDialog.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef slic3r_SendSystemInfoDialog_hpp_
|
||||
#define slic3r_SendSystemInfoDialog_hpp_
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class SendSystemInfoDialog : public DPIDialog
|
||||
{
|
||||
enum {
|
||||
DIALOG_MARGIN = 15,
|
||||
SPACING = 10,
|
||||
MIN_WIDTH = 60,
|
||||
MIN_HEIGHT = 40,
|
||||
MIN_HEIGHT_EXPANDED = 40,
|
||||
};
|
||||
|
||||
public:
|
||||
SendSystemInfoDialog(wxWindow* parent);
|
||||
|
||||
private:
|
||||
const std::string m_system_info_json;
|
||||
int m_min_width;
|
||||
int m_min_height;
|
||||
|
||||
void on_dpi_changed(const wxRect&) override;
|
||||
};
|
||||
|
||||
void show_send_system_info_dialog_if_needed();
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_SendSystemInfoDialog_hpp_
|
Loading…
Reference in New Issue
Block a user