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 }