From d8a2c1239cafbff0bbcb9b8705dd3c8d9923e0c1 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 11 Sep 2016 01:09:28 +0000 Subject: [PATCH] Make the splash screen less annoying with a permanent disable check box The change also includes a new MultiSettings feature that allows settings keys common to all configurations. The splash screen disable is the first of those to be used. The MultiSettings class has been made safer to use by ensuring it saves and re-enables the current QSettings group when doing multi settings actions. This allows access to common, across configuration, items while within a normal settings group without breaking the MultiSettings internal implementation. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7073 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- CMakeLists.txt | 1 + MultiSettings.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++ MultiSettings.hpp | 11 +++++++- SplashScreen.cpp | 51 +++++++++++++++++++++++++++++++++++++ SplashScreen.hpp | 24 +++++++++++++++++ main.cpp | 50 ++++++++++++++---------------------- 6 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 SplashScreen.cpp create mode 100644 SplashScreen.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e20041eea..923be021a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -236,6 +236,7 @@ set (wsjt_qt_CXXSRCS MultiSettings.cpp MaidenheadLocatorValidator.cpp CallsignValidator.cpp + SplashScreen.cpp ) set (wsjt_qtmm_CXXSRCS diff --git a/MultiSettings.cpp b/MultiSettings.cpp index 8f483849f..7f1e423da 100644 --- a/MultiSettings.cpp +++ b/MultiSettings.cpp @@ -217,6 +217,44 @@ QSettings * MultiSettings::settings () return &m_->settings_; } +QVariant MultiSettings::common_value (QString const& key, QVariant const& default_value) const +{ + QVariant value; + QSettings& mutable_settings {const_cast (m_->settings_)}; + auto const& current_group = mutable_settings.group (); + if (current_group.size ()) mutable_settings.endGroup (); + { + SettingsGroup alternatives {&mutable_settings, multi_settings_root_group}; + value = mutable_settings.value (key, default_value); + } + if (current_group.size ()) mutable_settings.beginGroup (current_group); + 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); +} + void MultiSettings::create_menu_actions (QMainWindow * main_window, QMenu * menu) { m_->create_menu_actions (main_window, menu); @@ -287,6 +325,8 @@ MultiSettings::impl::impl () // do actions that can only be done once all the windows are closed bool MultiSettings::impl::reposition () { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); switch (reposition_type_) { case RepositionType::save_and_replace: @@ -337,6 +377,7 @@ bool MultiSettings::impl::reposition () new_settings_.clear (); break; } + if (current_group.size ()) settings_.beginGroup (current_group); reposition_type_ = RepositionType::unchanged; // reset bool exit {exit_flag_}; @@ -349,6 +390,8 @@ bool MultiSettings::impl::reposition () // and, reset void MultiSettings::impl::create_menu_actions (QMainWindow * main_window, QMenu * menu) { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); 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 (); @@ -386,6 +429,7 @@ void MultiSettings::impl::create_menu_actions (QMainWindow * main_window, QMenu action_connections_ << connect (delete_action_, &QAction::triggered, [this, main_window] (bool) { delete_configuration (main_window); }); + if (current_group.size ()) settings_.beginGroup (current_group); } // call this at the end of the main program loop to determine if the @@ -422,8 +466,11 @@ QMenu * MultiSettings::impl::create_sub_menu (QMenu * parent_menu, bool is_current {sub_menu->menuAction ()->text () == current_}; select_action_->setEnabled (!is_current); delete_action_->setEnabled (!is_current); + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); SettingsGroup alternatives {&settings_, multi_settings_root_group}; clone_into_action_->setEnabled (settings_.childGroups ().size ()); + if (current_group.size ()) settings_.beginGroup (current_group); active_sub_menu_ = sub_menu; }); @@ -474,11 +521,14 @@ void MultiSettings::impl::select_configuration (QMainWindow * main_window) 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; @@ -493,6 +543,8 @@ void MultiSettings::impl::clone_configuration (QMenu * menu) { if (active_sub_menu_) { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); auto const& source_name = active_sub_menu_->title (); // settings to clone @@ -523,6 +575,7 @@ void MultiSettings::impl::clone_configuration (QMenu * menu) // insert the new configuration sub menu in the parent menu create_sub_menu (menu, new_name, configurations_group_); + if (current_group.size ()) settings_.beginGroup (current_group); } } @@ -530,6 +583,8 @@ void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window) { if (active_sub_menu_) { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); auto const& target_name = active_sub_menu_->title (); // get the current configuration name @@ -589,6 +644,7 @@ void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window) } } } + if (current_group.size ()) settings_.beginGroup (current_group); } } @@ -616,6 +672,8 @@ void MultiSettings::impl::reset_configuration (QMainWindow * main_window) } else { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); SettingsGroup alternatives {&settings_, multi_settings_root_group}; SettingsGroup target_group {&settings_, target_name}; settings_.remove (""); // purge entire group @@ -623,6 +681,7 @@ void MultiSettings::impl::reset_configuration (QMainWindow * main_window) // being lost settings_.setValue (multi_settings_place_holder_key, QVariant {}); settings_.sync (); + if (current_group.size ()) settings_.beginGroup (current_group); } } } @@ -631,6 +690,8 @@ void MultiSettings::impl::rename_configuration (QMainWindow * main_window) { if (active_sub_menu_) { + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); auto const& target_name = active_sub_menu_->title (); // gather names we cannot use @@ -666,6 +727,7 @@ void MultiSettings::impl::rename_configuration (QMainWindow * main_window) // change the action text in the menu active_sub_menu_->setTitle (dialog.new_name ()); } + if (current_group.size ()) settings_.beginGroup (current_group); } } @@ -688,11 +750,14 @@ void MultiSettings::impl::delete_configuration (QMainWindow * main_window) { return; } + auto const& current_group = settings_.group (); + if (current_group.size ()) settings_.endGroup (); SettingsGroup alternatives {&settings_, multi_settings_root_group}; SettingsGroup target_group {&settings_, target_name}; // purge the configuration data settings_.remove (""); // purge entire group settings_.sync (); + if (current_group.size ()) settings_.beginGroup (current_group); } // update the menu active_sub_menu_->deleteLater (), active_sub_menu_ = nullptr; diff --git a/MultiSettings.hpp b/MultiSettings.hpp index 80e1b49a7..1fdc0308f 100644 --- a/MultiSettings.hpp +++ b/MultiSettings.hpp @@ -1,10 +1,14 @@ -#ifndef MULTISETTINGS_HPP_ +#ifndef MULTISETTINGS_HPP__ +#define MULTISETTINGS_HPP__ + +#include #include "pimpl_h.hpp" class QSettings; class QMainWindow; class QMenu; +class QString; // // MultiSettings - Manage multiple configuration names @@ -71,6 +75,11 @@ public: // Access to the QSettings object instance. QSettings * settings (); + // Access to values in a common section + QVariant common_value (QString const& key, QVariant const& default_value = QVariant {}) const; + void set_common_value (QString const& key, QVariant const& value); + void remove_common_value (QString const& key); + // Call this to determine if the application is terminating, if it // returns false then the application main window should be // recreated, shown and the application exec() function called diff --git a/SplashScreen.cpp b/SplashScreen.cpp new file mode 100644 index 000000000..cdeed79b3 --- /dev/null +++ b/SplashScreen.cpp @@ -0,0 +1,51 @@ +#include "SplashScreen.hpp" + +#include +#include +#include +#include + +#include "revision_utils.hpp" +#include "pimpl_impl.hpp" + +class SplashScreen::impl +{ +public: + impl () + : checkbox_ {"Do not show this again"} + { + main_layout_.addStretch (); + main_layout_.addWidget (&checkbox_, 0, Qt::AlignRight); + } + + QVBoxLayout main_layout_; + QCheckBox checkbox_; +}; + +SplashScreen::SplashScreen () + : QSplashScreen {QPixmap {":/splash.png"}, Qt::WindowStaysOnTopHint} +{ + setLayout (&m_->main_layout_); + showMessage ("

" + QString {"Alpha Release: WSJT-X v" + + QCoreApplication::applicationVersion() + " " + + revision ()}.simplified () + "

" + "V1.7 has many new features, most aimed at VHF/UHF/Microwave users.
" + "Some are not yet described in the User Guide and may not be thoroughly
" + "tested. The release notes have more details.

" + "As a test user you have an obligation to report anomalous results
" + "to the development team. We are particularly interested in tests
" + "of experimental modes QRA64 (intended for EME) and MSK144
" + "(intended for meteor scatter).

" + "Send reports to wsjtgroup@yahoogroups.com, and be sure to save .wav
" + "files where appropriate.

" + "Open the Help menu and select Release Notes for more details.
" + "" + "", Qt::AlignCenter); + connect (&m_->checkbox_, &QCheckBox::stateChanged, [this] (int s) { + if (Qt::Checked == s) Q_EMIT disabled (); + }); +} + +SplashScreen::~SplashScreen () +{ +} diff --git a/SplashScreen.hpp b/SplashScreen.hpp new file mode 100644 index 000000000..6bf7712c6 --- /dev/null +++ b/SplashScreen.hpp @@ -0,0 +1,24 @@ +#ifndef SPLASH_SCREEN_HPP___ +#define SPLASH_SCREEN_HPP___ + +#include + +#include "pimpl_h.hpp" + +class SplashScreen final + : public QSplashScreen +{ + Q_OBJECT; + +public: + SplashScreen (); + ~SplashScreen (); + + Q_SIGNAL void disabled (); + +private: + class impl; + pimpl m_; +}; + +#endif diff --git a/main.cpp b/main.cpp index bc077beb7..89272f3bd 100644 --- a/main.cpp +++ b/main.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #if QT_VERSION >= 0x050200 #include @@ -37,6 +36,7 @@ #include "lib/init_random_seed.h" #include "Radio.hpp" #include "FrequencyList.hpp" +#include "SplashScreen.hpp" #include "MessageBox.hpp" // last to avoid nasty MS macro definitions extern "C" { @@ -105,27 +105,6 @@ int main(int argc, char *argv[]) // instantiating QApplication so // that GUI has correct l18n - QPixmap splash_pic {":/splash.png"}; - QSplashScreen splash {splash_pic, Qt::WindowStaysOnTopHint}; - splash.setWindowTitle (QString {}); - splash.showMessage ("

" + QString {"Alpha Release: WSJT-X v" + - QCoreApplication::applicationVersion() + " " + - revision ()}.simplified () + "

" - "V1.7 has many new features, most aimed at VHF/UHF/Microwave users.
" - "Some are not yet described in the User Guide and may not be thoroughly
" - "tested. The release notes have more details.

" - "As a test user you have an obligation to report anomalous results
" - "to the development team. We are particularly interested in tests
" - "of experimental modes QRA64 (intended for EME) and MSK144
" - "(intended for meteor scatter).

" - "Send reports to wsjtgroup@yahoogroups.com, and be sure to save .wav
" - "files where appropriate.

" - "Open the Help menu and select Release Notes for more details.
" - "" - "", Qt::AlignCenter); - splash.show (); - a.processEvents (); - // Override programs executable basename as application name. a.setApplicationName ("WSJT-X"); a.setApplicationVersion (version ()); @@ -148,7 +127,6 @@ int main(int argc, char *argv[]) if (!parser.parse (a.arguments ())) { - splash.hide (); MessageBox::critical_message (nullptr, a.translate ("main", "Command line error"), parser.errorText ()); return -1; } @@ -156,13 +134,11 @@ int main(int argc, char *argv[]) { if (parser.isSet (help_option)) { - splash.hide (); MessageBox::information_message (nullptr, a.translate ("main", "Command line help"), parser.helpText ()); return 0; } else if (parser.isSet (version_option)) { - splash.hide (); MessageBox::information_message (nullptr, a.translate ("main", "Application version"), a.applicationVersion ()); return 0; } @@ -193,6 +169,8 @@ int main(int argc, char *argv[]) multiple = true; } + // now we have the application name we can open the settings + MultiSettings multi_settings; // find the temporary files path QDir temp_dir {QStandardPaths::writableLocation (QStandardPaths::TempLocation)}; @@ -206,7 +184,6 @@ int main(int argc, char *argv[]) { if (QLockFile::LockFailedError == instance_lock.error ()) { - splash.hide (); auto button = MessageBox::query_message (nullptr , a.translate ("main", "Another instance may be running") , a.translate ("main", "try to remove stale lock file?") @@ -225,7 +202,6 @@ int main(int argc, char *argv[]) default: throw std::runtime_error {"Multiple instances must have unique rig names"}; } - splash.show (); } } #endif @@ -244,7 +220,6 @@ int main(int argc, char *argv[]) if (!temp_dir.mkpath (unique_directory) || !temp_dir.cd (unique_directory)) { - splash.hide (); MessageBox::critical_message (nullptr, a.translate ("main", "Failed to create a temporary directory"), a.translate ("main", "Path: \"%1\"").arg (temp_dir.absolutePath ())); @@ -252,7 +227,6 @@ int main(int argc, char *argv[]) } if (!temp_dir.isReadable () || !(temp_ok = QTemporaryFile {temp_dir.absoluteFilePath ("test")}.open ())) { - splash.hide (); auto button = MessageBox::critical_message (nullptr, a.translate ("main", "Failed to create a usable temporary directory"), a.translate ("main", "Another application may be locking the directory"), @@ -262,13 +236,27 @@ int main(int argc, char *argv[]) { throw std::runtime_error {"Failed to create a usable temporary directory"}; } - splash.show (); temp_dir.cdUp (); // revert to parent as this one is no good } } while (!temp_ok); - MultiSettings multi_settings; + SplashScreen splash; + { + // change this key if you want to force a new splash screen + // for a new version, the user will be able to re-disable it + // if they wish + QString splash_flag_name {"Splash_v1.7"}; + if (multi_settings.common_value (splash_flag_name, true).toBool ()) + { + QObject::connect (&splash, &SplashScreen::disabled, [&, splash_flag_name] { + multi_settings.set_common_value (splash_flag_name, false); + splash.close (); + }); + splash.show (); + a.processEvents (); + } + } int result; do