File indexing completed on 2025-01-05 03:58:23
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2016-09-29 0007 * Description : migration page from digikam4 0008 * 0009 * SPDX-FileCopyrightText: 2016 by Antonio Larrosa <alarrosa at suse dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "migratefromdigikam4page.h" 0016 0017 // Qt includes 0018 0019 #include <QLabel> 0020 #include <QRadioButton> 0021 #include <QButtonGroup> 0022 #include <QDir> 0023 #include <QFileInfo> 0024 #include <QFile> 0025 #include <QStringList> 0026 #include <QVBoxLayout> 0027 #include <QApplication> 0028 #include <QStyle> 0029 #include <QSqlDatabase> 0030 #include <QSqlQuery> 0031 #include <QSqlError> 0032 #include <QStandardPaths> 0033 0034 // KDE includes 0035 0036 #include <klocalizedstring.h> 0037 #include <kdelibs4configmigrator.h> 0038 #include <kdelibs4migration.h> 0039 0040 // Local includes 0041 0042 #include "digikam_debug.h" 0043 #include "dbengineparameters.h" 0044 #include "dlayoutbox.h" 0045 0046 namespace Digikam 0047 { 0048 0049 class Q_DECL_HIDDEN MigrateFromDigikam4Page::Private 0050 { 0051 public: 0052 0053 explicit Private() 0054 : migrateBehavior(nullptr), 0055 migrate (nullptr), 0056 createnew (nullptr) 0057 { 0058 } 0059 0060 QButtonGroup* migrateBehavior; 0061 QRadioButton* migrate; 0062 QRadioButton* createnew; 0063 }; 0064 0065 MigrateFromDigikam4Page::MigrateFromDigikam4Page(QWizard* const dlg) 0066 : DWizardPage(dlg, i18n("Migration from digiKam 4")), 0067 d (new Private) 0068 { 0069 const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0070 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0071 DVBox* const vbox = new DVBox(this); 0072 QLabel* const title = new QLabel(vbox); 0073 title->setWordWrap(true); 0074 title->setText(i18n("<qt>" 0075 "<p><h1><b>Migrate configuration and metadata from digiKam 4</b></h1></p>" 0076 "<p>You can choose here if you want to use the configuration and albums from digiKam 4 in new digiKam. " 0077 "Please note the following warnings:</p>" 0078 "<p>Migration is done <b>at your own risk</b>. digiKam developers " 0079 "do not recommend it and do not support it. On the other hand, creating " 0080 "a new configuration might result in loss of tags and other metadata that was not embedded inside " 0081 "the pictures and was only available in digiKam 4's database.</p>" 0082 "<p>In either case you are recommended to backup " 0083 "the configuration files and databases before proceeding.</p>" 0084 "</qt>")); 0085 0086 QWidget* const btns = new QWidget(vbox); 0087 QVBoxLayout* const vlay = new QVBoxLayout(btns); 0088 0089 d->migrateBehavior = new QButtonGroup(btns); 0090 d->migrate = new QRadioButton(btns); 0091 d->migrate->setText(i18n("Migrate configuration from digiKam 4")); 0092 d->migrate->setChecked(true); 0093 0094 connect(d->migrate, SIGNAL(toggled(bool)), 0095 this, SLOT(migrationToggled(bool))); 0096 0097 d->migrateBehavior->addButton(d->migrate); 0098 0099 d->createnew = new QRadioButton(btns); 0100 d->createnew->setText(i18n("Create a new configuration")); 0101 d->migrateBehavior->addButton(d->createnew); 0102 0103 vlay->addWidget(d->migrate); 0104 vlay->addWidget(d->createnew); 0105 vlay->setContentsMargins(spacing, spacing, spacing, spacing); 0106 vlay->setSpacing(spacing); 0107 0108 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) 0109 0110 connect(d->migrateBehavior, SIGNAL(idClicked(int)), 0111 this, SIGNAL(completeChanged())); 0112 0113 #else 0114 0115 connect(d->migrateBehavior, SIGNAL(buttonClicked(int)), 0116 this, SIGNAL(completeChanged())); 0117 0118 #endif 0119 0120 setPageWidget(vbox); 0121 } 0122 0123 MigrateFromDigikam4Page::~MigrateFromDigikam4Page() 0124 { 0125 delete d; 0126 } 0127 0128 void MigrateFromDigikam4Page::doMigration() 0129 { 0130 // Migrate digiKam config files from $KDEHOME/share/config/ 0131 0132 Kdelibs4ConfigMigrator migrator(QLatin1String("digikam")); 0133 QStringList configFiles; 0134 configFiles << QLatin1String("digikamrc") 0135 << QLatin1String("digikam_tagsmanagerrc") 0136 << QLatin1String("showfotorc"); 0137 migrator.setConfigFiles(configFiles); 0138 migrator.migrate(); 0139 0140 // Migrate digiKam config files from $KDEHOME/share/apps/digikam/ 0141 0142 Kdelibs4Migration migration; 0143 QString oldappdatadir = migration.locateLocal("data", QLatin1String("digikam")); 0144 QStringList oldAppFiles = QDir(oldappdatadir).entryList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot); 0145 0146 Q_FOREACH (const QString& configFileName, oldAppFiles) 0147 { 0148 const QString newConfigLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + 0149 QLatin1Char('/') + configFileName + QLatin1Char('5'); 0150 0151 if (QFile(newConfigLocation).exists()) 0152 { 0153 qCDebug(DIGIKAM_GENERAL_LOG) << newConfigLocation << " already exists. Skipping"; 0154 continue; 0155 } 0156 0157 QFileInfo fileInfo(newConfigLocation); 0158 QDir().mkpath(fileInfo.absolutePath()); 0159 0160 const QString oldConfigFile = oldappdatadir + QLatin1Char('/') + configFileName; 0161 0162 if (!oldConfigFile.isEmpty()) 0163 { 0164 if (QFile(oldConfigFile).copy(newConfigLocation)) 0165 { 0166 qCDebug(DIGIKAM_GENERAL_LOG) << "Config file" << oldConfigFile << "was migrated to" << newConfigLocation; 0167 } 0168 } 0169 } 0170 0171 // Migrate $KDEHOME/share/apps/kipi/geobookmarks.xml to ./.local/share/digikam/geobookmarks.xml 0172 0173 QString oldGeobookmarksFile = migration.locateLocal("data", QLatin1String("kipi/geobookmarks.xml")); 0174 const QString newGeobookmarksFile = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + 0175 QLatin1String("/geobookmarks.xml"); 0176 0177 if (QFile(newGeobookmarksFile).exists()) 0178 { 0179 qCDebug(DIGIKAM_GENERAL_LOG) << newGeobookmarksFile << " already exists. Skipping"; 0180 } 0181 else 0182 { 0183 QFileInfo fileInfo(newGeobookmarksFile); 0184 QDir().mkpath(fileInfo.absolutePath()); 0185 0186 if (!oldGeobookmarksFile.isEmpty()) 0187 { 0188 if (QFile(oldGeobookmarksFile).copy(newGeobookmarksFile)) 0189 { 0190 qCDebug(DIGIKAM_GENERAL_LOG) << "Config file" << oldGeobookmarksFile << "was migrated to" << newGeobookmarksFile; 0191 } 0192 } 0193 } 0194 0195 // Fix albumroot identifier since digiKam 5 doesn't interpret correctly 0196 // values like volumeid:?path=%2Fhome%2Fantonio%2FPictures and it needs 0197 // to be url-decoded. 0198 0199 DbEngineParameters parameters = DbEngineParameters::parametersFromConfig(); 0200 QSqlDatabase databaseHandler = QSqlDatabase::addDatabase(parameters.databaseType, QLatin1String("digikam4migration")); 0201 0202 databaseHandler.setHostName(parameters.hostName); 0203 databaseHandler.setPort(parameters.port); 0204 databaseHandler.setDatabaseName(parameters.databaseNameCore); 0205 databaseHandler.setUserName(parameters.userName); 0206 databaseHandler.setPassword(parameters.password); 0207 databaseHandler.setConnectOptions(parameters.connectOptions); 0208 0209 if (!databaseHandler.open()) 0210 { 0211 qCDebug(DIGIKAM_GENERAL_LOG) << "Cannot open database:" << databaseHandler.lastError().text(); 0212 return; 0213 } 0214 0215 QSqlQuery query(QLatin1String("SELECT id,identifier FROM albumroots"), databaseHandler); 0216 0217 while (query.next()) 0218 { 0219 int id = query.value(0).toInt(); 0220 QString identifier = query.value(1).toString(); 0221 0222 if (identifier.startsWith(QLatin1String("volumeid:?path=%2F"))) 0223 { 0224 QUrl url(identifier); 0225 url.setQuery(url.query(QUrl::FullyDecoded), QUrl::DecodedMode); 0226 qCDebug(DIGIKAM_GENERAL_LOG) << "Updating albumroot " << id << " from " << identifier << " to " << url.toString(); 0227 QSqlQuery uquery(QLatin1String("UPDATE albumroots SET identifier=? WHERE id=?"), databaseHandler); 0228 uquery.bindValue(0, url.toString()); 0229 uquery.bindValue(1, id); 0230 bool ret = uquery.exec(); 0231 0232 if (!ret) 0233 { 0234 qCDebug(DIGIKAM_GENERAL_LOG) << "Cannot query database for migration:" << databaseHandler.lastError().text(); 0235 } 0236 } 0237 } 0238 0239 databaseHandler.close(); 0240 0241 qCDebug(DIGIKAM_GENERAL_LOG) << "Migration finished"; 0242 } 0243 0244 bool MigrateFromDigikam4Page::isMigrationChecked() const 0245 { 0246 return d->migrate->isChecked(); 0247 } 0248 0249 void MigrateFromDigikam4Page::migrationToggled(bool b) 0250 { 0251 setFinalPage(b); 0252 } 0253 0254 int MigrateFromDigikam4Page::nextId() const 0255 { 0256 if (d->migrate->isChecked()) 0257 { 0258 return (-1); 0259 } 0260 else 0261 { 0262 return QWizardPage::nextId(); 0263 } 0264 } 0265 0266 bool MigrateFromDigikam4Page::checkForMigration() 0267 { 0268 0269 #ifdef Q_OS_LINUX 0270 0271 ::Kdelibs4Migration migration; 0272 0273 // If there's a digikamrc file in $KDEHOME/share/config, 0274 // then we create the migration page in the wizard 0275 0276 return (!migration.locateLocal("config", QLatin1String("digikamrc")).isEmpty()); 0277 0278 #endif 0279 0280 return false; 0281 } 0282 0283 } // namespace Digikam 0284 0285 #include "moc_migratefromdigikam4page.cpp"