Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::AppUpdater::priv Struct Reference
+ Collaboration diagram for Slic3r::AppUpdater::priv:

Public Member Functions

 priv ()
 
bool http_get_file (const std::string &url, size_t size_limit, std::function< bool(Http::Progress)> progress_fn, std::function< bool(std::string, std::string &error_message)> completefn, std::string &error_message) const
 
boost::filesystem::path download_file (const DownloadAppData &data) const
 
bool run_downloaded_file (boost::filesystem::path path)
 
void version_check (const std::string &version_check_url)
 
void parse_version_string (const std::string &body)
 
bool get_download_ongoing () const
 
DownloadAppData get_app_data ()
 
void set_app_data (DownloadAppData data)
 
bool get_triggered_by_user () const
 

Public Attributes

std::thread m_thread
 
std::atomic_bool m_cancel
 
std::mutex m_data_mutex
 
std::atomic_bool m_download_ongoing { false }
 
boost::filesystem::path m_default_dest_folder
 
DownloadAppData m_online_version_data
 
std::atomic_bool m_triggered_by_user {false}
 

Detailed Description

Constructor & Destructor Documentation

◆ priv()

Slic3r::AppUpdater::priv::priv ( )
151 :
152 m_cancel (false)
153#ifdef __linux__
154 , m_default_dest_folder (boost::filesystem::path("/tmp"))
155#else
156 , m_default_dest_folder (boost::filesystem::path(data_dir()) / "cache")
157#endif //_WIN32
158{
159 boost::filesystem::path downloads_path = boost::filesystem::path(get_downloads_path());
160 if (!downloads_path.empty()) {
161 m_default_dest_folder = std::move(downloads_path);
162 }
163 BOOST_LOG_TRIVIAL(trace) << "App updater default download path: " << m_default_dest_folder; //lm:Is this an error? // dk: changed to trace
164
165}
wxString get_downloads_path()
Definition ConfigWizard.cpp:1390
const std::string & data_dir()
Definition utils.cpp:206
std::atomic_bool m_cancel
Definition AppUpdater.cpp:134
boost::filesystem::path m_default_dest_folder
Definition AppUpdater.cpp:140

References m_default_dest_folder.

Member Function Documentation

◆ download_file()

