OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::HintDatabase Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/HintNotification.hpp>

Collaboration diagram for Slic3r::GUI::HintDatabase:

Public Member Functions

 ~HintDatabase ()
 HintDatabase (HintDatabase const &)=delete
void operator= (HintDatabase const &)=delete
HintData * get_hint (HintDataNavigation nav)
size_t get_index ()
size_t get_count ()
void uninit ()
void reinit ()

Static Public Member Functions

static HintDatabase & get_instance ()

Private Member Functions

 HintDatabase ()
void init ()
void init_random_hint_id ()
void load_hints_from_file (const boost::filesystem::path &path)
bool is_used (const std::string &id)
void set_used (const std::string &id)
void clear_used ()
size_t get_next_hint_id ()
size_t get_prev_hint_id ()
size_t get_random_next ()

Private Attributes

size_t m_hint_id
bool m_initialized { false }
std::vector< HintData > m_loaded_hints
bool m_sorted_hints { false }
std::vector< std::string > m_used_ids
bool m_used_ids_loaded { false }

Detailed Description

Constructor & Destructor Documentation

◆ HintDatabase() [1/2]

Slic3r::GUI::HintDatabase::HintDatabase ( )
inlineprivate
52 : m_hint_id(0)
53 {}
size_t m_hint_id
Definition HintNotification.hpp:82

References m_hint_id.

Referenced by HintDatabase(), get_instance(), and operator=().

Here is the caller graph for this function:

◆ ~HintDatabase()

Slic3r::GUI::HintDatabase::~HintDatabase ( )
312{
313 if (m_initialized) {
315 }
316}
bool m_initialized
Definition HintNotification.hpp:83
std::vector< std::string > m_used_ids
Definition HintNotification.hpp:86
void write_used_binary(const std::vector< std::string > &ids)
Definition HintNotification.cpp:89

References m_initialized, and m_used_ids.

◆ HintDatabase() [2/2]

Slic3r::GUI::HintDatabase::HintDatabase ( HintDatabase const & )
delete

References HintDatabase().

Here is the call graph for this function:

Member Function Documentation

◆ clear_used()

void Slic3r::GUI::HintDatabase::clear_used ( )
private
616{
617 m_used_ids.clear();
618}

References m_used_ids.

Referenced by get_random_next().

Here is the caller graph for this function:

◆ get_count()

size_t Slic3r::GUI::HintDatabase::get_count ( )
inline
62 {
63 if (!m_initialized)
64 return 0;
65 return m_loaded_hints.size();
66 }
std::vector< HintData > m_loaded_hints
Definition HintNotification.hpp:84

References m_initialized, and m_loaded_hints.

Referenced by Slic3r::GUI::DailyTipsPanel::render_controller_buttons().

Here is the caller graph for this function:

◆ get_hint()

HintData * Slic3r::GUI::HintDatabase::get_hint ( HintDataNavigation nav)
506{
507 if (!m_initialized) {
508 init();
510 }
511 if (m_loaded_hints.empty())
512 {
513 BOOST_LOG_TRIVIAL(error) << "There were no hints loaded from hints.ini file.";
514 return nullptr;
515 }
516
517 try
518 {
519 if (nav == HintDataNavigation::Next)
521 if(nav == HintDataNavigation::Prev)
525 }
526 catch (const std::exception&)
527 {
528 return nullptr;
529 }
530
531 return &m_loaded_hints[m_hint_id];
532}
size_t get_prev_hint_id()
Definition HintNotification.cpp:539
void init_random_hint_id()
Definition HintNotification.cpp:340
size_t get_next_hint_id()
Definition HintNotification.cpp:534
void init()
Definition HintNotification.cpp:334
@ Next
Definition HintNotification.hpp:37
@ Prev
Definition HintNotification.hpp:36
@ Random
Definition HintNotification.hpp:38

References get_next_hint_id(), get_prev_hint_id(), init(), init_random_hint_id(), m_hint_id, m_initialized, m_loaded_hints, Slic3r::GUI::Next, Slic3r::GUI::Prev, and Slic3r::GUI::Random.

