File indexing completed on 2024-05-19 04:48:26

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 "vvaveinterface.h"
0011 #include "vvaveadaptor.h"
0012 
0013 QVector<QPair<QSharedPointer<OrgKdeVvaveActionsInterface>, QStringList>> AppInstance::appInstances(const QString& preferredService)
0014 {
0015     QVector<QPair<QSharedPointer<OrgKdeVvaveActionsInterface>, QStringList>> dolphinInterfaces;
0016 
0017     if (!preferredService.isEmpty())
0018     {
0019         QSharedPointer<OrgKdeVvaveActionsInterface> preferredInterface(
0020                     new OrgKdeVvaveActionsInterface(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.vvave-");
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<OrgKdeVvaveActionsInterface> interface(
0047                         new OrgKdeVvaveActionsInterface(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, const QString& preferredService)
0061 {
0062     bool attached = false;
0063 
0064     auto dolphinInterfaces = appInstances(preferredService);
0065     if (dolphinInterfaces.isEmpty())
0066     {
0067         return attached;
0068     }
0069 
0070     QStringList newUrls;
0071 
0072     // check to see if any instances already have any of the given URLs open
0073     const auto urls = QUrl::toStringList(inputUrls);
0074     for (const QString& url : urls)
0075     {
0076         bool urlFound = false;
0077 
0078         for (auto& interface: dolphinInterfaces)
0079         {
0080             auto isUrlOpenReply = interface.first->isUrlOpen(url);
0081             isUrlOpenReply.waitForFinished();
0082 
0083             if (!isUrlOpenReply.isError() && isUrlOpenReply.value())
0084             {
0085                 interface.second.append(url);
0086                 urlFound = true;
0087                 break;
0088             }
0089         }
0090 
0091         if (!urlFound)
0092         {
0093             newUrls.append(url);
0094         }
0095     }
0096 
0097     for (const auto& interface: qAsConst(dolphinInterfaces))
0098     {
0099         auto reply = interface.first->openFiles(newUrls);
0100         reply.waitForFinished();
0101 
0102         if (!reply.isError())
0103         {
0104             interface.first->activateWindow();
0105             attached = true;
0106             break;
0107         }
0108     }
0109 
0110     return attached;
0111 }
0112 
0113 bool AppInstance::registerService()
0114 {
0115     QDBusConnectionInterface *iface = QDBusConnection::sessionBus().interface();
0116 
0117     auto registration = iface->registerService(QStringLiteral("org.kde.vvave-%1").arg(QCoreApplication::applicationPid()),
0118                                                QDBusConnectionInterface::ReplaceExistingService,
0119                                                QDBusConnectionInterface::DontAllowReplacement);
0120 
0121     if (!registration.isValid())
0122     {
0123         qWarning("2 Failed to register D-Bus service \"%s\" on session bus: \"%s\"",
0124                  qPrintable("org.kde.vvave"),
0125                  qPrintable(registration.error().message()));
0126         return false;
0127     }
0128 
0129     return true;
0130 }
0131 
0132 #endif
0133 
0134 
0135 Server::Server(QObject *parent) : QObject(parent)
0136   , m_qmlObject(nullptr)
0137 {
0138 #if (defined Q_OS_LINUX || defined Q_OS_FREEBSD) && !defined Q_OS_ANDROID
0139     new ActionsAdaptor(this);
0140     if(!QDBusConnection::sessionBus().registerObject(QStringLiteral("/Actions"), this))
0141     {
0142         qDebug() << "FAILED TO REGISTER BACKGROUND DBUS OBJECT";
0143         return;
0144     }
0145 #endif
0146 }
0147 
0148 void Server::setQmlObject(QObject *object)
0149 {
0150     if(!m_qmlObject)
0151     {
0152         m_qmlObject = object;
0153     }
0154 }
0155 
0156 void Server::activateWindow()
0157 {
0158     if(m_qmlObject)
0159     {
0160         qDebug() << "ACTIVET WINDOW FROM C++";
0161         auto window = qobject_cast<QQuickWindow *>(m_qmlObject);
0162         if (window)
0163         {
0164             qDebug() << "Trying to raise wndow";
0165             window->raise();
0166             window->requestActivate();
0167         }
0168     }
0169 }
0170 
0171 void Server::quit()
0172 {
0173     QCoreApplication::quit();
0174 }
0175 
0176 void Server::openFiles(const QStringList &urls)
0177 {
0178     if(m_qmlObject)
0179     {
0180         auto files = filterFiles(urls);
0181         if(!files.isEmpty())
0182         {
0183             QMetaObject::invokeMethod(m_qmlObject, "openFiles",
0184                                       Q_ARG(QVariant, files));
0185         }
0186 
0187     }
0188 }
0189 
0190 bool Server::isUrlOpen(const QString &url)
0191 {
0192     bool value = false;
0193 
0194     if(m_qmlObject)
0195     {
0196         QMetaObject::invokeMethod(m_qmlObject, "isUrlOpen",
0197                                   Q_RETURN_ARG(bool, value),
0198                                   Q_ARG(QString, url));
0199     }
0200     return value;
0201 }
0202 
0203 QStringList Server::filterFiles(const QStringList &urls)
0204 {
0205     qDebug() << "REQUEST FILES" << urls;
0206     QStringList res;
0207     for (const auto &url : urls) {
0208         const auto url_ = QUrl::fromUserInput(url);
0209         qDebug() << "REQUEST FILES" << url_.toString() << FMStatic::getMime(url_);
0210 
0211         if (FMStatic::checkFileType(FMStatic::FILTER_TYPE::AUDIO, FMStatic::getMime(url_)))
0212             res << url_.toString();
0213     }
0214 
0215     qDebug() << "REQUEST FILES" << res;
0216 
0217     return res;
0218 }