boost::filesystem::path Slic3r::AppUpdater::priv::download_file ( const DownloadAppData data) const
198{
199 boost::filesystem::path dest_path;
200 size_t last_gui_progress = 0;
201 size_t expected_size = data.size;
202 dest_path = data.target_path;
203 assert(!dest_path.empty());
204 if (dest_path.empty())
205 {
206 std::string line1 = GUI::format(_u8L("Internal download error for url %1%:"), data.url);
207 std::string line2 = _u8L("Destination path is empty.");
208 std::string message = GUI::format("%1%\n%2%", line1, line2);
209 BOOST_LOG_TRIVIAL(error) << message;
210 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
211 evt->SetString(message);
212 GUI::wxGetApp().QueueEvent(evt);
213 return boost::filesystem::path();
214 }
215
216 boost::filesystem::path tmp_path = dest_path;
217 tmp_path += format(".%1%%2%", std::to_string(GUI::GLCanvas3D::timestamp_now()), ".download");
218 FILE* file;
219 wxString temp_path_wstring(tmp_path.wstring());
220 file = fopen(temp_path_wstring.c_str(), "wb");
221 assert(file != NULL);
222 if (file == NULL) {
223 std::string line1 = GUI::format(_u8L("Download from %1% couldn't start:"), data.url);
224 std::string line2 = GUI::format(_u8L("Can't create file at %1%"), tmp_path.string());
225 std::string message = GUI::format("%1%\n%2%", line1, line2);
226 BOOST_LOG_TRIVIAL(error) << message;
227 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
228 evt->SetString(message);
229 GUI::wxGetApp().QueueEvent(evt);
230 return boost::filesystem::path();
231 }
232
233 std::string error_message;
234 bool res = http_get_file(data.url, 130 * 1024 * 1024 //2.4.0 windows installer is 65MB //lm:I don't know, but larger. The binaries will grow. // dk: changed to 130, to have 100% more space. We should put this information into version file.
235 // on_progress
236 , [&last_gui_progress, expected_size](Http::Progress progress) {
237 // size check
238 if (progress.dltotal > 0 && progress.dltotal > expected_size) {
239 std::string message = GUI::format("Downloading new %1% has failed. The file has incorrect file size. Aborting download.\nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);
240 BOOST_LOG_TRIVIAL(error) << message;
241 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
242 evt->SetString(message);
243 GUI::wxGetApp().QueueEvent(evt);
244 return false;
245 } else if (progress.dltotal > 0 && progress.dltotal < expected_size) {
246 // This is possible error, but we cannot know until the download is finished. Somehow the total size can grow during the download.
247 BOOST_LOG_TRIVIAL(info) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);
248 }
249 // progress event
250 size_t gui_progress = progress.dltotal > 0 ? 100 * progress.dlnow / progress.dltotal : 0;
251 BOOST_LOG_TRIVIAL(debug) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal;
252 if (last_gui_progress < gui_progress && (last_gui_progress != 0 || gui_progress != 100)) {
253 last_gui_progress = gui_progress;
254 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS);
255 evt->SetString(GUI::from_u8(std::to_string(gui_progress)));
256 GUI::wxGetApp().QueueEvent(evt);
257 }
258 return true;
259 }
260 // on_complete
261 , [&file, dest_path, tmp_path, expected_size](std::string body, std::string& error_message){
262 // Size check. Does always 1 char == 1 byte?
263 size_t body_size = body.size();
264 if (body_size != expected_size) {
265 error_message = GUI::format(_u8L("Downloaded file has wrong size. Expected size: %1% Downloaded size: %2%"), expected_size, body_size);
266 return false;
267 }
268 if (file == NULL) {
269 error_message = GUI::format(_u8L("Can't create file at %1%"), tmp_path.string());
270 return false;
271 }
272 try
273 {
274 fwrite(body.c_str(), 1, body.size(), file);
275 fclose(file);
276 boost::filesystem::rename(tmp_path, dest_path);
277 }
278 catch (const std::exception& e)
279 {
280 error_message = GUI::format(_u8L("Failed to write to file or to move %1% to %2%:\n%3%"), tmp_path, dest_path, e.what());
281 return false;
282 }
283 return true;
284 }
285 , error_message
286 );
287 if (!res)
288 {
289 if (m_cancel) {
290 BOOST_LOG_TRIVIAL(info) << error_message;
291 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); // FAILED with empty msg only closes progress notification
292 GUI::wxGetApp().QueueEvent(evt);
293 } else {
294 std::string message = (error_message.empty()
295 ? std::string()
296 : GUI::format(_u8L("Downloading new %1% has failed:\n%2%"), SLIC3R_APP_NAME, error_message));
297 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
298 if (!message.empty()) {
299 BOOST_LOG_TRIVIAL(error) << message;
300 evt->SetString(message);
301 }
302 GUI::wxGetApp().QueueEvent(evt);
303 }
304 return boost::filesystem::path();
305 }
306
307 return dest_path;
308}
#define _u8L(s)
macro used to mark string used at localization, return same string
Definition SLAPrint.cpp:29
static int64_t timestamp_now()
Definition GLCanvas3D.hpp:967
if(!(yy_init))
Definition lexer.c:1190
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:56
wxString from_u8(const std::string &str)
Definition GUI.cpp:437
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:44
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:195
bool http_get_file(const std::string &url, size_t size_limit, std::function< bool(Http::Progress)> progress_fn, std::function< bool(std::string, std::string &error_message)> completefn, std::string &error_message) const
Definition AppUpdater.cpp:167
static char error[256]
Definition tga.cpp:50

References _u8L, Slic3r::Http::Progress::dlnow, Slic3r::Http::Progress::dltotal, error, Slic3r::format(), Slic3r::GUI::format(), Slic3r::GUI::from_u8(), if(), and Slic3r::GUI::GLCanvas3D::timestamp_now().

+ Here is the call graph for this function:

◆ get_app_data()

DownloadAppData Slic3r::AppUpdater::priv::get_app_data ( )
535{
536 const std::lock_guard<std::mutex> lock(m_data_mutex);
537 DownloadAppData ret_val(m_online_version_data);
538 return ret_val;
539}
std::mutex m_data_mutex
Definition AppUpdater.cpp:135
DownloadAppData m_online_version_data
Definition AppUpdater.cpp:142

◆ get_download_ongoing()

bool Slic3r::AppUpdater::priv::get_download_ongoing ( ) const
inline
138{ return m_download_ongoing; }
std::atomic_bool m_download_ongoing
Definition AppUpdater.cpp:137

References m_download_ongoing.

◆ get_triggered_by_user()

bool Slic3r::AppUpdater::priv::get_triggered_by_user ( ) const
inline
148{ return m_triggered_by_user; }
std::atomic_bool m_triggered_by_user
Definition AppUpdater.cpp:147

References m_triggered_by_user.

◆ http_get_file()