Referenced by Slic3r::GUI::NotificationManager::HintNotification::retrieve_data(), and Slic3r::GUI::DailyTipsPanel::retrieve_data_from_hint_database().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_index()

size_t Slic3r::GUI::HintDatabase::get_index ( )
inline
61{ return m_hint_id; }

References m_hint_id.

Referenced by Slic3r::GUI::DailyTipsPanel::render_controller_buttons().

Here is the caller graph for this function:

◆ get_instance()

HintDatabase & Slic3r::GUI::HintDatabase::get_instance ( )
inlinestatic
45 {
46 static HintDatabase instance; // Guaranteed to be destroyed.
47 // Instantiated on first use.
48 return instance;
49 }
HintDatabase()
Definition HintNotification.hpp:51

References HintDatabase().

Referenced by Slic3r::GUI::GUI_App::load_language(), Slic3r::GUI::DailyTipsPanel::render_controller_buttons(), Slic3r::GUI::NotificationManager::HintNotification::retrieve_data(), and Slic3r::GUI::DailyTipsPanel::retrieve_data_from_hint_database().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_next_hint_id()

size_t Slic3r::GUI::HintDatabase::get_next_hint_id ( )
private
535{
536 return m_hint_id < m_loaded_hints.size() - 1 ? m_hint_id + 1 : 0;
537}

References m_hint_id, and m_loaded_hints.

Referenced by get_hint().

Here is the caller graph for this function:

◆ get_prev_hint_id()

size_t Slic3r::GUI::HintDatabase::get_prev_hint_id ( )
private
540{
541 return m_hint_id > 0 ? m_hint_id - 1 : m_loaded_hints.size() - 1;
542}

References m_hint_id, and m_loaded_hints.

Referenced by get_hint().

Here is the caller graph for this function:

◆ get_random_next()

size_t Slic3r::GUI::HintDatabase::get_random_next ( )
private
545{
546 if (!m_sorted_hints)
547 {
548 auto compare_wieght = [](const HintData& a, const HintData& b) { return a.weight < b.weight; };
549 std::sort(m_loaded_hints.begin(), m_loaded_hints.end(), compare_wieght);
550 m_sorted_hints = true;
551 srand(time(NULL));
552 }
553 std::vector<size_t> candidates; // index in m_loaded_hints
554 // total weight
555 size_t total_weight = 0;
556 for (size_t i = 0; i < m_loaded_hints.size(); i++) {
557 if (!m_loaded_hints[i].was_displayed && tags_check(m_loaded_hints[i].disabled_tags, m_loaded_hints[i].enabled_tags)) {
558 candidates.emplace_back(i);
559 total_weight += m_loaded_hints[i].weight;
560 }
561 }
562 // all were shown
563 if (total_weight == 0) {
564 clear_used();
565 for (size_t i = 0; i < m_loaded_hints.size(); i++) {
566 m_loaded_hints[i].was_displayed = false;
567 if (tags_check(m_loaded_hints[i].disabled_tags, m_loaded_hints[i].enabled_tags)) {
568 candidates.emplace_back(i);
569 total_weight += m_loaded_hints[i].weight;
570 }
571 }
572 }
573 if (total_weight == 0) {
574 BOOST_LOG_TRIVIAL(error) << "Hint notification random number generator failed. No suitable hint was found.";
575 throw std::exception();
576 }
577 size_t random_number = rand() % total_weight + 1;
578 size_t current_weight = 0;
579 for (size_t i = 0; i < candidates.size(); i++) {
580 current_weight += m_loaded_hints[candidates[i]].weight;
581 if (random_number <= current_weight) {
582 set_used(m_loaded_hints[candidates[i]].id_string);
583 m_loaded_hints[candidates[i]].was_displayed = true;
584 return candidates[i];
585 }
586 }
587 BOOST_LOG_TRIVIAL(error) << "Hint notification random number generator failed.";
588 throw std::exception();
589}
bool m_sorted_hints
Definition HintNotification.hpp:85
void clear_used()
Definition HintNotification.cpp:615
void set_used(const std::string &id)
Definition HintNotification.cpp:607
bool tags_check(const std::string &disabled_tags, const std::string &enabled_tags)
Definition HintNotification.cpp:220

