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
This commit is contained in:
Bill Somerville 2016-09-11 01:09:28 +00:00
parent d3fd8fc523
commit d8a2c1239c
6 changed files with 170 additions and 32 deletions

View File

@ -236,6 +236,7 @@ set (wsjt_qt_CXXSRCS
MultiSettings.cpp
MaidenheadLocatorValidator.cpp
CallsignValidator.cpp
SplashScreen.cpp
)
set (wsjt_qtmm_CXXSRCS

View File

@ -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<QSettings&> (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;

View File

@ -1,10 +1,14 @@
#ifndef MULTISETTINGS_HPP_
#ifndef MULTISETTINGS_HPP__
#define MULTISETTINGS_HPP__
#include <QVariant>
#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

51
SplashScreen.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "SplashScreen.hpp"
#include <QPixmap>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QCoreApplication>
#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 ("<h2>" + QString {"Alpha Release: WSJT-X v" +
QCoreApplication::applicationVersion() + " " +
revision ()}.simplified () + "</h2>"
"V1.7 has many new features, most aimed at VHF/UHF/Microwave users.<br />"
"Some are not yet described in the User Guide and may not be thoroughly<br />"
"tested. The release notes have more details.<br /><br />"
"As a test user you have an obligation to report anomalous results<br />"
"to the development team. We are particularly interested in tests<br />"
"of experimental modes QRA64 (intended for EME) and MSK144<br />"
"(intended for meteor scatter).<br /><br />"
"Send reports to wsjtgroup@yahoogroups.com, and be sure to save .wav<br />"
"files where appropriate.<br /><br />"
"<b>Open the Help menu and select Release Notes for more details.</b><br />"
"<img src=\":/icon_128x128.png\" />"
"<img src=\":/gpl-v3-logo.svg\" height=\"80\" />", Qt::AlignCenter);
connect (&m_->checkbox_, &QCheckBox::stateChanged, [this] (int s) {
if (Qt::Checked == s) Q_EMIT disabled ();
});
}
SplashScreen::~SplashScreen ()
{
}

24
SplashScreen.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef SPLASH_SCREEN_HPP___
#define SPLASH_SCREEN_HPP___
#include <QSplashScreen>
#include "pimpl_h.hpp"
class SplashScreen final
: public QSplashScreen
{
Q_OBJECT;
public:
SplashScreen ();
~SplashScreen ();
Q_SIGNAL void disabled ();
private:
class impl;
pimpl<impl> m_;
};
#endif

View File

@ -20,7 +20,6 @@
#include <QLockFile>
#include <QStack>
#include <QSplashScreen>
#include <QPixmap>
#if QT_VERSION >= 0x050200
#include <QCommandLineParser>
@ -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 ("<h2>" + QString {"Alpha Release: WSJT-X v" +
QCoreApplication::applicationVersion() + " " +
revision ()}.simplified () + "</h2>"
"V1.7 has many new features, most aimed at VHF/UHF/Microwave users.<br />"
"Some are not yet described in the User Guide and may not be thoroughly<br />"
"tested. The release notes have more details.<br /><br />"
"As a test user you have an obligation to report anomalous results<br />"
"to the development team. We are particularly interested in tests<br />"
"of experimental modes QRA64 (intended for EME) and MSK144<br />"
"(intended for meteor scatter).<br /><br />"
"Send reports to wsjtgroup@yahoogroups.com, and be sure to save .wav<br />"
"files where appropriate.<br /><br />"
"<b>Open the Help menu and select Release Notes for more details.</b><br />"
"<img src=\":/icon_128x128.png\" />"
"<img src=\":/gpl-v3-logo.svg\" height=\"80\" />", 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