File indexing completed on 2024-05-12 16:40:16
0001 /* This file is part of the KDE project 0002 Daniel Molkentin <molkentin@kde.org> 0003 Joseph Wenninger <jowenn@kde.org> 0004 Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this program; see the file COPYING. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "migratemanager.h" 0023 #include "migratemanager_p.h" 0024 #include "keximigrate.h" 0025 #include "KexiMigratePluginMetaData.h" 0026 #include <core/KexiMainWindowIface.h> 0027 #include <KexiJsonTrader.h> 0028 #include <config-kexi.h> 0029 0030 #include <KDbVersionInfo> 0031 0032 #include <KLocalizedString> 0033 0034 #include <QDebug> 0035 #include <QApplication> 0036 0037 #include <assert.h> 0038 0039 #ifdef KEXI_MIGRATEMANAGER_DEBUG 0040 #define KexiMigrateManagerDebug qDebug() 0041 #else 0042 #define KexiMigrateManagerDebug while (0) qDebug() 0043 #endif 0044 0045 using namespace KexiMigration; 0046 0047 Q_GLOBAL_STATIC(MigrateManagerInternal, s_self) 0048 Q_GLOBAL_STATIC_WITH_ARGS(KexiJsonTrader, KexiMigrateTrader_instance, (KEXI_BASE_PATH "/migrate")) 0049 0050 0051 MigrateManagerInternal::MigrateManagerInternal() 0052 : m_lookupDriversNeeded(true) 0053 { 0054 } 0055 0056 MigrateManagerInternal::~MigrateManagerInternal() 0057 { 0058 KexiMigrateManagerDebug; 0059 clear(); 0060 KexiMigrateManagerDebug << "ok"; 0061 } 0062 0063 void MigrateManagerInternal::clear() 0064 { 0065 KexiMigrateManagerDebug << "Clearing drivers..."; 0066 qDeleteAll(m_drivers); 0067 m_drivers.clear(); 0068 qDeleteAll(m_driversMetaData); 0069 m_driversMetaData.clear(); 0070 } 0071 0072 void MigrateManagerInternal::slotAppQuits() 0073 { 0074 if (qApp && !qApp->topLevelWidgets().isEmpty() 0075 && qApp->topLevelWidgets().first()->isVisible()) { 0076 return; //what a hack! - we give up when app is still there 0077 } 0078 clear(); 0079 } 0080 0081 bool MigrateManagerInternal::lookupDrivers() 0082 { 0083 if (!m_lookupDriversNeeded) 0084 return true; 0085 0086 if (qApp) { 0087 connect(qApp, &QApplication::aboutToQuit, this, &MigrateManagerInternal::slotAppQuits); 0088 } 0089 0090 m_lookupDriversNeeded = false; 0091 clearResult(); 0092 0093 QList<QPluginLoader*> offers 0094 = KexiMigrateTrader_instance->query(QLatin1String("Kexi/MigrationDriver")); 0095 const QString expectedVersion = QString::fromLatin1("%1.%2") 0096 .arg(KexiMigration::version().major()).arg(KexiMigration::version().minor()); 0097 for(const QPluginLoader *loader : offers) { 0098 QScopedPointer<KexiMigratePluginMetaData> metaData(new KexiMigratePluginMetaData(*loader)); 0099 if (m_driversMetaData.contains(metaData->id())) { 0100 qWarning() << "Migration driver with ID" << metaData->id() << "already found at" 0101 << m_driversMetaData.value(metaData->id())->fileName() 0102 << "-- skipping another at" << metaData->fileName(); 0103 continue; 0104 } 0105 //! @todo Similar version check could be merged with KDbDriverManager 0106 if (metaData->version() != expectedVersion) { 0107 qWarning() << QString("Migration driver '%1' (%2) has version '%3' but " 0108 "KexiMigration library requires version '%4'\n" 0109 " -- skipping this driver!") 0110 .arg(metaData->id()).arg(metaData->fileName()) 0111 .arg(metaData->version()) 0112 .arg(expectedVersion); 0113 m_possibleProblems += QString("Migration driver \"%1\" (%2) has version \"%3\" " 0114 "but required version is \"%4\"") 0115 .arg(metaData->id()).arg(metaData->fileName()) 0116 .arg(metaData->version()) 0117 .arg(expectedVersion); 0118 continue; 0119 } 0120 foreach (const QString& mimeType, metaData->mimeTypes()) { 0121 m_metadata_by_mimetype.insertMulti(mimeType, metaData.data()); 0122 } 0123 foreach (const QString& sourceDriverId, metaData->supportedSourceDrivers()) { 0124 m_metadataBySourceDrivers.insertMulti(sourceDriverId, metaData.data()); 0125 } 0126 m_driversMetaData.insert(metaData->id(), metaData.data()); 0127 KexiMigrateManagerDebug << "registered driver" << metaData->id() << '(' << metaData->fileName() << ")"; 0128 metaData.take(); 0129 } 0130 0131 if (m_driversMetaData.isEmpty()) { 0132 m_result = KDbResult(ERR_DRIVERMANAGER, xi18n("Could not find any migration database drivers.")); 0133 return false; 0134 } 0135 return true; 0136 } 0137 0138 QStringList MigrateManagerInternal::driverIds() 0139 { 0140 if (!lookupDrivers()) { 0141 return QStringList(); 0142 } 0143 if (m_driversMetaData.isEmpty() && result().isError()) { 0144 return QStringList(); 0145 } 0146 return m_driversMetaData.keys(); 0147 } 0148 0149 const KexiMigratePluginMetaData* MigrateManagerInternal::driverMetaData(const QString &id) 0150 { 0151 if (!lookupDrivers()) { 0152 return 0; 0153 } 0154 const KexiMigratePluginMetaData *metaData = m_driversMetaData.value(id.toLower()); 0155 if (!metaData || m_result.isError()) { 0156 m_result = KDbResult(ERR_DRIVERMANAGER, 0157 tr("Could not find migration driver \"%1\".").arg(id)); 0158 } 0159 return metaData; 0160 } 0161 0162 QStringList MigrateManagerInternal::driverIdsForMimeType(const QString &mimeType) 0163 { 0164 if (!lookupDrivers()) { 0165 return QStringList(); 0166 } 0167 const QList<KexiMigratePluginMetaData*> metaDatas(m_metadata_by_mimetype.values(mimeType.toLower())); 0168 QStringList result; 0169 for (const KexiMigratePluginMetaData* metaData : metaDatas) { 0170 result.append(metaData->id()); 0171 } 0172 return result; 0173 } 0174 0175 QStringList MigrateManagerInternal::driverIdsForSourceDriver(const QString &sourceDriverId) 0176 { 0177 if (!lookupDrivers()) { 0178 return QStringList(); 0179 } 0180 QStringList result; 0181 for (const KexiMigratePluginMetaData* metaData : m_metadataBySourceDrivers.values(sourceDriverId.toLower())) { 0182 result.append(metaData->id()); 0183 } 0184 return result; 0185 } 0186 0187 KexiMigrate* MigrateManagerInternal::driver(const QString& id) 0188 { 0189 if (!lookupDrivers()) { 0190 qWarning() << "lookupDrivers failed"; 0191 return 0; 0192 } 0193 0194 clearResult(); 0195 KexiMigrateManagerDebug << "loading" << id; 0196 0197 KexiMigrate *driver = m_drivers.value(id.toLatin1().toLower()); 0198 if (driver) { 0199 return driver; //cached 0200 } 0201 0202 if (!m_driversMetaData.contains(id.toLower())) { 0203 m_result = KDbResult(ERR_OBJECT_NOT_FOUND, 0204 tr("Could not find migration driver \"%1\".").arg(id)); 0205 return 0; 0206 } 0207 0208 const KexiMigratePluginMetaData *metaData = m_driversMetaData.value(id.toLower()); 0209 KPluginFactory *factory = qobject_cast<KPluginFactory*>(metaData->instantiate()); 0210 if (!factory) { 0211 m_result = KDbResult(ERR_CANNOT_LOAD_OBJECT, 0212 tr("Could not load migration driver's plugin file \"%1\".") 0213 .arg(metaData->fileName())); 0214 QPluginLoader loader(metaData->fileName()); // use this to get the message 0215 (void)loader.load(); 0216 m_result.setServerMessage(loader.errorString()); 0217 qWarning() << m_result.message() << m_result.serverMessage(); 0218 return 0; 0219 } 0220 driver = factory->create<KexiMigrate>(); 0221 if (!driver) { 0222 m_result = KDbResult(ERR_CANNOT_LOAD_OBJECT, 0223 tr("Could not open migration driver \"%1\" from plugin file \"%2\".") 0224 .arg(metaData->id()) 0225 .arg(metaData->fileName())); 0226 qWarning() << m_result.message(); 0227 return 0; 0228 } 0229 driver->setMetaData(metaData); 0230 m_drivers.insert(id.toLower(), driver); 0231 return driver; 0232 } 0233 0234 QStringList MigrateManagerInternal::possibleProblemsMessage() const 0235 { 0236 return m_possibleProblems; 0237 } 0238 0239 QStringList MigrateManagerInternal::supportedFileMimeTypes() 0240 { 0241 if (!lookupDrivers()) { 0242 qWarning() << "lookupDrivers failed"; 0243 return QStringList(); 0244 } 0245 return m_metadata_by_mimetype.uniqueKeys(); 0246 } 0247 0248 QStringList MigrateManagerInternal::supportedSourceDriverIds() 0249 { 0250 if (!lookupDrivers()) { 0251 qWarning() << "lookupDrivers failed"; 0252 return QStringList(); 0253 } 0254 return m_metadataBySourceDrivers.uniqueKeys(); 0255 } 0256 0257 // --------------------------- 0258 // --- DriverManager impl. --- 0259 // --------------------------- 0260 0261 MigrateManager::MigrateManager() 0262 : QObject(0) 0263 { 0264 setObjectName("KexiMigrate::MigrateManager"); 0265 } 0266 0267 MigrateManager::~MigrateManager() 0268 { 0269 KexiMigrateManagerDebug; 0270 } 0271 0272 QStringList MigrateManager::driverIdsForMimeType(const QString &mimeType) 0273 { 0274 return s_self->driverIdsForMimeType(mimeType); 0275 } 0276 0277 QStringList MigrateManager::driverIdsForSourceDriver(const QString &sourceDriverId) 0278 { 0279 return s_self->driverIdsForSourceDriver(sourceDriverId); 0280 } 0281 0282 KexiMigrate* MigrateManager::driver(const QString &id) 0283 { 0284 return s_self->driver(id); 0285 } 0286 0287 QString MigrateManager::possibleProblemsMessage() const 0288 { 0289 if (s_self->possibleProblemsMessage().isEmpty()) 0290 return QString(); 0291 QString str = "<ul>"; 0292 for(const QString &message : s_self->possibleProblemsMessage()) { 0293 str += (QString::fromLatin1("<li>") + message + QString::fromLatin1("</li>")); 0294 } 0295 str += "</ul>"; 0296 return str; 0297 } 0298 0299 QStringList MigrateManager::supportedFileMimeTypes() 0300 { 0301 return s_self->supportedFileMimeTypes(); 0302 } 0303 0304 QStringList MigrateManager::supportedSourceDriverIds() 0305 { 0306 return s_self->supportedSourceDriverIds(); 0307 } 0308 0309 KDbResult MigrateManager::result() const 0310 { 0311 return s_self->result(); 0312 } 0313 0314 const KDbResultable* MigrateManager::resultable() const 0315 { 0316 return s_self; 0317 }