mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-01-31 07:58:43 +03:00
PRUSA 2.7.0
This commit is contained in:
304
src/slic3r/GUI/WifiConfigDialog.cpp
Normal file
304
src/slic3r/GUI/WifiConfigDialog.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
#include "WifiConfigDialog.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "format.hpp"
|
||||
#include "RemovableDriveManager.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
const char* WIFI_CONFIGFILE_NAME = "prusa_printer_settings.ini";
|
||||
|
||||
WifiConfigDialog::WifiConfigDialog(wxWindow* parent, std::string& file_path, RemovableDriveManager* removable_manager, const wxString& preffered_drive)
|
||||
// TRN: This is the dialog title.
|
||||
: DPIDialog(parent, wxID_ANY, _L("Wi-Fi Configuration File Generator"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, m_wifi_scanner(new WifiScanner())
|
||||
, out_file_path(file_path)
|
||||
, m_removable_manager(removable_manager)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(this);
|
||||
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel->SetSizer(vsizer);
|
||||
|
||||
// TRN Wifi config dialog explanation line 1.
|
||||
wxStaticText* explain_label1 = new wxStaticText(panel, wxID_ANY, _L("Generate a file to be loaded by a Prusa printer to configure its Wi-Fi connection."));
|
||||
// TRN Wifi config dialog explanation line 2.
|
||||
wxStaticText* explain_label2 = new wxStaticText(panel, wxID_ANY, GUI::format_wxstr(_L("Write this file on the USB flash drive. Its name will be %1%."), WIFI_CONFIGFILE_NAME));
|
||||
// TRN Wifi config dialog explanation line 3.
|
||||
wxStaticText* explain_label3 = new wxStaticText(panel, wxID_ANY, _L("Your Prusa printer should load this file automatically."));
|
||||
// TRN Wifi config dialog explanation line 4.
|
||||
wxStaticText* explain_label4 = new wxStaticText(panel, wxID_ANY, _L("Note: This file will contain the SSID and password in plain text."));
|
||||
|
||||
auto* ssid_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
// TRN SSID of WiFi network. It is a standard abbreviation which should probably not change in most languages.
|
||||
wxStaticText* ssid_label = new wxStaticText(panel, wxID_ANY, GUI::format_wxstr("%1%:", _L("SSID")));
|
||||
m_ssid_combo = new ::ComboBox(panel, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, DD_NO_CHECK_ICON);
|
||||
#if __APPLE__
|
||||
m_ssid_combo->SetToolTip(_L("On some versions of MacOS, this only loads SSID of connected network."));
|
||||
#endif // __APPLE__
|
||||
rescan_networks(false);
|
||||
m_ssid_button_id = NewControlId();
|
||||
// TRN Text of button to rescan visible networks in Wifi Config dialog.
|
||||
wxButton* ssid_button = new wxButton(panel, m_ssid_button_id, _(L("Rescan")));
|
||||
ssid_sizer->Add(m_ssid_combo, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
|
||||
ssid_sizer->Add(ssid_button, 0);
|
||||
|
||||
auto* pass_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
// TRN Password of WiFi network.
|
||||
wxStaticText* password_label = new wxStaticText(panel, wxID_ANY, GUI::format_wxstr("%1%:", _L("Password")));
|
||||
m_pass_textctrl = new ::TextInput(panel, "", "", "", wxDefaultPosition, wxDefaultSize);
|
||||
#if __APPLE__
|
||||
pass_sizer->Add(m_pass_textctrl, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
|
||||
m_pass_button_id = NewControlId();
|
||||
// TRN Text of button to retrieve password from keychain in Wifi Config dialog. Only on Mac.
|
||||
wxButton* pass_button = new wxButton(panel, m_pass_button_id, _(L("Retrieve")));
|
||||
pass_sizer->Add(pass_button, 0);
|
||||
pass_button->Bind(wxEVT_BUTTON, &WifiConfigDialog::on_retrieve_password, this);
|
||||
#else
|
||||
pass_sizer->Add(m_pass_textctrl, 1, wxALIGN_CENTER_VERTICAL, 10);
|
||||
#endif // __APPLE__
|
||||
// show password if current ssid was selected already
|
||||
fill_password();
|
||||
|
||||
auto* drive_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
// TRN description of Combo Box with path to USB drive.
|
||||
wxStaticText* drive_label = new wxStaticText(panel, wxID_ANY, GUI::format_wxstr("%1%:", _L("Drive")));
|
||||
m_drive_combo = new ::ComboBox(panel, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, DD_NO_CHECK_ICON);
|
||||
rescan_drives(preffered_drive);
|
||||
m_drive_button_id = NewControlId();
|
||||
// TRN Text of button to rescan connect usb drives in Wifi Config dialog.
|
||||
wxButton* drive_button = new wxButton(panel, m_drive_button_id, _(L("Rescan")));
|
||||
drive_sizer->Add(m_drive_combo, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);
|
||||
drive_sizer->Add(drive_button, 0);
|
||||
|
||||
// TRN Text of button to write config file in Wifi Config dialog.
|
||||
wxButton* ok_button = new wxButton(panel, wxID_OK, _L("Write"));
|
||||
wxButton* cancel_button = new wxButton(panel, wxID_CANCEL);
|
||||
|
||||
auto* grid = new wxFlexGridSizer(2, 15, 15);
|
||||
grid->AddGrowableCol(1);
|
||||
|
||||
grid->Add(ssid_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->Add(ssid_sizer, 0, wxEXPAND);
|
||||
|
||||
grid->Add(password_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->Add(pass_sizer, 0, wxEXPAND);
|
||||
|
||||
grid->Add(drive_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->Add(drive_sizer, 0, wxEXPAND);
|
||||
|
||||
vsizer->Add(explain_label1, 0, wxALIGN_CENTER_VERTICAL);
|
||||
vsizer->Add(explain_label2, 0, wxALIGN_CENTER_VERTICAL);
|
||||
vsizer->Add(explain_label3, 0, wxALIGN_CENTER_VERTICAL);
|
||||
vsizer->Add(explain_label4, 0, wxALIGN_CENTER_VERTICAL);
|
||||
vsizer->Add(grid, 0, wxEXPAND | wxTOP | wxBOTTOM, 15);
|
||||
|
||||
wxBoxSizer* buttons_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
buttons_sizer->Add(ok_button, 1, wxLEFT);
|
||||
buttons_sizer->AddStretchSpacer();
|
||||
buttons_sizer->Add(cancel_button, 1, wxRIGHT);
|
||||
|
||||
vsizer->Add(buttons_sizer, 0, wxEXPAND);
|
||||
|
||||
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
topsizer->Add(panel, 1, wxEXPAND | wxALL, 15);
|
||||
SetSizerAndFit(topsizer);
|
||||
|
||||
ok_button->Bind(wxEVT_BUTTON, &WifiConfigDialog::on_ok, this);
|
||||
m_ssid_combo->Bind(wxEVT_TEXT, &WifiConfigDialog::on_combo, this);
|
||||
drive_button->Bind(wxEVT_BUTTON, &WifiConfigDialog::on_rescan_drives, this);
|
||||
ssid_button->Bind(wxEVT_BUTTON, &WifiConfigDialog::on_rescan_networks, this);
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
WifiConfigDialog::~WifiConfigDialog()
|
||||
{
|
||||
if (m_wifi_scanner)
|
||||
delete m_wifi_scanner;
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_combo(wxCommandEvent& e)
|
||||
{
|
||||
fill_password();
|
||||
}
|
||||
|
||||
void WifiConfigDialog::fill_password()
|
||||
{
|
||||
assert(m_ssid_combo && m_pass_textctrl && m_wifi_scanner);
|
||||
if (auto it = m_wifi_scanner->get_map().find(m_ssid_combo->GetValue()); it != m_wifi_scanner->get_map().end())
|
||||
m_pass_textctrl->SetValue(boost::nowide::widen(it->second));
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_retrieve_password(wxCommandEvent& e)
|
||||
{
|
||||
if (m_ssid_combo->GetValue().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string psk = m_wifi_scanner->get_psk(boost::nowide::narrow(m_ssid_combo->GetValue()));
|
||||
if (psk.empty()) {
|
||||
// TRN Alert message when retrieving password for wifi from keychain. Probably will display only on Apple so keychain is MacOS term.
|
||||
wxString msg = _L("No password in the keychain for given SSID.");
|
||||
show_info(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
m_pass_textctrl->SetValue(boost::nowide::widen(psk));
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_rescan_drives(wxCommandEvent& e)
|
||||
{
|
||||
rescan_drives({});
|
||||
}
|
||||
|
||||
void WifiConfigDialog::rescan_drives(const wxString& preffered_drive)
|
||||
{
|
||||
assert(m_drive_combo && m_removable_manager);
|
||||
m_drive_combo->Clear();
|
||||
std::vector<DriveData> ddata = m_removable_manager->get_drive_list();
|
||||
for (const auto& data : ddata) {
|
||||
wxString item = boost::nowide::widen(data.path);
|
||||
m_drive_combo->Append(item);
|
||||
if (preffered_drive == item)
|
||||
m_ssid_combo->Select(m_ssid_combo->GetCount() - 1);
|
||||
}
|
||||
if (m_drive_combo->GetSelection() == -1 && m_drive_combo->GetCount() > 0) {
|
||||
m_drive_combo->Select(0);
|
||||
}
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_rescan_networks(wxCommandEvent& e)
|
||||
{
|
||||
rescan_networks(true);
|
||||
}
|
||||
|
||||
void WifiConfigDialog::rescan_networks(bool select)
|
||||
{
|
||||
assert(m_ssid_combo && m_wifi_scanner);
|
||||
m_wifi_scanner->scan();
|
||||
std::string current = m_wifi_scanner->get_current_ssid();
|
||||
const auto& map = m_wifi_scanner->get_map();
|
||||
m_ssid_combo->Clear();
|
||||
for (const auto pair : map) {
|
||||
m_ssid_combo->Append(pair.first);
|
||||
// select ssid of current network (if connected)
|
||||
if (current == pair.first)
|
||||
m_ssid_combo->Select(m_ssid_combo->GetCount() - 1);
|
||||
}
|
||||
if (m_ssid_combo->GetSelection() == -1 && m_ssid_combo->GetCount() > 0)
|
||||
m_ssid_combo->Select(0);
|
||||
if (select && m_ssid_combo->GetSelection() != -1)
|
||||
fill_password();
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_ok(wxCommandEvent& e)
|
||||
{
|
||||
assert(m_ssid_combo && m_pass_textctrl);
|
||||
if (m_ssid_combo->GetValue().empty()) {
|
||||
// TRN Alert message when writing WiFi configuration file to usb drive.
|
||||
wxString msg = _L("SSID field is empty.");
|
||||
show_info(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string selected_path = boost::nowide::narrow(m_drive_combo->GetValue());
|
||||
|
||||
if (selected_path.empty()) {
|
||||
// TRN Alert message when writing WiFi configuration file to usb drive.
|
||||
wxString msg = _L("Drive field is empty.");
|
||||
show_info(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
boost::filesystem::path file_path = boost::filesystem::path(selected_path) / WIFI_CONFIGFILE_NAME;
|
||||
|
||||
bool path_on_removable_media = m_removable_manager->set_and_verify_last_save_path(file_path.string());
|
||||
if (!path_on_removable_media) {
|
||||
// TRN Alert message when writing WiFi configuration file to usb drive.
|
||||
wxString msg = _L("Selected path is not on removable media.");
|
||||
show_info(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (boost::filesystem::exists(file_path)) {
|
||||
// TRN placeholder 1 is path to file
|
||||
wxString msg_text = GUI::format_wxstr(_L("%1% already exists. Do you want to rewrite it?\n(Other items than Wi-Fi credentials will stay unchanged)"), file_path.string());
|
||||
WarningDialog dialog(m_parent, msg_text, _L("Warning"), wxYES | wxNO);
|
||||
if (dialog.ShowModal() == wxID_NO) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string data;
|
||||
namespace pt = boost::property_tree;
|
||||
pt::ptree tree;
|
||||
// File already exist and we only need to add data to it rather than rewrite it.
|
||||
if (boost::filesystem::exists(file_path)) {
|
||||
|
||||
boost::nowide::ifstream ifs(file_path.string());
|
||||
try {
|
||||
pt::read_ini(ifs, tree);
|
||||
}
|
||||
catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
|
||||
throw Slic3r::RuntimeError(format("Failed loading ini file \"%1%\"\nError: \"%2%\" at line %3%", file_path, err.message(), err.line()).c_str());
|
||||
}
|
||||
|
||||
if (auto sub = tree.get_optional<std::string>("wifi"); sub) {
|
||||
tree.erase("wifi");
|
||||
}
|
||||
}
|
||||
|
||||
pt::ptree subtree;
|
||||
subtree.put("ssid", m_ssid_combo->GetValue().utf8_string());
|
||||
subtree.put("psk", m_pass_textctrl->GetValue().utf8_string());
|
||||
tree.add_child("wifi", subtree);
|
||||
|
||||
data.clear();
|
||||
// manually write ini string (so there is extra line between sections)
|
||||
for (const auto& section : tree) {
|
||||
data += "[" + section.first + "]" + "\n";
|
||||
for (const auto& entry : section.second) {
|
||||
data += entry.first + " = " + entry.second.get_value<std::string>() + "\n";
|
||||
}
|
||||
data += "\n";
|
||||
}
|
||||
|
||||
m_used_path = boost::nowide::widen(file_path.string());
|
||||
FILE* file;
|
||||
file = fopen(file_path.string().c_str(), "w");
|
||||
if (file == NULL) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to write to file " << file_path;
|
||||
// TODO show error
|
||||
show_error(nullptr, _L("Failed to open file for writing."));
|
||||
return;
|
||||
}
|
||||
fwrite(data.c_str(), 1, data.size(), file);
|
||||
fclose(file);
|
||||
out_file_path = file_path.string();
|
||||
this->EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
void WifiConfigDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
|
||||
const int em = em_unit();
|
||||
msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL, m_ssid_button_id, m_pass_button_id, m_drive_button_id });
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
}}// Slicer::GUI
|
||||
Reference in New Issue
Block a user