References clear_used(), m_loaded_hints, m_sorted_hints, set_used(), and Slic3r::GUI::HintData::weight.

Here is the call graph for this function:

◆ init()

void Slic3r::GUI::HintDatabase::init ( )
private
335{
336 load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini"));
337 m_initialized = true;
339}
void load_hints_from_file(const boost::filesystem::path &path)
Definition HintNotification.cpp:345
const std::string & resources_dir()
Definition utils.cpp:296

References init_random_hint_id(), load_hints_from_file(), m_initialized, and Slic3r::resources_dir().

Referenced by get_hint(), and reinit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_random_hint_id()

void Slic3r::GUI::HintDatabase::init_random_hint_id ( )
private
341{
342 srand(time(NULL));
343 m_hint_id = rand() % m_loaded_hints.size();
344}

References m_hint_id, and m_loaded_hints.

Referenced by get_hint(), and init().

Here is the caller graph for this function:

◆ is_used()

bool Slic3r::GUI::HintDatabase::is_used ( const std::string & id)
private
592{
593 // load used ids from file
594 if (!m_used_ids_loaded) {
596 m_used_ids_loaded = true;
597 }
598 // check if id is in used
599 for (const std::string& used_id : m_used_ids) {
600 if (used_id == id)
601 {
602 return true;
603 }
604 }
605 return false;
606}
bool m_used_ids_loaded
Definition HintNotification.hpp:87
void read_used_binary(std::vector< std::string > &ids)
Definition HintNotification.cpp:103

References m_used_ids, and m_used_ids_loaded.

Referenced by load_hints_from_file(), and set_used().

Here is the caller graph for this function:

◆ load_hints_from_file()

