| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | #include "MultiSettings.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdexcept>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QObject>
 | 
					
						
							|  |  |  | #include <QSettings>
 | 
					
						
							|  |  |  | #include <QString>
 | 
					
						
							|  |  |  | #include <QStringList>
 | 
					
						
							|  |  |  | #include <QDir>
 | 
					
						
							| 
									
										
										
										
											2016-04-26 20:06:36 +00:00
										 |  |  | #include <QFont>
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | #include <QApplication>
 | 
					
						
							|  |  |  | #include <QStandardPaths>
 | 
					
						
							|  |  |  | #include <QMainWindow>
 | 
					
						
							|  |  |  | #include <QMenu>
 | 
					
						
							|  |  |  | #include <QAction>
 | 
					
						
							|  |  |  | #include <QActionGroup>
 | 
					
						
							|  |  |  | #include <QDialog>
 | 
					
						
							|  |  |  | #include <QLineEdit>
 | 
					
						
							|  |  |  | #include <QRegularExpression>
 | 
					
						
							|  |  |  | #include <QRegularExpressionValidator>
 | 
					
						
							|  |  |  | #include <QFormLayout>
 | 
					
						
							|  |  |  | #include <QVBoxLayout>
 | 
					
						
							|  |  |  | #include <QDialogButtonBox>
 | 
					
						
							|  |  |  | #include <QPushButton>
 | 
					
						
							|  |  |  | #include <QComboBox>
 | 
					
						
							|  |  |  | #include <QLabel>
 | 
					
						
							|  |  |  | #include <QList>
 | 
					
						
							|  |  |  | #include <QMetaObject>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | #include "SettingsGroup.hpp"
 | 
					
						
							| 
									
										
										
										
											2016-04-26 20:06:36 +00:00
										 |  |  | #include "qt_helpers.hpp"
 | 
					
						
							| 
									
										
										
										
											2016-07-03 20:31:19 +00:00
										 |  |  | #include "SettingsGroup.hpp"
 | 
					
						
							|  |  |  | #include "MessageBox.hpp"
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | #include "pimpl_impl.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char const * default_string = QT_TRANSLATE_NOOP ("MultiSettings", "Default"); | 
					
						
							|  |  |  |   char const * multi_settings_root_group = "MultiSettings"; | 
					
						
							|  |  |  |   char const * multi_settings_current_group_key = "CurrentMultiSettingsConfiguration"; | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   char const * multi_settings_current_name_key = "CurrentName"; | 
					
						
							|  |  |  |   char const * multi_settings_place_holder_key = "MultiSettingsPlaceHolder"; | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // calculate a useable and unique settings file path
 | 
					
						
							|  |  |  |   QString settings_path () | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     auto config_directory = QStandardPaths::writableLocation (QStandardPaths::ConfigLocation); | 
					
						
							|  |  |  |     QDir config_path {config_directory}; // will be "." if config_directory is empty
 | 
					
						
							|  |  |  |     if (!config_path.mkpath (".")) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         throw std::runtime_error {"Cannot find a usable configuration path \"" + config_path.path ().toStdString () + '"'}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     return config_path.absoluteFilePath (QApplication::applicationName () + ".ini"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // Dialog to get a valid new configuration name
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   class NameDialog final | 
					
						
							|  |  |  |     : public QDialog | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     explicit NameDialog (QString const& current_name, | 
					
						
							|  |  |  |                          QStringList const& current_names, | 
					
						
							|  |  |  |                          QWidget * parent = nullptr) | 
					
						
							|  |  |  |       : QDialog {parent} | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       setWindowTitle (tr ("New Configuration Name")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto form_layout = new QFormLayout (); | 
					
						
							|  |  |  |       form_layout->addRow (tr ("Old name:"), &old_name_label_); | 
					
						
							|  |  |  |       old_name_label_.setText (current_name); | 
					
						
							|  |  |  |       form_layout->addRow (tr ("&New name:"), &name_line_edit_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto main_layout = new QVBoxLayout (this); | 
					
						
							|  |  |  |       main_layout->addLayout (form_layout); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel}; | 
					
						
							|  |  |  |       button_box->button (QDialogButtonBox::Ok)->setEnabled (false); | 
					
						
							|  |  |  |       main_layout->addWidget (button_box); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto * name_validator = new QRegularExpressionValidator {QRegularExpression {R"([^/\\]+)"}, this}; | 
					
						
							|  |  |  |       name_line_edit_.setValidator (name_validator); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       connect (&name_line_edit_, &QLineEdit::textChanged, [current_names, button_box] (QString const& name) { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |           bool valid {!current_names.contains (name.trimmed ())}; | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |           button_box->button (QDialogButtonBox::Ok)->setEnabled (valid); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       connect (button_box, &QDialogButtonBox::accepted, this, &QDialog::accept); | 
					
						
							|  |  |  |       connect (button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString new_name () const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return name_line_edit_.text ().trimmed (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							|  |  |  |     QLabel old_name_label_; | 
					
						
							|  |  |  |     QLineEdit name_line_edit_; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // Dialog to get a valid new existing name
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   class ExistingNameDialog final | 
					
						
							|  |  |  |     : public QDialog | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     explicit ExistingNameDialog (QStringList const& current_names, QWidget * parent = nullptr) | 
					
						
							|  |  |  |       : QDialog {parent} | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       setWindowTitle (tr ("Configuration to Clone From")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       name_combo_box_.addItems (current_names); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto form_layout = new QFormLayout (); | 
					
						
							|  |  |  |       form_layout->addRow (tr ("&Source Configuration Name:"), &name_combo_box_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto main_layout = new QVBoxLayout (this); | 
					
						
							|  |  |  |       main_layout->addLayout (form_layout); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel}; | 
					
						
							|  |  |  |       main_layout->addWidget (button_box); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       connect (button_box, &QDialogButtonBox::accepted, this, &QDialog::accept); | 
					
						
							|  |  |  |       connect (button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString name () const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return name_combo_box_.currentText (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							|  |  |  |     QComboBox name_combo_box_; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MultiSettings::impl final | 
					
						
							|  |  |  |   : public QObject | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Q_OBJECT | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |   explicit impl (MultiSettings const * parent); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   bool reposition (); | 
					
						
							|  |  |  |   void create_menu_actions (QMainWindow * main_window, QMenu * menu); | 
					
						
							|  |  |  |   bool exit (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   QSettings settings_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   using Dictionary = QMap<QString, QVariant>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create a configuration maintenance sub menu
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   QMenu * create_sub_menu (QMainWindow * main_window, | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |                            QMenu * parent, | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |                            QString const& menu_title, | 
					
						
							|  |  |  |                            QActionGroup * = nullptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // extract all settings from the current QSettings group
 | 
					
						
							|  |  |  |   Dictionary get_settings () const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // write the settings values from the dictionary to the current group
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   void load_from (Dictionary const&, bool add_placeholder = true); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // switch to this configuration
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void select_configuration (QMainWindow *, QMenu const *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // clone this configuration
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void clone_configuration (QMainWindow * main_window, QMenu *, QMenu const *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // update this configuration from another
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void clone_into_configuration (QMainWindow *, QMenu const *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // reset configuration to default values
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void reset_configuration (QMainWindow *, QMenu const *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // change configuration name
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void rename_configuration (QMainWindow *, QMenu *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // remove a configuration
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   void delete_configuration (QMainWindow *, QMenu *); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |   MultiSettings const * parent_;  // required for emitting signals
 | 
					
						
							|  |  |  |   bool name_change_emit_pending_; // delayed until menu built
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 20:06:36 +00:00
										 |  |  |   QFont original_font_; | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   QString current_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // action to take on restart
 | 
					
						
							|  |  |  |   enum class RepositionType {unchanged, replace, save_and_replace} reposition_type_; | 
					
						
							|  |  |  |   Dictionary new_settings_; | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   bool exit_flag_;              // false means loop around with new
 | 
					
						
							|  |  |  |                                 // configuration
 | 
					
						
							|  |  |  |   QActionGroup * configurations_group_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MultiSettings.moc"
 | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  | #include "moc_MultiSettings.cpp"
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | MultiSettings::MultiSettings () | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |   : m_ {this} | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiSettings::~MultiSettings () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QSettings * MultiSettings::settings () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return &m_->settings_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  | QVariant MultiSettings::common_value (QString const& key, QVariant const& default_value) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QVariant value; | 
					
						
							| 
									
										
										
										
											2016-09-11 12:27:35 +00:00
										 |  |  |   QSettings * mutable_settings {const_cast<QSettings *> (&m_->settings_)}; | 
					
						
							|  |  |  |   auto const& current_group = mutable_settings->group (); | 
					
						
							|  |  |  |   if (current_group.size ()) mutable_settings->endGroup (); | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-09-11 12:27:35 +00:00
										 |  |  |     SettingsGroup alternatives {mutable_settings, multi_settings_root_group}; | 
					
						
							|  |  |  |     value = mutable_settings->value (key, default_value); | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-11 12:27:35 +00:00
										 |  |  |   if (current_group.size ()) mutable_settings->beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MultiSettings::set_common_value (QString const& key, QVariant const& value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   auto const& current_group = m_->settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) m_->settings_.endGroup (); | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     SettingsGroup alternatives {&m_->settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |     m_->settings_.setValue (key, value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (current_group.size ()) m_->settings_.beginGroup (current_group); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MultiSettings::remove_common_value (QString const& key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!key.size ()) return;     // we don't allow global delete as it
 | 
					
						
							|  |  |  |                                 // would break this classes data model
 | 
					
						
							|  |  |  |   auto const& current_group = m_->settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) m_->settings_.endGroup (); | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     SettingsGroup alternatives {&m_->settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |     m_->settings_.remove (key); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (current_group.size ()) m_->settings_.beginGroup (current_group); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | void MultiSettings::create_menu_actions (QMainWindow * main_window, QMenu * menu) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_->create_menu_actions (main_window, menu); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool MultiSettings::exit () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_->exit (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  | MultiSettings::impl::impl (MultiSettings const * parent) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   : settings_ {settings_path (), QSettings::IniFormat} | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |   , parent_ {parent} | 
					
						
							|  |  |  |   , name_change_emit_pending_ {true} | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   , reposition_type_ {RepositionType::unchanged} | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   , exit_flag_ {true} | 
					
						
							|  |  |  |   , configurations_group_ {new QActionGroup {this}} | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!settings_.isWritable ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       throw std::runtime_error {QString {"Cannot access \"%1\" for writing"} | 
					
						
							|  |  |  |         .arg (settings_.fileName ()).toStdString ()}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // deal with transient, now defunct, settings key
 | 
					
						
							|  |  |  |   if (settings_.contains (multi_settings_current_group_key)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       current_ = settings_.value (multi_settings_current_group_key).toString (); | 
					
						
							|  |  |  |       settings_.remove (multi_settings_current_group_key); | 
					
						
							|  |  |  |       if (current_.size ()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               SettingsGroup source_group {&settings_, current_}; | 
					
						
							|  |  |  |               new_settings_ = get_settings (); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             settings_.setValue (multi_settings_current_name_key, tr (default_string)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           reposition_type_ = RepositionType::save_and_replace; | 
					
						
							|  |  |  |           reposition (); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |           settings_.setValue (multi_settings_current_name_key, tr (default_string)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // bootstrap
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |     current_ = settings_.value (multi_settings_current_name_key).toString (); | 
					
						
							|  |  |  |     if (!current_.size ()) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         current_ = tr (default_string); | 
					
						
							|  |  |  |         settings_.setValue (multi_settings_current_name_key, current_); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   settings_.sync (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | // do actions that can only be done once all the windows are closed
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | bool MultiSettings::impl::reposition () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.endGroup (); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   switch (reposition_type_) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |     case RepositionType::save_and_replace: | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         // save the current settings with the other alternatives
 | 
					
						
							|  |  |  |         Dictionary saved_settings {get_settings ()}; | 
					
						
							|  |  |  |         SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |         // get the current configuration name
 | 
					
						
							|  |  |  |         auto previous_group_name = settings_.value (multi_settings_current_name_key, tr (default_string)).toString (); | 
					
						
							|  |  |  |         SettingsGroup save_group {&settings_, previous_group_name}; | 
					
						
							|  |  |  |         load_from (saved_settings); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // fall through
 | 
					
						
							|  |  |  |     case RepositionType::replace: | 
					
						
							|  |  |  |       // and purge current settings
 | 
					
						
							|  |  |  |       for (auto const& key: settings_.allKeys ()) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |           if (!key.contains (multi_settings_root_group)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               settings_.remove (key); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       // insert the new settings
 | 
					
						
							|  |  |  |       load_from (new_settings_, false); | 
					
						
							| 
									
										
										
										
											2016-04-26 20:06:36 +00:00
										 |  |  |       if (!new_settings_.size ()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           // if we are clearing the current settings then we must
 | 
					
						
							|  |  |  |           // reset the application font and the font in the
 | 
					
						
							|  |  |  |           // application style sheet, this is necessary since the
 | 
					
						
							|  |  |  |           // application instance is not recreated
 | 
					
						
							|  |  |  |           qApp->setFont (original_font_); | 
					
						
							|  |  |  |           qApp->setStyleSheet (qApp->styleSheet () + "* {" + font_as_stylesheet (original_font_) + '}'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       // now we have set up the new current we can safely purge it
 | 
					
						
							|  |  |  |       // from the alternatives
 | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           SettingsGroup purge_group {&settings_, current_}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |           settings_.remove (QString {});  // purge entire group
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         // switch to the specified configuration name
 | 
					
						
							|  |  |  |         settings_.setValue (multi_settings_current_name_key, current_); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       settings_.sync (); | 
					
						
							|  |  |  |       // fall through
 | 
					
						
							|  |  |  |     case RepositionType::unchanged: | 
					
						
							|  |  |  |       new_settings_.clear (); | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   reposition_type_ = RepositionType::unchanged; // reset
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   bool exit {exit_flag_}; | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   exit_flag_ = true;           // reset exit flag so normal exit works
 | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   return exit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // populate a pop up menu with the configurations sub-menus for
 | 
					
						
							|  |  |  | // maintenance including select, clone, clone from, delete, rename
 | 
					
						
							|  |  |  | // and, reset
 | 
					
						
							|  |  |  | void MultiSettings::impl::create_menu_actions (QMainWindow * main_window, QMenu * menu) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.endGroup (); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |   // get the current configuration name
 | 
					
						
							|  |  |  |   auto current_configuration_name = settings_.value (multi_settings_current_name_key, tr (default_string)).toString (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   // add the default configuration sub menu
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   QMenu * default_menu = create_sub_menu (main_window, menu, current_configuration_name, configurations_group_); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   // and set as the current configuration
 | 
					
						
							|  |  |  |   default_menu->menuAction ()->setChecked (true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   QStringList available_configurations; | 
					
						
							|  |  |  |   // get the existing alternatives
 | 
					
						
							|  |  |  |   available_configurations = settings_.childGroups (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // add all the other configurations
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   for (auto const& configuration_name: available_configurations) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       create_sub_menu (main_window, menu, configuration_name, configurations_group_); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |   if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (name_change_emit_pending_) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-11-27 01:34:35 +00:00
										 |  |  |       Q_EMIT parent_->configurationNameChanged (current_.replace (QRegularExpression {R"(&([^&]))"}, R"(\1)").replace ("&&", "&")); | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |       name_change_emit_pending_ = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // call this at the end of the main program loop to determine if the
 | 
					
						
							|  |  |  | // main window really wants to quit or to run again with a new configuration
 | 
					
						
							|  |  |  | bool MultiSettings::impl::exit () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-28 17:15:04 +00:00
										 |  |  |   // ensure that configuration name changed signal gets fired on restart
 | 
					
						
							|  |  |  |   name_change_emit_pending_ = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   // do any configuration swap required and return exit flag
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   return reposition (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | QMenu * MultiSettings::impl::create_sub_menu (QMainWindow * main_window, | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |                                               QMenu * parent_menu, | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |                                               QString const& menu_title, | 
					
						
							|  |  |  |                                               QActionGroup * action_group) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |   auto sub_menu = parent_menu->addMenu (menu_title); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   if (action_group) action_group->addAction (sub_menu->menuAction ()); | 
					
						
							|  |  |  |   sub_menu->menuAction ()->setCheckable (true); | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // populate sub-menu actions before showing
 | 
					
						
							|  |  |  |   connect (sub_menu, &QMenu::aboutToShow, [this, main_window, parent_menu, sub_menu] () { | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |       // depopulate before populating and showing because on Mac OS X
 | 
					
						
							|  |  |  |       // there is an issue with depopulating in QMenu::aboutToHide()
 | 
					
						
							|  |  |  |       // with connections being disconnected before they are actioned
 | 
					
						
							|  |  |  |       while (!sub_menu->actions ().isEmpty ()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           sub_menu->removeAction (sub_menu->actions ().last ()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       bool is_current {sub_menu->menuAction ()->text () == current_}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       if (!is_current) | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           auto select_action = new QAction {tr ("&Switch To"), this}; | 
					
						
							|  |  |  |           sub_menu->addAction (select_action); | 
					
						
							|  |  |  |           connect (select_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { | 
					
						
							|  |  |  |               select_configuration (main_window, sub_menu); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           sub_menu->addSeparator (); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto clone_action = new QAction {tr ("&Clone"), this}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       sub_menu->addAction (clone_action); | 
					
						
							|  |  |  |       connect (clone_action, &QAction::triggered, [this, main_window, parent_menu, sub_menu] (bool) { | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |           clone_configuration (main_window, parent_menu, sub_menu); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |       if (current_group.size ()) settings_.endGroup (); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       if (settings_.childGroups ().size ()) | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           auto clone_into_action = new QAction {tr ("Clone &Into ..."), this}; | 
					
						
							|  |  |  |           sub_menu->addAction (clone_into_action); | 
					
						
							|  |  |  |           connect (clone_into_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { | 
					
						
							|  |  |  |               clone_into_configuration (main_window, sub_menu); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |       auto reset_action = new QAction {tr ("R&eset"), this}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       sub_menu->addAction (reset_action); | 
					
						
							|  |  |  |       connect (reset_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |           reset_configuration (main_window, sub_menu); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |       auto rename_action = new QAction {tr ("&Rename ..."), this}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       sub_menu->addAction (rename_action); | 
					
						
							|  |  |  |       connect (rename_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |           rename_configuration (main_window, sub_menu); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (!is_current) | 
					
						
							| 
									
										
										
										
											2016-10-29 19:26:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           auto delete_action = new QAction {tr ("&Delete"), this}; | 
					
						
							|  |  |  |           sub_menu->addAction (delete_action); | 
					
						
							|  |  |  |           connect (delete_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { | 
					
						
							|  |  |  |               delete_configuration (main_window, sub_menu); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |   return sub_menu; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | auto MultiSettings::impl::get_settings () const -> Dictionary | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Dictionary settings; | 
					
						
							|  |  |  |   for (auto const& key: settings_.allKeys ()) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-26 20:06:36 +00:00
										 |  |  |       // filter out multi settings group and empty settings
 | 
					
						
							|  |  |  |       // placeholder
 | 
					
						
							|  |  |  |       if (!key.contains (multi_settings_root_group) | 
					
						
							|  |  |  |           && !key.contains (multi_settings_place_holder_key)) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           settings[key] = settings_.value (key); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return settings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  | void MultiSettings::impl::load_from (Dictionary const& dictionary, bool add_placeholder) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   if (dictionary.size ()) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       for (Dictionary::const_iterator iter = dictionary.constBegin (); | 
					
						
							|  |  |  |            iter != dictionary.constEnd (); ++iter) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           settings_.setValue (iter.key (), iter.value ()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   else if (add_placeholder) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       // add a placeholder key to stop the alternative configuration
 | 
					
						
							|  |  |  |       // name from disappearing
 | 
					
						
							|  |  |  |       settings_.setValue (multi_settings_place_holder_key, QVariant {}); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |   settings_.sync (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::select_configuration (QMainWindow * main_window, QMenu const * menu) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   auto const& target_name = menu->title (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   if (target_name != current_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	auto const& current_group = settings_.group (); | 
					
						
							|  |  |  | 	if (current_group.size ()) settings_.endGroup (); | 
					
						
							|  |  |  | 	// position to the alternative settings
 | 
					
						
							|  |  |  | 	SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  | 	// save the target settings
 | 
					
						
							|  |  |  | 	SettingsGroup target_group {&settings_, target_name}; | 
					
						
							|  |  |  | 	new_settings_ = get_settings (); | 
					
						
							|  |  |  | 	if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // and set up the restart
 | 
					
						
							|  |  |  |       current_ = target_name; | 
					
						
							|  |  |  |       Q_EMIT parent_->configurationNameChanged (current_); | 
					
						
							|  |  |  |       reposition_type_ = RepositionType::save_and_replace; | 
					
						
							|  |  |  |       exit_flag_ = false; | 
					
						
							|  |  |  |       main_window->close (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::clone_configuration (QMainWindow * main_window, QMenu * parent_menu, QMenu const * menu) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.endGroup (); | 
					
						
							|  |  |  |   auto const& source_name = menu->title (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // settings to clone
 | 
					
						
							|  |  |  |   Dictionary source_settings; | 
					
						
							|  |  |  |   if (source_name == current_) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       // grab the data to clone from the current settings
 | 
					
						
							|  |  |  |       source_settings = get_settings (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |   if (source_name != current_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       SettingsGroup source_group {&settings_, source_name}; | 
					
						
							|  |  |  |       source_settings = get_settings (); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   // find a new unique name
 | 
					
						
							|  |  |  |   QString new_name_root {source_name + " - Copy"};; | 
					
						
							|  |  |  |   QString new_name {new_name_root}; | 
					
						
							|  |  |  |   unsigned index {0}; | 
					
						
							|  |  |  |   do | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (index++) new_name = new_name_root + '(' + QString::number (index) + ')'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   while (settings_.childGroups ().contains (new_name) || new_name == current_); | 
					
						
							|  |  |  |   SettingsGroup new_group {&settings_, new_name}; | 
					
						
							|  |  |  |   load_from (source_settings); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   // insert the new configuration sub menu in the parent menu
 | 
					
						
							|  |  |  |   create_sub_menu (main_window, parent_menu, new_name, configurations_group_); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window, QMenu const * menu) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.endGroup (); | 
					
						
							|  |  |  |   auto const& target_name = menu->title (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // get the current configuration name
 | 
					
						
							|  |  |  |   QString current_group_name; | 
					
						
							|  |  |  |   QStringList sources; | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |     current_group_name = settings_.value (multi_settings_current_name_key).toString (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // get the source configuration name for the clone
 | 
					
						
							|  |  |  |       sources = settings_.childGroups (); | 
					
						
							|  |  |  |       sources << current_group_name; | 
					
						
							|  |  |  |       sources.removeOne (target_name); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // pick a source configuration
 | 
					
						
							|  |  |  |   ExistingNameDialog dialog {sources, main_window}; | 
					
						
							|  |  |  |   if (sources.size () && (1 == sources.size () || QDialog::Accepted == dialog.exec ())) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QString source_name {1 == sources.size () ? sources.at (0) : dialog.name ()}; | 
					
						
							|  |  |  |       if (MessageBox::Yes == MessageBox::query_message (main_window, | 
					
						
							|  |  |  | 							tr ("Clone Into Configuration"), | 
					
						
							|  |  |  | 							tr ("Confirm overwrite of all values for configuration \"%1\" with values from \"%2\"?") | 
					
						
							|  |  |  | 							.arg (target_name) | 
					
						
							|  |  |  | 							.arg (source_name))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  // grab the data to clone from
 | 
					
						
							|  |  |  | 	  if (source_name == current_group_name) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      // grab the data to clone from the current settings
 | 
					
						
							|  |  |  | 	      new_settings_ = get_settings (); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  | 	      SettingsGroup source_group {&settings_, source_name}; | 
					
						
							|  |  |  | 	      new_settings_ = get_settings (); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  // purge target settings and replace
 | 
					
						
							|  |  |  | 	  if (target_name == current_) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      // restart with new settings
 | 
					
						
							|  |  |  | 	      reposition_type_ = RepositionType::replace; | 
					
						
							|  |  |  | 	      exit_flag_ = false; | 
					
						
							|  |  |  | 	      main_window->close (); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  | 	      SettingsGroup target_group {&settings_, target_name}; | 
					
						
							|  |  |  | 	      settings_.remove (QString {}); // purge entire group
 | 
					
						
							|  |  |  | 	      load_from (new_settings_); | 
					
						
							|  |  |  | 	      new_settings_.clear (); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::reset_configuration (QMainWindow * main_window, QMenu const * menu) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   auto const& target_name = menu->title (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (MessageBox::Yes != MessageBox::query_message (main_window, | 
					
						
							|  |  |  | 						    tr ("Reset Configuration"), | 
					
						
							|  |  |  | 						    tr ("Confirm reset to default values for configuration \"%1\"?") | 
					
						
							|  |  |  | 						    .arg (target_name))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (target_name == current_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // restart with default settings
 | 
					
						
							|  |  |  |       reposition_type_ = RepositionType::replace; | 
					
						
							|  |  |  |       new_settings_.clear (); | 
					
						
							|  |  |  |       exit_flag_ = false; | 
					
						
							|  |  |  |       main_window->close (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |       if (current_group.size ()) settings_.endGroup (); | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |       SettingsGroup target_group {&settings_, target_name}; | 
					
						
							|  |  |  |       settings_.remove (QString {}); // purge entire group
 | 
					
						
							|  |  |  |       // add a placeholder to stop alternative configuration name
 | 
					
						
							|  |  |  |       // being lost
 | 
					
						
							|  |  |  |       settings_.setValue (multi_settings_place_holder_key, QVariant {}); | 
					
						
							|  |  |  |       settings_.sync (); | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::rename_configuration (QMainWindow * main_window, QMenu * menu) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |   if (current_group.size ()) settings_.endGroup (); | 
					
						
							|  |  |  |   auto const& target_name = menu->title (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   // gather names we cannot use
 | 
					
						
							|  |  |  |   SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							|  |  |  |   auto invalid_names = settings_.childGroups (); | 
					
						
							|  |  |  |   invalid_names << settings_.value (multi_settings_current_name_key).toString (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   // get the new name
 | 
					
						
							|  |  |  |   NameDialog dialog {target_name, invalid_names, main_window}; | 
					
						
							|  |  |  |   if (QDialog::Accepted == dialog.exec ()) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       if (target_name == current_) | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  settings_.setValue (multi_settings_current_name_key, dialog.new_name ()); | 
					
						
							|  |  |  | 	  settings_.sync (); | 
					
						
							|  |  |  | 	  current_ = dialog.new_name (); | 
					
						
							|  |  |  | 	  Q_EMIT parent_->configurationNameChanged (current_); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  // switch to the target group and fetch the configuration data
 | 
					
						
							|  |  |  | 	  Dictionary target_settings; | 
					
						
							|  |  |  | 	  { | 
					
						
							|  |  |  | 	    // grab the target configuration settings
 | 
					
						
							|  |  |  | 	    SettingsGroup target_group {&settings_, target_name}; | 
					
						
							|  |  |  | 	    target_settings = get_settings (); | 
					
						
							|  |  |  | 	    // purge the old configuration data
 | 
					
						
							|  |  |  | 	    settings_.remove (QString {}); // purge entire group
 | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  // load into new configuration group name
 | 
					
						
							|  |  |  | 	  SettingsGroup target_group {&settings_, dialog.new_name ()}; | 
					
						
							|  |  |  | 	  load_from (target_settings); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       // change the action text in the menu
 | 
					
						
							|  |  |  |       menu->setTitle (dialog.new_name ()); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  | void MultiSettings::impl::delete_configuration (QMainWindow * main_window, QMenu * menu) | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   auto const& target_name = menu->title (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (target_name == current_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return;               // suicide not allowed here
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       if (MessageBox::Yes != MessageBox::query_message (main_window, | 
					
						
							|  |  |  | 							tr ("Delete Configuration"), | 
					
						
							|  |  |  | 							tr ("Confirm deletion of configuration \"%1\"?") | 
					
						
							|  |  |  | 							.arg (target_name))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       auto const& current_group = settings_.group (); | 
					
						
							|  |  |  |       if (current_group.size ()) settings_.endGroup (); | 
					
						
							| 
									
										
										
										
											2016-04-21 18:56:59 +00:00
										 |  |  |       SettingsGroup alternatives {&settings_, multi_settings_root_group}; | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |       SettingsGroup target_group {&settings_, target_name}; | 
					
						
							|  |  |  |       // purge the configuration data
 | 
					
						
							|  |  |  |       settings_.remove (QString {}); // purge entire group
 | 
					
						
							|  |  |  |       settings_.sync (); | 
					
						
							| 
									
										
										
										
											2016-09-11 01:09:28 +00:00
										 |  |  |       if (current_group.size ()) settings_.beginGroup (current_group); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-29 12:05:52 +00:00
										 |  |  |   // update the menu
 | 
					
						
							|  |  |  |   menu->deleteLater (); | 
					
						
							| 
									
										
										
										
											2016-04-17 23:39:12 +00:00
										 |  |  | } |