diff --git a/src/lay/lay/laySaltDownloadManager.cc b/src/lay/lay/laySaltDownloadManager.cc index cf7d9ee0c..4fe9c7b2b 100644 --- a/src/lay/lay/laySaltDownloadManager.cc +++ b/src/lay/lay/laySaltDownloadManager.cc @@ -23,6 +23,7 @@ #include "laySaltDownloadManager.h" #include "laySaltManagerDialog.h" #include "laySalt.h" +#include "tlProgress.h" #include "tlFileUtils.h" #include "tlWebDAV.h" @@ -77,16 +78,59 @@ ConfirmationDialog::separator () m_file.separator (); } +void +ConfirmationDialog::mark_fetching (const std::string &name) +{ + std::map::const_iterator i = m_items_by_name.find (name); + if (i != m_items_by_name.end ()) { + list->scrollToItem (i->second); + for (int c = 0; c < list->columnCount (); ++c) { + i->second->setData (c, Qt::BackgroundColorRole, QColor (224, 244, 244)); + i->second->setData (c, Qt::TextColorRole, Qt::blue); + } + i->second->setData (1, Qt::DisplayRole, tr ("FETCHING")); + } +} + void ConfirmationDialog::mark_error (const std::string &name) { set_icon_for_name (name, QIcon (QString::fromUtf8 (":/error_16.png"))); + + std::map::const_iterator i = m_items_by_name.find (name); + if (i != m_items_by_name.end ()) { + list->scrollToItem (i->second); + for (int c = 0; c < list->columnCount (); ++c) { + i->second->setData (c, Qt::BackgroundColorRole, QColor (255, 224, 244)); + i->second->setData (c, Qt::TextColorRole, Qt::black); + } + i->second->setData (1, Qt::DisplayRole, tr ("ERROR")); + } } void ConfirmationDialog::mark_success (const std::string &name) { set_icon_for_name (name, QIcon (QString::fromUtf8 (":/marked_16.png"))); + + std::map::const_iterator i = m_items_by_name.find (name); + if (i != m_items_by_name.end ()) { + list->scrollToItem (i->second); + for (int c = 0; c < list->columnCount (); ++c) { + i->second->setData (c, Qt::BackgroundColorRole, QColor (160, 255, 160)); + i->second->setData (c, Qt::TextColorRole, Qt::black); + } + i->second->setData (1, Qt::DisplayRole, tr ("INSTALLED")); + } +} + +void +ConfirmationDialog::set_progress (const std::string &name, double progress) +{ + std::map::const_iterator i = m_items_by_name.find (name); + if (i != m_items_by_name.end ()) { + i->second->setData (1, Qt::DisplayRole, tl::to_qstring (tl::sprintf ("%.1f%%", progress))); + } } void @@ -353,6 +397,43 @@ SaltDownloadManager::make_confirmation_dialog (QWidget *parent, const lay::Salt return dialog; } +namespace +{ + class DownloadProgressAdaptor + : public tl::ProgressAdaptor + { + public: + DownloadProgressAdaptor (lay::ConfirmationDialog *dialog, const std::string &name) + : mp_dialog (dialog), m_name (name) + { + mp_dialog->mark_fetching (m_name); + } + + virtual void register_object (tl::Progress * /*progress*/) { } + virtual void unregister_object (tl::Progress * /*progress*/) { } + virtual void yield (tl::Progress * /*progress*/) { } + + virtual void trigger (tl::Progress *progress) + { + mp_dialog->set_progress (m_name, progress->value ()); + } + + void error () + { + mp_dialog->mark_error (m_name); + } + + void success () + { + mp_dialog->mark_success (m_name); + } + + private: + lay::ConfirmationDialog *mp_dialog; + std::string m_name; + }; +} + bool SaltDownloadManager::execute (lay::SaltManagerDialog *parent, lay::Salt &salt) { @@ -393,12 +474,16 @@ SaltDownloadManager::execute (lay::SaltManagerDialog *parent, lay::Salt &salt) } int status = 1; - if (! salt.create_grain (p->grain, target)) { - dialog->mark_error (p->name); - result = false; - status = 0; - } else { - dialog->mark_success (p->name); + + { + DownloadProgressAdaptor pa (dialog.get (), p->name); + if (! salt.create_grain (p->grain, target)) { + pa.error (); + result = false; + status = 0; + } else { + pa.success (); + } } try { diff --git a/src/lay/lay/laySaltDownloadManager.h b/src/lay/lay/laySaltDownloadManager.h index 47ed7cb73..749347c56 100644 --- a/src/lay/lay/laySaltDownloadManager.h +++ b/src/lay/lay/laySaltDownloadManager.h @@ -57,8 +57,10 @@ public: void separator (); void finish (); + void mark_fetching (const std::string &name); void mark_error (const std::string &name); void mark_success (const std::string &name); + void set_progress (const std::string &name, double progress); private slots: void confirm_pressed () { m_confirmed = true; } diff --git a/src/lay/lay/layTechnologyController.cc b/src/lay/lay/layTechnologyController.cc index b01d2c2f9..a1816fbfb 100644 --- a/src/lay/lay/layTechnologyController.cc +++ b/src/lay/lay/layTechnologyController.cc @@ -52,6 +52,7 @@ std::string tech_string_from_name (const std::string &tn) TechnologyController::TechnologyController () : PluginDeclaration (), mp_editor (0), mp_mw (0), mp_active_technology (0) { + m_configure_enabled = true; m_current_technology_updated = false; m_technologies_configured = false; } @@ -204,7 +205,14 @@ TechnologyController::technologies_changed () // update the configuration to reflect the persisted technologies lay::PluginRoot *pr = mp_mw; if (pr) { - pr->config_set (cfg_technologies, lay::Technologies::instance ()->to_xml ()); + m_configure_enabled = false; + try { + pr->config_set (cfg_technologies, lay::Technologies::instance ()->to_xml ()); + m_configure_enabled = true; + } catch (...) { + m_configure_enabled = true; + throw; + } } update_menu (); @@ -220,7 +228,11 @@ TechnologyController::technology_changed (lay::Technology *) bool TechnologyController::configure (const std::string &name, const std::string &value) { - if (name == cfg_initial_technology) { + if (! m_configure_enabled) { + + // ignore configuration request (prevent recursion + + } else if (name == cfg_initial_technology) { if (value != m_current_technology) { m_current_technology = value; diff --git a/src/lay/lay/layTechnologyController.h b/src/lay/lay/layTechnologyController.h index 6bf80cfa3..bcb375a40 100644 --- a/src/lay/lay/layTechnologyController.h +++ b/src/lay/lay/layTechnologyController.h @@ -127,6 +127,7 @@ private slots: private: tl::stable_vector m_tech_actions; std::string m_current_technology; + bool m_configure_enabled; bool m_current_technology_updated; bool m_technologies_configured; lay::TechSetupDialog *mp_editor; diff --git a/src/tl/tl/tlProgress.cc b/src/tl/tl/tlProgress.cc index 5876af82b..f1212ee09 100644 --- a/src/tl/tl/tlProgress.cc +++ b/src/tl/tl/tlProgress.cc @@ -38,6 +38,7 @@ namespace tl // ProgressAdaptor implementation ProgressAdaptor::ProgressAdaptor () + : mp_prev (0) { tl::Progress::register_adaptor (this); } @@ -47,6 +48,18 @@ ProgressAdaptor::~ProgressAdaptor () tl::Progress::register_adaptor (0); } +void +ProgressAdaptor::prev (ProgressAdaptor *pa) +{ + mp_prev = pa; +} + +ProgressAdaptor * +ProgressAdaptor::prev () +{ + return mp_prev; +} + // --------------------------------------------------------------------------------------------- // Progress implementation @@ -79,7 +92,15 @@ Progress::~Progress () void Progress::register_adaptor (ProgressAdaptor *pa) { - tl_assert (adaptor () == 0 || pa == 0); + ProgressAdaptor *current_pa = adaptor (); + if (current_pa) { + if (! pa) { + pa = current_pa->prev (); + } else { + pa->prev (current_pa); + } + } + s_thread_data.setLocalData (new (ProgressAdaptor *) (pa)); } diff --git a/src/tl/tl/tlProgress.h b/src/tl/tl/tlProgress.h index 67b6c8197..aa79e4e86 100644 --- a/src/tl/tl/tlProgress.h +++ b/src/tl/tl/tlProgress.h @@ -37,6 +37,14 @@ namespace tl class Progress; +/** + * @brief The receivers for progress reports + * + * The progress adaptors form a thread-local stack of receivers. New receivers can override the + * previous receivers. It is important that receivers are always created in a nested fashion inside + * a single thread. + */ + class TL_PUBLIC ProgressAdaptor { public: @@ -47,6 +55,12 @@ public: virtual void unregister_object (Progress *progress) = 0; virtual void trigger (Progress *progress) = 0; virtual void yield (Progress *progress) = 0; + + void prev (ProgressAdaptor *pa); + ProgressAdaptor *prev (); + +private: + ProgressAdaptor *mp_prev; }; /**