void Slic3r::GUI::HintDatabase::load_hints_from_file ( const boost::filesystem::path & path)
private
346{
347 namespace pt = boost::property_tree;
348 pt::ptree tree;
349 boost::nowide::ifstream ifs(path.string());
350 try {
351 pt::read_ini(ifs, tree);
352 }
353 catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
354 throw Slic3r::RuntimeError(format("Failed loading hints file \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
355 }
356
357 for (const auto& section : tree) {
358 if (boost::starts_with(section.first, "hint:")) {
359 // create std::map with tree data
360 std::map<std::string, std::string> dict;
361 for (const auto& data : section.second) {
362 dict.emplace(data.first, data.second.data());
363 }
364 // unique id string [hint:id] (trim "hint:")
365 std::string id_string = section.first.substr(5);
366 id_string = std::to_string(std::hash<std::string>{}(id_string));
367 // unescaping and translating all texts and saving all data common for all hint types
368 std::string fulltext;
369 std::string text1;
370 std::string hypertext_text;
371 std::string follow_text;
372 // tags
373 std::string disabled_tags;
374 std::string enabled_tags;
375 // optional link to documentation (accessed from button)
376 std::string documentation_link;
377 std::string img_url;
378 // randomized weighted order variables
379 size_t weight = 1;
380 bool was_displayed = is_used(id_string);
381 //unescape text1
382 unescape_string_cstyle(dict["text"], fulltext);
383 fulltext = _utf8(fulltext);
384#ifdef __APPLE__
385 boost::replace_all(fulltext, "Ctrl+", "?");
386#endif //__APPLE__
387 // replace <b> and </b> for imgui markers
388 std::string marker_s(1, ImGui::ColorMarkerStart);
389 std::string marker_e(1, ImGui::ColorMarkerEnd);
390 // start marker
391 size_t marker_pos = fulltext.find(BOLD_MARKER_START);
392 while (marker_pos != std::string::npos) {
393 fulltext.replace(marker_pos, 3, marker_s);
394 marker_pos = fulltext.find(BOLD_MARKER_START, marker_pos);
395 }
396 // end marker
397 marker_pos = fulltext.find(BOLD_MARKER_END);
398 while (marker_pos != std::string::npos) {
399 fulltext.replace(marker_pos, 4, marker_e);
400 marker_pos = fulltext.find(BOLD_MARKER_END, marker_pos);
401 }
402 // divide fulltext
403 size_t hypertext_start = fulltext.find(HYPERTEXT_MARKER_START);
404 if (hypertext_start != std::string::npos) {
405 //hypertext exists
406 fulltext.erase(hypertext_start, HYPERTEXT_MARKER_START.size());
407 if (fulltext.find(HYPERTEXT_MARKER_START) != std::string::npos) {
408 // This must not happen - only 1 hypertext allowed
409 BOOST_LOG_TRIVIAL(error) << "Hint notification with multiple hypertexts: " << _utf8(dict["text"]);
410 continue;
411 }
412 size_t hypertext_end = fulltext.find(HYPERTEXT_MARKER_END);
413 if (hypertext_end == std::string::npos) {
414 // hypertext was not correctly ended
415 BOOST_LOG_TRIVIAL(error) << "Hint notification without hypertext end marker: " << _utf8(dict["text"]);
416 continue;
417 }
418 fulltext.erase(hypertext_end, HYPERTEXT_MARKER_END.size());
419 if (fulltext.find(HYPERTEXT_MARKER_END) != std::string::npos) {
420 // This must not happen - only 1 hypertext end allowed
421 BOOST_LOG_TRIVIAL(error) << "Hint notification with multiple hypertext end markers: " << _utf8(dict["text"]);
422 continue;
423 }
424
425 text1 = fulltext.substr(0, hypertext_start);
426 hypertext_text = fulltext.substr(hypertext_start, hypertext_end - hypertext_start);
427 follow_text = fulltext.substr(hypertext_end);
428 }
429 else {
430 text1 = fulltext;
431 }
432
433 if (dict.find("disabled_tags") != dict.end()) {
434 disabled_tags = dict["disabled_tags"];
435 }
436 if (dict.find("enabled_tags") != dict.end()) {
437 enabled_tags = dict["enabled_tags"];
438 }
439 if (dict.find("documentation_link") != dict.end()) {
440 documentation_link = dict["documentation_link"];
441 }
442 if (dict.find("image") != dict.end()) {
443 img_url = dict["image"];
444 }
445
446 if (dict.find("weight") != dict.end()) {
447 weight = (size_t)std::max(1, std::atoi(dict["weight"].c_str()));
448 }
449
450 // create HintData
451 if (dict.find("hypertext_type") != dict.end()) {
452 //link to internet
453 if (dict["hypertext_type"] == "link") {
454 std::string hypertext_link = dict["hypertext_link"];
455 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [hypertext_link]() { launch_browser_if_allowed(hypertext_link); } };
456 m_loaded_hints.emplace_back(hint_data);
457 // highlight settings
458 }
459 else if (dict["hypertext_type"] == "settings") {
460 std::string opt = dict["hypertext_settings_opt"];
461 Preset::Type type = static_cast<Preset::Type>(std::atoi(dict["hypertext_settings_type"].c_str()));
462 std::wstring category = boost::nowide::widen(dict["hypertext_settings_category"]);
463 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } };
464 m_loaded_hints.emplace_back(hint_data);
465 // open preferences
466 }
467 else if (dict["hypertext_type"] == "preferences") {
468 std::string item = dict["hypertext_preferences_item"];
469 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [item]() { wxGetApp().open_preferences(PreferencesTab::Control, item); } };
470 m_loaded_hints.emplace_back(hint_data);
471 }
472 else if (dict["hypertext_type"] == "plater") {
473 std::string item = dict["hypertext_plater_item"];
474 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_toolbar_item(item); } };
475 m_loaded_hints.emplace_back(hint_data);
476 }
477 else if (dict["hypertext_type"] == "gizmo") {
478 std::string item = dict["hypertext_gizmo_item"];
479 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_gizmo(item); } };
480 m_loaded_hints.emplace_back(hint_data);
481 }
482 else if (dict["hypertext_type"] == "gallery") {
483 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, []() {
484 // Deselect all objects, otherwise gallery wont show.
485 wxGetApp().plater()->canvas3D()->deselect_all();
486 //wxGetApp().obj_list()->load_shape_object_from_gallery(); }
487 } };
488 m_loaded_hints.emplace_back(hint_data);
489 }
490 else if (dict["hypertext_type"] == "menubar") {
491 wxString menu(_("&" + dict["hypertext_menubar_menu_name"]));
492 wxString item(_(dict["hypertext_menubar_item_name"]));
493 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } };
494 m_loaded_hints.emplace_back(hint_data);
495 }
496 }
497 else {
498 // plain text without hypertext
499 HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url };
500 m_loaded_hints.emplace_back(hint_data);
501 }
502 }
503 }
504}
#define _(s)
Definition 3mf.cpp:306
bool is_used(const std::string &id)
Definition HintNotification.cpp:591
Type
Definition Preset.hpp:244
void launch_browser_if_allowed(const std::string &url)
Definition HintNotification.cpp:306
const std::string HYPERTEXT_MARKER_START
Definition HintNotification.cpp:77
@ Control
Definition Preferences.hpp:40
const std::string HYPERTEXT_MARKER_END
Definition HintNotification.cpp:78
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
const std::string BOLD_MARKER_END
Definition HintNotification.cpp:76
const std::string BOLD_MARKER_START
Definition HintNotification.cpp:75
bool unescape_string_cstyle(const std::string &str, std::string &str_out)
Definition Config.cpp:150
#define _utf8(s)
Definition I18N.hpp:10

