File indexing completed on 2025-01-19 03:53:48

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-11-14
0007  * Description : database migration dialog
0008  *
0009  * SPDX-FileCopyrightText: 2009-2010 by Holger Foerster <Hamsi2k at freenet dot de>
0010  * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "dbmigrationdlg.h"
0017 
0018 // QT includes
0019 
0020 #include <QApplication>
0021 #include <QGridLayout>
0022 #include <QWidget>
0023 #include <QList>
0024 #include <QSqlQuery>
0025 #include <QMap>
0026 #include <QSqlError>
0027 #include <QLabel>
0028 #include <QGroupBox>
0029 #include <QDialogButtonBox>
0030 #include <QVBoxLayout>
0031 #include <QPushButton>
0032 #include <QMessageBox>
0033 
0034 // KDE includes
0035 
0036 #include <klocalizedstring.h>
0037 
0038 // Local includes
0039 
0040 #include "digikam_debug.h"
0041 #include "digikam_globals.h"
0042 #include "applicationsettings.h"
0043 #include "coredbaccess.h"
0044 #include "dbengineparameters.h"
0045 #include "coredbschemaupdater.h"
0046 
0047 namespace Digikam
0048 {
0049 
0050 class Q_DECL_HIDDEN DatabaseCopyThread::Private
0051 {
0052 public:
0053 
0054     explicit Private()
0055     {
0056     }
0057 
0058     DbEngineParameters fromDbEngineParameters;
0059     DbEngineParameters toDbEngineParameters;
0060 };
0061 
0062 DatabaseCopyThread::DatabaseCopyThread(QWidget* const parent)
0063     : QThread(parent),
0064       d      (new Private)
0065 {
0066 }
0067 
0068 DatabaseCopyThread::~DatabaseCopyThread()
0069 {
0070     delete d;
0071 }
0072 
0073 void DatabaseCopyThread::run()
0074 {
0075     m_copyManager.copyDatabases(d->fromDbEngineParameters, d->toDbEngineParameters);
0076 }
0077 
0078 void DatabaseCopyThread::init(const DbEngineParameters& fromDbEngineParameters,
0079                               const DbEngineParameters& toDbEngineParameters)
0080 {
0081     d->fromDbEngineParameters = fromDbEngineParameters;
0082     d->toDbEngineParameters   = toDbEngineParameters;
0083 }
0084 
0085 // ---------------------------------------------------------------------------
0086 
0087 class Q_DECL_HIDDEN DatabaseMigrationDialog::Private
0088 {
0089 public:
0090 
0091     explicit Private()
0092       : fromDatabaseSettingsWidget  (nullptr),
0093         toDatabaseSettingsWidget    (nullptr),
0094         migrateButton               (nullptr),
0095         cancelButton                (nullptr),
0096         overallStepTitle            (nullptr),
0097         progressBar                 (nullptr),
0098         progressBarSmallStep        (nullptr),
0099         buttons                     (nullptr),
0100         copyThread                  (nullptr)
0101     {
0102     }
0103 
0104     DatabaseSettingsWidget* fromDatabaseSettingsWidget;
0105     DatabaseSettingsWidget* toDatabaseSettingsWidget;
0106     QPushButton*            migrateButton;
0107     QPushButton*            cancelButton;
0108     QLabel*                 overallStepTitle;
0109     QProgressBar*           progressBar;
0110     QProgressBar*           progressBarSmallStep;
0111     QDialogButtonBox*       buttons;
0112     DatabaseCopyThread*     copyThread;
0113 };
0114 
0115 DatabaseMigrationDialog::DatabaseMigrationDialog(QWidget* const parent)
0116     : QDialog(parent),
0117       d      (new Private)
0118 {
0119     setupMainArea();
0120 }
0121 
0122 DatabaseMigrationDialog::~DatabaseMigrationDialog()
0123 {
0124     d->copyThread->wait();
0125     delete d;
0126 }
0127 
0128 void DatabaseMigrationDialog::setupMainArea()
0129 {
0130     d->buttons = new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Help, this);
0131     d->buttons->button(QDialogButtonBox::Close)->setDefault(true);
0132 
0133     d->copyThread                      = new DatabaseCopyThread(this);
0134     d->fromDatabaseSettingsWidget      = new DatabaseSettingsWidget(this);
0135     d->toDatabaseSettingsWidget        = new DatabaseSettingsWidget(this);
0136     d->migrateButton                   = new QPushButton(i18n("Migrate ->"), this);
0137     d->cancelButton                    = new QPushButton(i18n("Cancel"), this);
0138     d->cancelButton->setEnabled(false);
0139 
0140     QGroupBox* const progressBox       = new QGroupBox(i18n("Progress Information"), this);
0141     QGridLayout* const grid            = new QGridLayout(progressBox);
0142 
0143     d->progressBar                     = new QProgressBar(progressBox);
0144     d->progressBar->setTextVisible(true);
0145     d->progressBar->setRange(0, 22);
0146     d->progressBarSmallStep            = new QProgressBar(progressBox);
0147     d->progressBarSmallStep->setTextVisible(true);
0148 
0149     d->overallStepTitle                = new QLabel(i18n("Step Progress"), progressBox);
0150     QLabel* const overallSteps         = new QLabel(i18n("Overall Progress"), progressBox);
0151 
0152     grid->addWidget(d->overallStepTitle,     0, 0, 1, 1);
0153     grid->addWidget(new QLabel(this),        0, 1, 1, 1);
0154     grid->addWidget(overallSteps,            0, 2, 1, 1);
0155     grid->addWidget(d->progressBarSmallStep, 1, 0, 1, 1);
0156     grid->addWidget(new QLabel(this),        1, 1, 1, 1);
0157     grid->addWidget(d->progressBar,          1, 2, 1, 1);
0158     grid->setColumnStretch(0, 10);
0159     grid->setColumnStretch(1, 2);
0160     grid->setColumnStretch(2, 10);
0161 
0162     QWidget* const mainWidget = new QWidget;
0163     QGridLayout* const layout = new QGridLayout;
0164     mainWidget->setLayout(layout);
0165 
0166     layout->addWidget(d->fromDatabaseSettingsWidget, 0, 0, 4, 1);
0167     layout->addWidget(d->migrateButton,              1, 1);
0168     layout->addWidget(d->cancelButton,               2, 1);
0169     layout->addWidget(d->toDatabaseSettingsWidget,   0, 2, 4, 1);
0170     layout->addWidget(progressBox,                   4, 0, 1, 3);
0171 
0172     QVBoxLayout* const vbx = new QVBoxLayout(this);
0173     vbx->addWidget(mainWidget);
0174     vbx->addWidget(d->buttons);
0175     setLayout(vbx);
0176 
0177     dataInit();
0178 
0179     // --------------------------------------------------------------------------
0180 
0181     connect(d->buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()),
0182             this, SLOT(accept()));
0183 
0184     connect(d->buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()),
0185             this, SLOT(accept()));
0186 
0187     connect(d->migrateButton, SIGNAL(clicked()),
0188             this, SLOT(slotPerformCopy()));
0189 
0190     // connect signal handlers for copy d->copyThread
0191 
0192     connect(&(d->copyThread->m_copyManager), SIGNAL(finished(int,QString)),
0193             this, SLOT(slotHandleFinish(int,QString)));
0194 
0195     connect(&(d->copyThread->m_copyManager), SIGNAL(stepStarted(QString)),
0196             this, SLOT(slotHandleStepStarted(QString)));
0197 
0198     connect(&(d->copyThread->m_copyManager), SIGNAL(smallStepStarted(int,int)),
0199             this, SLOT(slotHandleSmallStepStarted(int,int)));
0200 
0201     connect(d->buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()),
0202             &(d->copyThread->m_copyManager), SLOT(stopProcessing()));
0203 
0204     connect(d->cancelButton, SIGNAL(clicked()),
0205             &(d->copyThread->m_copyManager), SLOT(stopProcessing()));
0206 }
0207 
0208 void DatabaseMigrationDialog::slotHelp()
0209 {
0210     openOnlineDocumentation(QLatin1String("setup_application"), QLatin1String("database_settings"), QLatin1String("database_migration"));
0211 }
0212 
0213 void DatabaseMigrationDialog::slotPerformCopy()
0214 {
0215     DbEngineParameters toDBParameters   = d->toDatabaseSettingsWidget->getDbEngineParameters();
0216     DbEngineParameters fromDBParameters = d->fromDatabaseSettingsWidget->getDbEngineParameters();
0217 
0218     if (fromDBParameters == toDBParameters)
0219     {
0220         QMessageBox::critical(this, qApp->applicationName(),
0221                               i18n("Database type or location must be different!"));
0222         return;
0223     }
0224 
0225     if (fromDBParameters.internalServer && toDBParameters.internalServer)
0226     {
0227         QMessageBox::critical(this, qApp->applicationName(),
0228                               i18n("Internal server can only be used once!"));
0229         return;
0230     }
0231 
0232     DbEngineParameters orgPrms = ApplicationSettings::instance()->getDbEngineParameters();
0233 
0234     if ((fromDBParameters.internalServer || toDBParameters.internalServer) && !orgPrms.internalServer)
0235     {
0236         QMessageBox::critical(this, qApp->applicationName(),
0237                               i18n("Internal server is not used and is not active!"));
0238         return;
0239     }
0240 
0241     d->copyThread->init(fromDBParameters, toDBParameters);
0242 
0243     slotLockInputFields();
0244     d->copyThread->start();
0245 }
0246 
0247 void DatabaseMigrationDialog::dataInit()
0248 {
0249     d->fromDatabaseSettingsWidget->setParametersFromSettings(ApplicationSettings::instance(), true);
0250     d->toDatabaseSettingsWidget->setParametersFromSettings(ApplicationSettings::instance(),   true);
0251 }
0252 
0253 void DatabaseMigrationDialog::slotUnlockInputFields()
0254 {
0255     d->fromDatabaseSettingsWidget->setEnabled(true);
0256     d->toDatabaseSettingsWidget->setEnabled(true);
0257     d->migrateButton->setEnabled(true);
0258     d->progressBar->setValue(0);
0259     d->progressBarSmallStep->setValue(0);
0260 
0261     d->cancelButton->setEnabled(false);
0262 }
0263 
0264 void DatabaseMigrationDialog::slotLockInputFields()
0265 {
0266     d->fromDatabaseSettingsWidget->setEnabled(false);
0267     d->toDatabaseSettingsWidget->setEnabled(false);
0268     d->migrateButton->setEnabled(false);
0269     d->cancelButton->setEnabled(true);
0270 }
0271 
0272 void DatabaseMigrationDialog::slotHandleFinish(int finishState, const QString& errorMsg)
0273 {
0274     switch (finishState)
0275     {
0276         case CoreDbCopyManager::failed:
0277             QMessageBox::critical(this, qApp->applicationName(), errorMsg);
0278             slotUnlockInputFields();
0279             break;
0280 
0281         case CoreDbCopyManager::success:
0282             QMessageBox::information(this, qApp->applicationName(), i18n("Database copied successfully."));
0283             slotUnlockInputFields();
0284             break;
0285 
0286         case CoreDbCopyManager::canceled:
0287             QMessageBox::information(this, qApp->applicationName(), i18n("Database conversion canceled."));
0288             slotUnlockInputFields();
0289             break;
0290     }
0291 }
0292 
0293 void DatabaseMigrationDialog::slotHandleStepStarted(const QString& stepName)
0294 {
0295     int progressBarValue = d->progressBar->value();
0296     d->overallStepTitle->setText(i18n("Step Progress (%1)", stepName));
0297     d->progressBar->setValue(++progressBarValue);
0298 }
0299 
0300 void DatabaseMigrationDialog::slotHandleSmallStepStarted(int currentValue, int maxValue)
0301 {
0302     d->progressBarSmallStep->setMaximum(maxValue);
0303     d->progressBarSmallStep->setValue(currentValue);
0304 }
0305 
0306 } // namespace Digikam
0307 
0308 #include "moc_dbmigrationdlg.cpp"