bool Slic3r::AppUpdater::priv::http_get_file ( const std::string &  url,
size_t  size_limit,
std::function< bool(Http::Progress)>  progress_fn,
std::function< bool(std::string, std::string &error_message)>  completefn,
std::string &  error_message 
) const
168{
169 bool res = false;
170 Http::get(url)
171 .size_limit(size_limit)
172 .on_progress([&, progress_fn](Http::Progress progress, bool& cancel) {
173 // progress function returns true as success (to continue)
174 cancel = (m_cancel ? true : !progress_fn(std::move(progress)));
175 if (cancel) {
176 // Lets keep error_message empty here - if there is need to show error dialog, the message will be probably shown by whatever caused the cancel.
177 //error_message = GUI::format(_u8L("Error getting: `%1%`: Download was canceled."), url);
178 BOOST_LOG_TRIVIAL(debug) << "AppUpdater::priv::http_get_file message: "<< error_message;
179 }
180 })
181 .on_error([&](std::string body, std::string error, unsigned http_status) {
182 error_message = GUI::format("Error getting: `%1%`: HTTP %2%, %3%",
183 url,
184 http_status,
185 error);
186 BOOST_LOG_TRIVIAL(error) << error_message;
187 })
188 .on_complete([&](std::string body, unsigned /* http_status */) {
189 assert(complete_fn != nullptr);
190 res = complete_fn(body, error_message);
191 })
192 .perform_sync();
193
194 return res;
195}
void cancel()
Definition AppUpdater.cpp:607
Http & size_limit(size_t sizeLimit)
Definition Http.cpp:441
static Http get(std::string url)
Definition Http.cpp:607
Http & on_progress(ProgressFn fn)
Definition Http.cpp:571

References Slic3r::AppUpdater::cancel(), error, Slic3r::GUI::format(), Slic3r::Http::get(), Slic3r::Http::on_progress(), and Slic3r::Http::size_limit().

+ Here is the call graph for this function:

◆ parse_version_string()

void Slic3r::AppUpdater::priv::parse_version_string ( const std::string &  body)
347{
348 size_t start = body.find('[');
349 if (start == std::string::npos) {
350#if 0
351 BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Starting old parsing.";
352 parse_version_string_old(body);
353 return;
354#endif // 0
355 BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Checking for application update has failed.";
356 // Lets send event with current version, this way if user triggered this check, it will notify him about no new version online.
357 std::string version = Semver().to_string();
358 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
359 evt->SetString(GUI::from_u8(version));
360 GUI::wxGetApp().QueueEvent(evt);
361 return;
362 }
363 std::string tree_string = body.substr(start);
364 boost::property_tree::ptree tree;
365 std::stringstream ss(tree_string);
366 try {
367 boost::property_tree::read_ini(ss, tree);
368 } catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
369 //throw Slic3r::RuntimeError(format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string).c_str());
370 BOOST_LOG_TRIVIAL(error) << format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string);
371 return;
372 }
373
374 DownloadAppData new_data;
375
376 for (const auto& section : tree) {
377 std::string section_name = section.first;
378
379 // online release version info
380 if (section_name ==
381#ifdef _WIN32
382 "release:win64"
383#elif __APPLE__
384 "release:osx"
385#else
386 "release:linux"
387#endif
388//lm:Related to the ifdefs. We should also support BSD, which behaves similar to Linux in most cases.
389// Unless you have a reason not to, I would consider doing _WIN32, elif __APPLE__, else ... Not just here.
390// dk: so its ok now or we need to specify BSD?
391 ) {
392 for (const auto& data : section.second) {
393 if (data.first == "url") {
394 new_data.url = data.second.data();
395 new_data.target_path = m_default_dest_folder / AppUpdater::get_filename_from_url(new_data.url);
396 BOOST_LOG_TRIVIAL(info) << format("parsing version string: url: %1%", new_data.url);
397 } else if (data.first == "size"){
398 new_data.size = std::stoi(data.second.data());
399 BOOST_LOG_TRIVIAL(info) << format("parsing version string: expected size: %1%", new_data.size);
400 }
401 }
402 }
403
404 // released versions - to be send to UI layer
405 if (section_name == "common") {
406 std::vector<std::string> prerelease_versions;
407 for (const auto& data : section.second) {
408 // release version - save and send to UI layer
409 if (data.first == "release") {
410 std::string version = data.second.data();
411 boost::optional<Semver> release_version = Semver::parse(version);
412 if (!release_version) {
413 BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from version file: Not a correct semver: `%1%`", version);
414 return;
415 }
416 new_data.version = release_version;
417 // Send after all data is read
418 /*
419 BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
420 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
421 evt->SetString(GUI::from_u8(version));
422 GUI::wxGetApp().QueueEvent(evt);
423 */
424 // prerelease versions - write down to be sorted and send to UI layer
425 } else if (data.first == "alpha") {
426 prerelease_versions.emplace_back(data.second.data());
427 } else if (data.first == "beta") {
428 prerelease_versions.emplace_back(data.second.data());
429 } else if (data.first == "rc") {
430 prerelease_versions.emplace_back(data.second.data());
431 }
432 }
433 // find recent version that is newer than last full release.
434 boost::optional<Semver> recent_version;
435 std::string version_string;
436 for (const std::string& ver_string : prerelease_versions) {
437 boost::optional<Semver> ver = Semver::parse(ver_string);
438 if (ver && *new_data.version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) {
439 recent_version = ver;
440 version_string = ver_string;
441 }
442 }
443 // send prerelease version to UI layer
444 if (recent_version) {
445 BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version_string);
446 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE);
447 evt->SetString(GUI::from_u8(version_string));
448 GUI::wxGetApp().QueueEvent(evt);
449 }
450 }
451 }
452 assert(!new_data.url.empty());
453 assert(new_data.version);
454 // save
455 set_app_data(new_data);
456 // send
457 std::string version = new_data.version.get().to_string();
458 BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
459 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
460 evt->SetString(GUI::from_u8(version));
461 GUI::wxGetApp().QueueEvent(evt);
462}
static std::string get_filename_from_url(const std::string &url)
Definition AppUpdater.cpp:622
static boost::optional< Semver > parse(const std::string &str)
Definition Semver.hpp:58
char * version
Definition main.c:59
void set_app_data(DownloadAppData data)
Definition AppUpdater.cpp:541