References _, _utf8, Slic3r::GUI::BOLD_MARKER_END, Slic3r::GUI::BOLD_MARKER_START, Slic3r::GUI::Control, Slic3r::GUI::format(), Slic3r::GUI::HYPERTEXT_MARKER_END, Slic3r::GUI::HYPERTEXT_MARKER_START, is_used(), m_loaded_hints, and Slic3r::unescape_string_cstyle().

Referenced by init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

void Slic3r::GUI::HintDatabase::operator= ( HintDatabase const & )
delete

References HintDatabase().

Here is the call graph for this function:

◆ reinit()

void Slic3r::GUI::HintDatabase::reinit ( )
329{
330 if (m_initialized)
331 uninit();
332 init();
333}
void uninit()
Definition HintNotification.cpp:317

References init(), m_initialized, and uninit().

Here is the call graph for this function:

◆ set_used()

void Slic3r::GUI::HintDatabase::set_used ( const std::string & id)
private
608{
609 // check needed?
610 if (!is_used(id))
611 {
612 m_used_ids.emplace_back(id);
613 }
614}

References is_used(), and m_used_ids.

Referenced by get_random_next().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ uninit()

void Slic3r::GUI::HintDatabase::uninit ( )
318{
319 if (m_initialized) {
321 }
322 m_initialized = false;
323 m_loaded_hints.clear();
324 m_sorted_hints = false;
325 m_used_ids.clear();
326 m_used_ids_loaded = false;
327}

References m_initialized, m_loaded_hints, m_sorted_hints, m_used_ids, and m_used_ids_loaded.

Referenced by reinit().

Here is the caller graph for this function:

Member Data Documentation

◆ m_hint_id

size_t Slic3r::GUI::HintDatabase::m_hint_id
private

◆ m_initialized

bool Slic3r::GUI::HintDatabase::m_initialized { false }
private
83{ false };

Referenced by ~HintDatabase(), get_count(), get_hint(), init(), reinit(), and uninit().

◆ m_loaded_hints

std::vector<HintData> Slic3r::GUI::HintDatabase::m_loaded_hints
private

◆ m_sorted_hints

bool Slic3r::GUI::HintDatabase::m_sorted_hints { false }
private
85{ false };

Referenced by get_random_next(), and uninit().

◆ m_used_ids

std::vector<std::string> Slic3r::GUI::HintDatabase::m_used_ids
private

◆ m_used_ids_loaded

bool Slic3r::GUI::HintDatabase::m_used_ids_loaded { false }
private
87{ false };

Referenced by is_used(), and uninit().


The documentation for this class was generated from the following files: