mono: Show a popup during database migration
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 30 May 2018 23:16:47 +0000 (01:16 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 6 Jun 2018 19:12:17 +0000 (21:12 +0200)
Database upgrades may take a long while, during which the monolightic
client can not be used. Show a modal popup during migration to both
inform the user about what's going on, and preventing them from
interacting with the client until the internal core is up and running.

Show an "Initializing..." message in the status bar while the core
is starting up, so there's some indication for the user besides the
modal popup.

src/client/client.cpp
src/client/client.h
src/client/coreconnection.cpp
src/core/abstractsqlstorage.cpp
src/core/core.cpp
src/core/core.h
src/core/storage.h
src/qtui/mainwin.cpp
src/qtui/mainwin.h
src/qtui/monoapplication.cpp

index 0c71bef..6cd94c1 100644 (file)
@@ -206,6 +206,12 @@ bool Client::internalCore()
 }
 
 
 }
 
 
+void Client::onDbUpgradeInProgress(bool inProgress)
+{
+    emit dbUpgradeInProgress(inProgress);
+}
+
+
 /*** Network handling ***/
 
 QList<NetworkId> Client::networkIds()
 /*** Network handling ***/
 
 QList<NetworkId> Client::networkIds()
index 3dc261a..3676e29 100644 (file)
@@ -217,6 +217,9 @@ signals:
     void requestKickClient(int peerId);
     void passwordChanged(bool success);
 
     void requestKickClient(int peerId);
     void passwordChanged(bool success);
 
+    //! Emitted when database schema upgrade starts or ends (only mono client)
+    void dbUpgradeInProgress(bool inProgress);
+
 public slots:
     void disconnectFromCore();
 
 public slots:
     void disconnectFromCore();
 
@@ -226,6 +229,8 @@ public slots:
 
     void markBufferAsRead(BufferId id);
 
 
     void markBufferAsRead(BufferId id);
 
+    void onDbUpgradeInProgress(bool inProgress);
+
 private slots:
     void setSyncedToCore();
     void setDisconnectedFromCore();
 private slots:
     void setSyncedToCore();
     void setDisconnectedFromCore();
index dd196d1..4127152 100644 (file)
@@ -385,6 +385,7 @@ void CoreConnection::connectToCurrentAccount()
         InternalPeer *peer = new InternalPeer();
         _peer = peer;
         Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership
         InternalPeer *peer = new InternalPeer();
         _peer = peer;
         Client::instance()->signalProxy()->addPeer(peer); // sigproxy will take ownership
+        emit connectionMsg(tr("Initializing..."));
         emit connectToInternalCore(peer);
         setState(Connected);
         return;
         emit connectToInternalCore(peer);
         setState(Connected);
         return;
index fce1bb1..89169ee 100644 (file)
@@ -139,20 +139,19 @@ Storage::State AbstractSqlStorage::init(const QVariantMap &settings,
     }
 
     if (installedSchemaVersion() < schemaVersion()) {
     }
 
     if (installedSchemaVersion() < schemaVersion()) {
-        qWarning() << qPrintable(tr("Installed Schema (version %1) is not up to date. Upgrading to "
-                                    "version %2...  This may take a while for major upgrades."
-                                    ).arg(installedSchemaVersion()).arg(schemaVersion()));
-        // TODO: The monolithic client won't show this message unless one looks into the debug log.
-        // This should be made more friendly, e.g. a popup message in the GUI.
-        if (!upgradeDb()) {
+        quInfo() << qPrintable(tr("Installed database schema (version %1) is not up to date. Upgrading to "
+                                  "version %2...  This may take a while for major upgrades."
+                                 ).arg(installedSchemaVersion()).arg(schemaVersion()));
+        emit dbUpgradeInProgress(true);
+        auto upgradeResult = upgradeDb();
+        emit dbUpgradeInProgress(false);
+        if (!upgradeResult) {
             qWarning() << qPrintable(tr("Upgrade failed..."));
             return NotAvailable;
         }
             qWarning() << qPrintable(tr("Upgrade failed..."));
             return NotAvailable;
         }
-        // Warning messages are also sent to the console, while Info messages aren't.  Add a message
-        // when migration succeeds to avoid confusing folks by implying the schema upgrade failed if
+        // Add a message when migration succeeds to avoid confusing folks by implying the schema upgrade failed if
         // later functionality does not work.
         // later functionality does not work.
-        qWarning() << qPrintable(tr("Installed Schema successfully upgraded to version %1."
-                                    ).arg(schemaVersion()));
+        quInfo() << qPrintable(tr("Installed database schema successfully upgraded to version %1.").arg(schemaVersion()));
     }
 
     quInfo() << qPrintable(displayName()) << "storage backend is ready. Schema version:" << installedSchemaVersion();
     }
 
     quInfo() << qPrintable(displayName()) << "storage backend is ready. Schema version:" << installedSchemaVersion();
index 3f49a22..cf943b9 100644 (file)
@@ -406,6 +406,8 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings,
         return false;
     }
 
         return false;
     }
 
+    connect(storage.get(), SIGNAL(dbUpgradeInProgress(bool)), this, SIGNAL(dbUpgradeInProgress(bool)));
+
     Storage::State storageState = storage->init(settings, environment, loadFromEnvironment);
     switch (storageState) {
     case Storage::NeedsSetup:
     Storage::State storageState = storage->init(settings, environment, loadFromEnvironment);
     switch (storageState) {
     case Storage::NeedsSetup:
index e0ec748..01bf477 100644 (file)
@@ -702,6 +702,9 @@ signals:
     //! Relay from CoreSession::sessionState(). Used for internal connection only
     void sessionState(const Protocol::SessionState &sessionState);
 
     //! Relay from CoreSession::sessionState(). Used for internal connection only
     void sessionState(const Protocol::SessionState &sessionState);
 
+    //! Emitted when database schema upgrade starts or ends
+    void dbUpgradeInProgress(bool inProgress);
+
 public slots:
     bool init();
 
 public slots:
     bool init();
 
index f912c8b..3930a95 100644 (file)
@@ -551,6 +551,9 @@ signals:
     //! Sent when a user has been removed
     void userRemoved(UserId);
 
     //! Sent when a user has been removed
     void userRemoved(UserId);
 
+    //! Emitted when database schema upgrade starts or ends
+    void dbUpgradeInProgress(bool inProgress);
+
 protected:
     QString hashPassword(const QString &password);
     bool checkHashedPassword(const UserId user, const QString &password, const QString &hashedPassword, const Storage::HashVersion version);
 protected:
     QString hashPassword(const QString &password);
     bool checkHashedPassword(const UserId user, const QString &password, const QString &hashedPassword, const Storage::HashVersion version);
index 5dd6eb4..b1a4eb7 100644 (file)
@@ -207,6 +207,7 @@ void MainWin::init()
     connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showNetworkConfig(NetworkId)), SLOT(showNetworkConfig(NetworkId)));
     connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString)));
     connect(Client::instance(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString)));
     connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showNetworkConfig(NetworkId)), SLOT(showNetworkConfig(NetworkId)));
     connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString)));
     connect(Client::instance(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString)));
+    connect(Client::instance(), SIGNAL(dbUpgradeInProgress(bool)), SLOT(showMigrationWarning(bool)));
 
     connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList, QVariantList)), SLOT(showCoreConfigWizard(QVariantList, QVariantList)));
     connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString)));
 
     connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList, QVariantList)), SLOT(showCoreConfigWizard(QVariantList, QVariantList)));
     connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString)));
@@ -828,6 +829,29 @@ void MainWin::showPasswordChangeDlg()
 }
 
 
 }
 
 
+void MainWin::showMigrationWarning(bool show)
+{
+    if (show && !_migrationWarning) {
+        _migrationWarning = new QMessageBox(QMessageBox::Information,
+                                            tr("Upgrading..."),
+                                            "<b>" + tr("Your database is being upgraded") + "</b>",
+                                            QMessageBox::NoButton, this);
+        _migrationWarning->setInformativeText("<p>"
+                                              + tr("In order to support new features, we need to make changes to your backlog database. This may take a long while.")
+                                              + "</p><p>"
+                                              + tr("Do not exit Quassel until the upgrade is complete!")
+                                              + "</p>");
+        _migrationWarning->setStandardButtons(QMessageBox::NoButton);
+        _migrationWarning->show();
+    }
+    else if (!show && _migrationWarning) {
+        _migrationWarning->close();
+        _migrationWarning->deleteLater();
+        _migrationWarning = nullptr;
+    }
+}
+
+
 void MainWin::changeActiveBufferView(bool backwards)
 {
     if (_activeBufferViewIndex >= 0 && _activeBufferViewIndex < _bufferViews.count()) {
 void MainWin::changeActiveBufferView(bool backwards)
 {
     if (_activeBufferViewIndex >= 0 && _activeBufferViewIndex < _bufferViews.count()) {
index aa8aa94..6f741f5 100644 (file)
@@ -50,8 +50,9 @@ class NickListWidget;
 class SystemTray;
 class TopicWidget;
 
 class SystemTray;
 class TopicWidget;
 
-class QMenu;
 class QLabel;
 class QLabel;
+class QMenu;
+class QMessageBox;
 class QToolBar;
 
 class KHelpMenu;
 class QToolBar;
 
 class KHelpMenu;
@@ -97,6 +98,8 @@ public slots:
     void nextBuffer();
     void previousBuffer();
 
     void nextBuffer();
     void previousBuffer();
 
+    void showMigrationWarning(bool show);
+
     //! Quit application
     void quit();
 
     //! Quit application
     void quit();
 
@@ -261,6 +264,8 @@ private:
 
     QWidget *_awayLog;
 
 
     QWidget *_awayLog;
 
+    QMessageBox* _migrationWarning{nullptr};
+
     bool _layoutLoaded;
 
     QSize _normalSize; //!< Size of the non-maximized window
     bool _layoutLoaded;
 
     QSize _normalSize; //!< Size of the non-maximized window
index 1a8822d..d880f33 100644 (file)
@@ -82,6 +82,8 @@ void MonolithicApplication::startInternalCore()
     connect(this, SIGNAL(connectInternalPeer(QPointer<InternalPeer>)), _core, SLOT(connectInternalPeer(QPointer<InternalPeer>)));
     connect(_core, SIGNAL(sessionState(Protocol::SessionState)), Client::coreConnection(), SLOT(internalSessionStateReceived(Protocol::SessionState)));
 
     connect(this, SIGNAL(connectInternalPeer(QPointer<InternalPeer>)), _core, SLOT(connectInternalPeer(QPointer<InternalPeer>)));
     connect(_core, SIGNAL(sessionState(Protocol::SessionState)), Client::coreConnection(), SLOT(internalSessionStateReceived(Protocol::SessionState)));
 
+    connect(_core, SIGNAL(dbUpgradeInProgress(bool)), Client::instance(), SLOT(onDbUpgradeInProgress(bool)));
+
     _coreThread.start();
 }
 
     _coreThread.start();
 }