File indexing completed on 2024-11-24 04:18:33
0001 #include "server.h" 0002 0003 #include <QGuiApplication> 0004 #include <QQuickWindow> 0005 #include <QQmlApplicationEngine> 0006 0007 #include <MauiKit3/FileBrowsing/fmstatic.h> 0008 0009 #if (defined Q_OS_LINUX || defined Q_OS_FREEBSD) && !defined Q_OS_ANDROID 0010 #include "notainterface.h" 0011 #include "notaadaptor.h" 0012 0013 QVector<QPair<QSharedPointer<OrgKdeNotaActionsInterface>, QStringList>> AppInstance::appInstances(const QString& preferredService) 0014 { 0015 QVector<QPair<QSharedPointer<OrgKdeNotaActionsInterface>, QStringList>> dolphinInterfaces; 0016 0017 if (!preferredService.isEmpty()) 0018 { 0019 QSharedPointer<OrgKdeNotaActionsInterface> preferredInterface( 0020 new OrgKdeNotaActionsInterface(preferredService, 0021 QStringLiteral("/Actions"), 0022 QDBusConnection::sessionBus())); 0023 0024 qDebug() << "IS PREFRFRED INTERFACE VALID?" << preferredInterface->isValid() << preferredInterface->lastError().message(); 0025 if (preferredInterface->isValid() && !preferredInterface->lastError().isValid()) { 0026 dolphinInterfaces.append(qMakePair(preferredInterface, QStringList())); 0027 } 0028 } 0029 0030 // Look for dolphin instances among all available dbus services. 0031 QDBusConnectionInterface *sessionInterface = QDBusConnection::sessionBus().interface(); 0032 const QStringList dbusServices = sessionInterface ? sessionInterface->registeredServiceNames().value() : QStringList(); 0033 // Don't match the service without trailing "-" (unique instance) 0034 const QString pattern = QStringLiteral("org.kde.nota-"); 0035 0036 // Don't match the pid without leading "-" 0037 const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid()); 0038 0039 for (const QString& service : dbusServices) 0040 { 0041 if (service.startsWith(pattern) && !service.endsWith(myPid)) 0042 { 0043 qDebug() << "EXISTING INTANCES" << service; 0044 0045 // Check if instance can handle our URLs 0046 QSharedPointer<OrgKdeNotaActionsInterface> interface( 0047 new OrgKdeNotaActionsInterface(service, 0048 QStringLiteral("/Actions"), 0049 QDBusConnection::sessionBus())); 0050 if (interface->isValid() && !interface->lastError().isValid()) 0051 { 0052 dolphinInterfaces.append(qMakePair(interface, QStringList())); 0053 } 0054 } 0055 } 0056 0057 return dolphinInterfaces; 0058 } 0059 0060 bool AppInstance::attachToExistingInstance(const QList<QUrl>& inputUrls, bool splitView, const QString& preferredService) 0061 { 0062 bool attached = false; 0063 0064 if (inputUrls.isEmpty()) 0065 { 0066 return false; 0067 } 0068 0069 auto dolphinInterfaces = appInstances(preferredService); 0070 if (dolphinInterfaces.isEmpty()) 0071 { 0072 return false; 0073 } 0074 0075 QStringList newUrls; 0076 0077 // check to see if any instances already have any of the given URLs open 0078 const auto urls = QUrl::toStringList(inputUrls); 0079 for (const QString& url : urls) 0080 { 0081 bool urlFound = false; 0082 0083 for (auto& interface: dolphinInterfaces) 0084 { 0085 auto isUrlOpenReply = interface.first->isUrlOpen(url); 0086 isUrlOpenReply.waitForFinished(); 0087 0088 if (!isUrlOpenReply.isError() && isUrlOpenReply.value()) 0089 { 0090 interface.second.append(url); 0091 urlFound = true; 0092 break; 0093 } 0094 } 0095 0096 if (!urlFound) 0097 { 0098 newUrls.append(url); 0099 } 0100 } 0101 0102 if(newUrls.isEmpty()) 0103 { 0104 auto interface = dolphinInterfaces.first(); 0105 auto reply = interface.first->focusFile(urls.first()); 0106 reply.waitForFinished(); 0107 0108 if (!reply.isError()) 0109 { 0110 interface.first->activateWindow(); 0111 } 0112 0113 return true; 0114 } 0115 0116 for (const auto& interface: qAsConst(dolphinInterfaces)) 0117 { 0118 auto reply = interface.first->openFiles(newUrls, splitView); 0119 reply.waitForFinished(); 0120 0121 if (!reply.isError()) 0122 { 0123 interface.first->activateWindow(); 0124 attached = true; 0125 break; 0126 } 0127 } 0128 0129 return attached; 0130 } 0131 0132 bool AppInstance::registerService() 0133 { 0134 QDBusConnectionInterface *iface = QDBusConnection::sessionBus().interface(); 0135 0136 auto registration = iface->registerService(QStringLiteral("org.kde.nota-%1").arg(QCoreApplication::applicationPid()), 0137 QDBusConnectionInterface::ReplaceExistingService, 0138 QDBusConnectionInterface::DontAllowReplacement); 0139 0140 if (!registration.isValid()) 0141 { 0142 qWarning("2 Failed to register D-Bus service \"%s\" on session bus: \"%s\"", 0143 qPrintable("org.kde.nota"), 0144 qPrintable(registration.error().message())); 0145 return false; 0146 } 0147 0148 return true; 0149 } 0150 0151 #endif 0152 0153 0154 Server::Server(QObject *parent) : QObject(parent) 0155 , m_qmlObject(nullptr) 0156 { 0157 #if (defined Q_OS_LINUX || defined Q_OS_FREEBSD) && !defined Q_OS_ANDROID 0158 new ActionsAdaptor(this); 0159 if(!QDBusConnection::sessionBus().registerObject(QStringLiteral("/Actions"), this)) 0160 { 0161 qDebug() << "FAILED TO REGISTER BACKGROUND DBUS OBJECT"; 0162 return; 0163 } 0164 #endif 0165 } 0166 0167 void Server::setQmlObject(QObject *object) 0168 { 0169 if(!m_qmlObject) 0170 { 0171 m_qmlObject = object; 0172 } 0173 } 0174 0175 void Server::activateWindow() 0176 { 0177 if(m_qmlObject) 0178 { 0179 qDebug() << "ACTIVET WINDOW FROM C++"; 0180 auto window = qobject_cast<QQuickWindow *>(m_qmlObject); 0181 if (window) 0182 { 0183 qDebug() << "Trying to raise wndow"; 0184 window->raise(); 0185 window->requestActivate(); 0186 } 0187 } 0188 } 0189 0190 void Server::quit() 0191 { 0192 QCoreApplication::quit(); 0193 } 0194 0195 void Server::openFiles(const QStringList &urls, bool splitView) 0196 { 0197 auto files = filterFiles(urls); 0198 0199 if(m_qmlObject) 0200 { 0201 if(files.isEmpty()) 0202 { 0203 openEmptyTab(); 0204 }else 0205 { 0206 QMetaObject::invokeMethod(m_qmlObject, "openFiles", 0207 Q_ARG(QVariant, files)); 0208 } 0209 0210 } 0211 } 0212 0213 void Server::openNewTab(const QString &url) 0214 { 0215 if(m_qmlObject) 0216 { 0217 QMetaObject::invokeMethod(m_qmlObject, "openFile", 0218 Q_ARG(QString, url)); 0219 } 0220 } 0221 0222 void Server::openEmptyTab() 0223 { 0224 if(m_qmlObject) 0225 { 0226 QMetaObject::invokeMethod(m_qmlObject, "openTab"); 0227 } 0228 } 0229 0230 void Server::focusFile(const QString &url) 0231 { 0232 if(m_qmlObject) 0233 { 0234 QMetaObject::invokeMethod(m_qmlObject, "focusFile", 0235 Q_ARG(QString, url)); 0236 } 0237 } 0238 0239 void Server::openNewTabAndActivate(const QString &url) 0240 { 0241 if(m_qmlObject) 0242 { 0243 QMetaObject::invokeMethod(m_qmlObject, "openFile", 0244 Q_ARG(QString, url)); 0245 this->activateWindow(); 0246 } 0247 } 0248 0249 void Server::openNewWindow(const QString &url) 0250 { 0251 0252 } 0253 0254 bool Server::isUrlOpen(const QString &url) 0255 { 0256 bool value = false; 0257 0258 if(m_qmlObject) 0259 { 0260 QMetaObject::invokeMethod(m_qmlObject, "isUrlOpen", 0261 Q_RETURN_ARG(bool, value), 0262 Q_ARG(QString, url)); 0263 } 0264 return value; 0265 } 0266 0267 QStringList Server::filterFiles(const QStringList &urls) 0268 { 0269 qDebug() << "REQUEST FILES" << urls; 0270 QStringList res; 0271 for (const auto &url : urls) { 0272 const auto url_ = QUrl::fromUserInput(url); 0273 qDebug() << "REQUEST FILES" << url_.toString() << FMStatic::getMime(url_); 0274 0275 if (FMStatic::checkFileType(FMStatic::FILTER_TYPE::TEXT, FMStatic::getMime(url_))) 0276 res << url_.toString(); 0277 } 0278 0279 qDebug() << "REQUEST FILES" << res; 0280 0281 return res; 0282 }