References error, Slic3r::format(), Slic3r::GUI::from_u8(), Slic3r::AppUpdater::get_filename_from_url(), Slic3r::Semver::parse(), Slic3r::AppUpdater::set_app_data(), Slic3r::DownloadAppData::size, Slic3r::DownloadAppData::target_path, Slic3r::Semver::to_string(), Slic3r::DownloadAppData::url, version, and Slic3r::DownloadAppData::version.

+ Here is the call graph for this function:

◆ run_downloaded_file()

bool Slic3r::AppUpdater::priv::run_downloaded_file ( boost::filesystem::path  path)
311{
312 assert(!path.empty());
313 return run_file(path);
314}
bool run_file(const boost::filesystem::path &path)
Definition AppUpdater.cpp:83

◆ set_app_data()

void Slic3r::AppUpdater::priv::set_app_data ( DownloadAppData  data)
542{
543 const std::lock_guard<std::mutex> lock(m_data_mutex);
545}

◆ version_check()

void Slic3r::AppUpdater::priv::version_check ( const std::string &  version_check_url)
317{
318 assert(!version_check_url.empty());
319 std::string error_message;
320 bool res = http_get_file(version_check_url, 1024
321 // on_progress
322 , [](Http::Progress progress) { return true; }
323 // on_complete
324 , [&](std::string body, std::string& error_message) {
325 boost::trim(body);
327 return true;
328 }
329 , error_message
330 );
331 //lm:In case the internet is not available, it will report no updates if run by user.
332 // We might save a flag that we don't know or try to run the version_check again, reporting
333 // the failure.
334 // dk: changed to download version every time. Dialog will show if m_triggered_by_user.
335 if (!res) {
336 std::string message = GUI::format("Downloading %1% version file has failed:\n%2%", SLIC3R_APP_NAME, error_message);
337 BOOST_LOG_TRIVIAL(error) << message;
339 wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
340 evt->SetString(message);
341 GUI::wxGetApp().QueueEvent(evt);
342 }
343 }
344}
void parse_version_string(const std::string &body)
Definition AppUpdater.cpp:346

References error, and Slic3r::GUI::format().

+ Here is the call graph for this function:

Member Data Documentation

◆ m_cancel

std::atomic_bool Slic3r::AppUpdater::priv::m_cancel

◆ m_data_mutex

std::mutex Slic3r::AppUpdater::priv::m_data_mutex

◆ m_default_dest_folder

boost::filesystem::path Slic3r::AppUpdater::priv::m_default_dest_folder

Referenced by priv().

◆ m_download_ongoing

std::atomic_bool Slic3r::AppUpdater::priv::m_download_ongoing { false }

Referenced by get_download_ongoing().

◆ m_online_version_data

DownloadAppData Slic3r::AppUpdater::priv::m_online_version_data

◆ m_thread

std::thread Slic3r::AppUpdater::priv::m_thread

◆ m_triggered_by_user

std::atomic_bool Slic3r::AppUpdater::priv::m_triggered_by_user {false}

Referenced by get_triggered_by_user().


The documentation for this struct was generated from the following file: