File indexing completed on 2025-01-05 03:54:00
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2007-03-23 0007 * Description : Core database image properties synchronizer 0008 * 0009 * SPDX-FileCopyrightText: 2007-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2009-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 "coredbwatch.h" 0017 0018 // Qt includes 0019 0020 #include <QMetaType> 0021 #include <QApplication> 0022 0023 #ifdef HAVE_DBUS 0024 # include <QtDBus> 0025 # include "coredbwatchadaptor.h" 0026 #endif 0027 0028 // Local includes 0029 0030 #include "collectionmanager.h" 0031 0032 namespace Digikam 0033 { 0034 0035 #ifdef HAVE_DBUS 0036 class DBusSignalListenerThread; 0037 #endif 0038 0039 class Q_DECL_HIDDEN CoreDbWatch::Private 0040 { 0041 public: 0042 0043 explicit Private() 0044 : mode (CoreDbWatch::DatabaseSlave) 0045 0046 #ifdef HAVE_DBUS 0047 0048 ,adaptor (nullptr) 0049 ,slaveThread(nullptr) 0050 0051 #endif 0052 0053 { 0054 } 0055 0056 #ifdef HAVE_DBUS 0057 0058 void connectWithDBus(const char* dbusSignal, QObject* obj, const char* slot, 0059 QDBusConnection connection = QDBusConnection::sessionBus()) 0060 { 0061 // connect to slave signals 0062 0063 connection.connect(QString(), QLatin1String("/ChangesetRelay"), 0064 QLatin1String("org.kde.digikam.DatabaseChangesetRelay"), 0065 QString::fromUtf8(dbusSignal), 0066 obj, slot); 0067 0068 // connect to master signals 0069 0070 connection.connect(QString(), QLatin1String("/ChangesetRelayForPeers"), 0071 QLatin1String("org.kde.digikam.DatabaseChangesetRelay"), 0072 QString::fromUtf8(dbusSignal), 0073 obj, slot); 0074 } 0075 0076 #endif 0077 0078 public: 0079 0080 0081 CoreDbWatch::DatabaseMode mode; 0082 QString databaseId; 0083 QString applicationId; 0084 0085 #ifdef HAVE_DBUS 0086 0087 CoreDbWatchAdaptor* adaptor; 0088 DBusSignalListenerThread* slaveThread; 0089 0090 #endif 0091 0092 }; 0093 0094 // --------------------------------------------------------------------------------- 0095 0096 #ifdef HAVE_DBUS 0097 0098 DBusSignalListenerThread::DBusSignalListenerThread(CoreDbWatch* const qq, CoreDbWatch::Private* const dd) 0099 : q(qq), 0100 d(dd) 0101 { 0102 start(); 0103 } 0104 0105 DBusSignalListenerThread::~DBusSignalListenerThread() 0106 { 0107 quit(); 0108 wait(); 0109 } 0110 0111 void DBusSignalListenerThread::run() 0112 { 0113 // We cannot use sessionBus() here but need to connect on our own 0114 0115 QDBusConnection threadConnection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, 0116 QString::fromUtf8("DigikamDatabaseSlaveConnection-%1") 0117 .arg(qApp->applicationPid())); 0118 0119 // DBus signals are received from within this thread and then sent with queued signals to the main thread 0120 0121 d->connectWithDBus("signalImageTagChangeDBus", q, 0122 SLOT(slotImageTagChangeDBus(QString,QString,Digikam::ImageTagChangeset)), 0123 threadConnection); 0124 0125 d->connectWithDBus("signalAlbumRootChangeDBus", q, 0126 SLOT(slotAlbumRootChangeDBus(QString,QString,Digikam::AlbumRootChangeset)), 0127 threadConnection); 0128 0129 // enter thread event loop 0130 0131 exec(); 0132 } 0133 0134 #endif 0135 0136 // --------------------------------------------------------------------------------- 0137 0138 CoreDbWatch::CoreDbWatch() 0139 : d(new Private) 0140 { 0141 } 0142 0143 CoreDbWatch::~CoreDbWatch() 0144 { 0145 0146 #ifdef HAVE_DBUS 0147 0148 delete d->adaptor; 0149 delete d->slaveThread; 0150 0151 #endif 0152 0153 delete d; 0154 } 0155 0156 void CoreDbWatch::initializeRemote(DatabaseMode mode) 0157 { 0158 d->mode = mode; 0159 0160 qRegisterMetaType<ImageChangeset>("ImageChangeset"); 0161 qRegisterMetaType<ImageTagChangeset>("ImageTagChangeset"); 0162 qRegisterMetaType<CollectionImageChangeset>("CollectionImageChangeset"); 0163 qRegisterMetaType<AlbumChangeset>("AlbumChangeset"); 0164 qRegisterMetaType<TagChangeset>("TagChangeset"); 0165 qRegisterMetaType<AlbumRootChangeset>("AlbumRootChangeset"); 0166 qRegisterMetaType<SearchChangeset>("SearchChangeset"); 0167 0168 #ifdef HAVE_DBUS 0169 0170 // NOTE: The literal for registration with DBus here will include namespace qualifier. 0171 // Therefore, the header file declaration for DBus signals and slots 0172 // must contain the full qualifier as well, so that moc picks them up. 0173 0174 qDBusRegisterMetaType<ImageChangeset>(); 0175 qDBusRegisterMetaType<ImageTagChangeset>(); 0176 qDBusRegisterMetaType<CollectionImageChangeset>(); 0177 qDBusRegisterMetaType<AlbumChangeset>(); 0178 qDBusRegisterMetaType<TagChangeset>(); 0179 qDBusRegisterMetaType<AlbumRootChangeset>(); 0180 qDBusRegisterMetaType<SearchChangeset>(); 0181 0182 qDBusRegisterMetaType<DatabaseFields::Set>(); 0183 qDBusRegisterMetaType< QList<qlonglong> >(); 0184 qDBusRegisterMetaType< QList<int> >(); 0185 0186 #endif 0187 0188 if (d->mode == DatabaseSlave) 0189 { 0190 0191 #ifdef HAVE_DBUS 0192 0193 d->adaptor = new CoreDbWatchAdaptor(this); 0194 0195 QDBusConnection::sessionBus().registerObject(QLatin1String("/ChangesetRelay"), this); 0196 0197 // Slave do not have an event loop which is needed for receiving DBus signals. 0198 // See also the event loop in CoreDbAccess::setParameters. 0199 0200 d->slaveThread = new DBusSignalListenerThread(this, d); 0201 0202 #endif 0203 0204 } 0205 else 0206 { 0207 0208 #ifdef HAVE_DBUS 0209 0210 d->adaptor = new CoreDbWatchAdaptor(this); 0211 0212 QDBusConnection::sessionBus().registerObject(QLatin1String("/ChangesetRelayForPeers"), this); 0213 0214 // connect DBus signals from slave or peer to our application 0215 0216 d->connectWithDBus("signalImageChangeDBus", this, 0217 SLOT(slotImageChangeDBus(QString,QString,Digikam::ImageChangeset))); 0218 0219 d->connectWithDBus("signalImageTagChangeDBus", this, 0220 SLOT(slotImageTagChangeDBus(QString,QString,Digikam::ImageTagChangeset))); 0221 0222 d->connectWithDBus("signalCollectionImageChangeDBus", this, 0223 SLOT(slotCollectionImageChangeDBus(QString,QString,Digikam::CollectionImageChangeset))); 0224 0225 d->connectWithDBus("signalAlbumChangeDBus", this, 0226 SLOT(slotAlbumChangeDBus(QString,QString,Digikam::AlbumChangeset))); 0227 0228 d->connectWithDBus("signalTagChangeDBus", this, 0229 SLOT(slotTagChangeDBus(QString,QString,Digikam::TagChangeset))); 0230 0231 d->connectWithDBus("signalAlbumRootChangeDBus", this, 0232 SLOT(slotAlbumRootChangeDBus(QString,QString,Digikam::AlbumRootChangeset))); 0233 0234 d->connectWithDBus("signalSearchChangeDBus", this, 0235 SLOT(slotSearchChangeDBus(QString,QString,Digikam::SearchChangeset))); 0236 #endif 0237 0238 } 0239 0240 // Do this as a favor for CollectionManager, we may not exist at time of its creation 0241 connect(this, SIGNAL(albumRootChange(AlbumRootChangeset)), 0242 CollectionManager::instance(), SLOT(slotAlbumRootChange(AlbumRootChangeset))); 0243 } 0244 0245 void CoreDbWatch::doAnyProcessing() 0246 { 0247 0248 #ifdef HAVE_DBUS 0249 0250 // In a slave we have no event loop. 0251 // This method is called when a slave begins a new operation 0252 // (it calls CoreDbAccess::setParameters then). 0253 // Allow here queued signals to proceed that may be caused by CoreDbWatch signals 0254 // that were send from within the DBus listener thread (see above). 0255 0256 QEventLoop loop; 0257 loop.processEvents(); 0258 0259 #endif 0260 0261 } 0262 0263 void CoreDbWatch::setDatabaseIdentifier(const QString& identifier) 0264 { 0265 d->databaseId = identifier; 0266 } 0267 0268 void CoreDbWatch::setApplicationIdentifier(const QString& identifier) 0269 { 0270 d->applicationId = identifier; 0271 } 0272 0273 void CoreDbWatch::sendDatabaseChanged() 0274 { 0275 0276 #ifdef HAVE_DBUS 0277 0278 // Note: This is not dispatched by DBus! 0279 0280 #endif 0281 0282 Q_EMIT databaseChanged(); 0283 } 0284 0285 // --- methods to dispatch changes from database to listeners (local and remote) --- 0286 0287 void CoreDbWatch::sendImageChange(const ImageChangeset& cset) 0288 { 0289 // send local signal 0290 0291 Q_EMIT imageChange(cset); 0292 0293 #ifdef HAVE_DBUS 0294 0295 // send DBUS signal 0296 0297 Q_EMIT signalImageChangeDBus(d->databaseId, d->applicationId, cset); 0298 0299 #endif 0300 0301 } 0302 0303 void CoreDbWatch::sendImageTagChange(const ImageTagChangeset& cset) 0304 { 0305 Q_EMIT imageTagChange(cset); 0306 0307 #ifdef HAVE_DBUS 0308 0309 Q_EMIT signalImageTagChangeDBus(d->databaseId, d->applicationId, cset); 0310 0311 #endif 0312 0313 } 0314 0315 void CoreDbWatch::sendCollectionImageChange(const CollectionImageChangeset& cset) 0316 { 0317 Q_EMIT collectionImageChange(cset); 0318 0319 #ifdef HAVE_DBUS 0320 0321 Q_EMIT signalCollectionImageChangeDBus(d->databaseId, d->applicationId, cset); 0322 0323 #endif 0324 0325 } 0326 0327 void CoreDbWatch::sendAlbumChange(const AlbumChangeset& cset) 0328 { 0329 Q_EMIT albumChange(cset); 0330 0331 #ifdef HAVE_DBUS 0332 0333 Q_EMIT signalAlbumChangeDBus(d->databaseId, d->applicationId, cset); 0334 0335 #endif 0336 0337 } 0338 0339 void CoreDbWatch::sendTagChange(const TagChangeset& cset) 0340 { 0341 Q_EMIT tagChange(cset); 0342 0343 #ifdef HAVE_DBUS 0344 0345 Q_EMIT signalTagChangeDBus(d->databaseId, d->applicationId, cset); 0346 0347 #endif 0348 0349 } 0350 0351 void CoreDbWatch::sendAlbumRootChange(const AlbumRootChangeset& cset) 0352 { 0353 Q_EMIT albumRootChange(cset); 0354 0355 #ifdef HAVE_DBUS 0356 0357 Q_EMIT signalAlbumRootChangeDBus(d->databaseId, d->applicationId, cset); 0358 0359 #endif 0360 0361 } 0362 0363 void CoreDbWatch::sendSearchChange(const SearchChangeset& cset) 0364 { 0365 Q_EMIT searchChange(cset); 0366 0367 #ifdef HAVE_DBUS 0368 0369 Q_EMIT signalSearchChangeDBus(d->databaseId, d->applicationId, cset); 0370 0371 #endif 0372 0373 } 0374 0375 #ifdef HAVE_DBUS 0376 0377 // --- methods to dispatch from slave or peer to local listeners --- 0378 0379 void CoreDbWatch::slotImageChangeDBus(const QString& databaseIdentifier, 0380 const QString& applicationIdentifier, 0381 const ImageChangeset& changeset) 0382 { 0383 if ((applicationIdentifier != d->applicationId) && 0384 (databaseIdentifier == d->databaseId)) 0385 { 0386 Q_EMIT imageChange(changeset); 0387 } 0388 } 0389 0390 void CoreDbWatch::slotImageTagChangeDBus(const QString& databaseIdentifier, 0391 const QString& applicationIdentifier, 0392 const ImageTagChangeset& changeset) 0393 { 0394 if ((applicationIdentifier != d->applicationId) && 0395 (databaseIdentifier == d->databaseId)) 0396 { 0397 Q_EMIT imageTagChange(changeset); 0398 } 0399 } 0400 0401 void CoreDbWatch::slotCollectionImageChangeDBus(const QString& databaseIdentifier, 0402 const QString& applicationIdentifier, 0403 const CollectionImageChangeset& changeset) 0404 { 0405 if ((applicationIdentifier != d->applicationId) && 0406 (databaseIdentifier == d->databaseId)) 0407 { 0408 Q_EMIT collectionImageChange(changeset); 0409 } 0410 } 0411 0412 void CoreDbWatch::slotAlbumChangeDBus(const QString& databaseIdentifier, 0413 const QString& applicationIdentifier, 0414 const AlbumChangeset& changeset) 0415 { 0416 if ((applicationIdentifier != d->applicationId) && 0417 (databaseIdentifier == d->databaseId)) 0418 { 0419 Q_EMIT albumChange(changeset); 0420 } 0421 } 0422 0423 void CoreDbWatch::slotTagChangeDBus(const QString& databaseIdentifier, 0424 const QString& applicationIdentifier, 0425 const TagChangeset& changeset) 0426 { 0427 if ((applicationIdentifier != d->applicationId) && 0428 (databaseIdentifier == d->databaseId)) 0429 { 0430 Q_EMIT tagChange(changeset); 0431 } 0432 } 0433 0434 void CoreDbWatch::slotAlbumRootChangeDBus(const QString& databaseIdentifier, 0435 const QString& applicationIdentifier, 0436 const AlbumRootChangeset& changeset) 0437 { 0438 if ((applicationIdentifier != d->applicationId) && 0439 (databaseIdentifier == d->databaseId)) 0440 { 0441 Q_EMIT albumRootChange(changeset); 0442 } 0443 } 0444 0445 void CoreDbWatch::slotSearchChangeDBus(const QString& databaseIdentifier, 0446 const QString& applicationIdentifier, 0447 const SearchChangeset& changeset) 0448 { 0449 if ((applicationIdentifier != d->applicationId) && 0450 (databaseIdentifier == d->databaseId)) 0451 { 0452 Q_EMIT searchChange(changeset); 0453 } 0454 } 0455 0456 #endif 0457 0458 } // namespace Digikam 0459 0460 #include "moc_coredbwatch.cpp"