diff --git a/gui/gui.pro b/gui/gui.pro index 5417c1f..e97e05c 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core concurrent gui +QT += core concurrent gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 @@ -23,6 +23,8 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + ipcclient.cpp \ + ipcserver.cpp \ main.cpp \ mainwindow.cpp \ pdfworker.cpp \ @@ -30,6 +32,9 @@ SOURCES += \ clicklabel.cpp HEADERS += \ + ipc.h \ + ipcclient.h \ + ipcserver.h \ mainwindow.h \ pdfworker.h \ pdfpreview.h \ diff --git a/gui/ipc.h b/gui/ipc.h new file mode 100644 index 0000000..f1ef8a3 --- /dev/null +++ b/gui/ipc.h @@ -0,0 +1,9 @@ +#ifndef IPC_H +#define IPC_H + +enum IPCCommand +{ + DocOpen, + FileOpen +}; +#endif // IPC_H diff --git a/gui/ipcclient.cpp b/gui/ipcclient.cpp new file mode 100644 index 0000000..9f29f6b --- /dev/null +++ b/gui/ipcclient.cpp @@ -0,0 +1,27 @@ +#include +#include "ipcclient.h" + +IPCClient::IPCClient(QString socketPath) +{ + this->socketPath = socketPath; +} + +bool IPCClient::sendCommand(IPCCommand command, QStringList args) +{ + bool result = false; + QLocalSocket socket; + socket.connectToServer(socketPath); + if(socket.isOpen() && socket.isWritable()) + { + QDataStream stream(&socket); + stream << command; + stream << args; + socket.flush(); + result = true; + } + else + { + qDebug() << "Not connected to IPC server"; + } + return result; +} diff --git a/gui/ipcclient.h b/gui/ipcclient.h new file mode 100644 index 0000000..cd3eb2c --- /dev/null +++ b/gui/ipcclient.h @@ -0,0 +1,18 @@ +#ifndef IPCCLIENT_H +#define IPCCLIENT_H +#include +#include +#include +#include "ipc.h" + +class IPCClient +{ + private: + QString socketPath; + + public: + IPCClient(QString socketPath); + bool sendCommand(IPCCommand command, QStringList args); +}; + +#endif // IPCCLIENT_H diff --git a/gui/ipcserver.cpp b/gui/ipcserver.cpp new file mode 100644 index 0000000..01ec349 --- /dev/null +++ b/gui/ipcserver.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ipcserver.h" + +IpcServer::IpcServer() +{ + connect(&this->spawningServer, &QLocalServer::newConnection, this, &IpcServer::spawnerNewConnection); +} + +bool IpcServer::startSpawner(QString socketPath) +{ + QFile::remove(socketPath); + return this->spawningServer.listen(socketPath); +} + +bool IpcServer::docOpen(QString path, int pagenum) +{ + QSettings settings; + QString command = settings.value("pdfviewer").toString(); + if(command != "" && command.contains("%p") && command.contains("%f")) + { + QStringList splitted = command.split(" "); + if(splitted.size() > 1) + { + QString cmd = splitted[0]; + QStringList args = splitted.mid(1); + args.replaceInStrings("%f", path); + args.replaceInStrings("%p", QString::number(pagenum)); + + QProcess::startDetached(cmd, args); + } + } + else + { + QDesktopServices::openUrl(QUrl::fromLocalFile(path)); + } + return true; +} + +bool IpcServer::fileOpen(QString path) +{ + return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); +} + +void IpcServer::spawnerNewConnection() +{ + QScopedPointer socket{this->spawningServer.nextPendingConnection()}; + if(!socket.isNull()) + { + if(!socket->waitForReadyRead()) + { + return; + } + QDataStream stream(socket.get()); + IPCCommand command; + QStringList args; + stream >> command; + stream >> args; + if(args.size() < 1) + { + stream << "invalid"; + return; + } + if(command == DocOpen) + { + if(args.size() < 2) + { + stream << "invalid"; + return; + } + docOpen(args[0], args[2].toInt()); + } + if(command == FileOpen) + { + if(args.size() < 1) + { + stream << "invalid"; + return; + } + fileOpen(args[0]); + } + } +} diff --git a/gui/ipcserver.h b/gui/ipcserver.h new file mode 100644 index 0000000..7f86a8b --- /dev/null +++ b/gui/ipcserver.h @@ -0,0 +1,21 @@ +#ifndef IPCSERVER_H +#define IPCSERVER_H +#include +#include +#include "ipc.h" +class IpcServer : public QObject +{ + Q_OBJECT + private: + QLocalServer spawningServer; + bool docOpen(QString path, int pagenum); + bool fileOpen(QString path); + private slots: + void spawnerNewConnection(); + + public: + IpcServer(); + bool startSpawner(QString socketPath); +}; + +#endif // IPCSERVER_H diff --git a/gui/main.cpp b/gui/main.cpp index cd8766d..06dcfeb 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -2,19 +2,51 @@ #include #include #include +#include + #include "mainwindow.h" #include "searchresult.h" #include "pdfpreview.h" #include "../shared/common.h" #include "../submodules/qssb.h/qssb.h" +#include "ipcserver.h" int main(int argc, char *argv[]) { + QString socketPath = "/tmp/looqs-spawner"; + if(argc > 1) + { + QApplication a(argc, argv); + QString arg = argv[1]; + if(arg == "ipc") + { + IpcServer *ipcserver = new IpcServer(); + qDebug() << "Launching ipc"; + if(!ipcserver->startSpawner(socketPath)) + { + qDebug() << "Error failed to spawn"; + return 1; + } + qDebug() << "Launched"; + } + return a.exec(); + } + QProcess process; + QStringList args; + args << "ipc"; + if(!process.startDetached("/proc/self/exe", args)) + { + QString errorMsg = "Failed to start IPC server"; + qDebug() << errorMsg; + QMessageBox::critical(nullptr, "Error", errorMsg); + } + struct qssb_policy *policy = qssb_init_policy(); std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString(); - + std::string sockPath = socketPath.toStdString(); policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER; + qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE, "/"); qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE, appDataLocation.c_str()); @@ -44,7 +76,9 @@ int main(int argc, char *argv[]) qRegisterMetaType>("QVector"); qRegisterMetaType>("QVector"); qRegisterMetaType("PdfPreview"); - MainWindow w; + + IPCClient client{socketPath}; + MainWindow w{0, client}; w.showMaximized(); return a.exec(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 9f1487f..7049457 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -18,10 +18,11 @@ #include "../shared/looqsgeneralexception.h" #include "../shared/common.h" -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) +MainWindow::MainWindow(QWidget *parent, IPCClient &client) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowTitle(QCoreApplication::applicationName()); + this->ipcClient = &client; QSettings settings; db = QSqlDatabase::addDatabase("QSQLITE"); @@ -136,29 +137,7 @@ void MainWindow::pdfPreviewReceived(PdfPreview preview) label->setPixmap(QPixmap::fromImage(preview.previewImage)); label->setToolTip(preview.documentPath); ui->scrollAreaWidgetContents->layout()->addWidget(label); - connect(label, &ClickLabel::leftClick, - [docPath, previewPage]() - { - QSettings settings; - QString command = settings.value("pdfviewer").toString(); - if(command != "" && command.contains("%p") && command.contains("%f")) - { - QStringList splitted = command.split(" "); - if(splitted.size() > 1) - { - QString cmd = splitted[0]; - QStringList args = splitted.mid(1); - args.replaceInStrings("%f", docPath); - args.replaceInStrings("%p", QString::number(previewPage)); - - QProcess::startDetached(cmd, args); - } - } - else - { - QDesktopServices::openUrl(QUrl::fromLocalFile(docPath)); - } - }); + connect(label, &ClickLabel::leftClick, [this, docPath, previewPage]() { ipcDocOpen(docPath, previewPage); }); connect(label, &ClickLabel::rightClick, [this, docPath, previewPage]() { @@ -301,17 +280,27 @@ void MainWindow::createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo) [&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.fileName()); }); menu.addAction("Copy full path to clipboard", [&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.absoluteFilePath()); }); - menu.addAction("Open containing folder", - [&fileInfo] - { - QString dir = fileInfo.absolutePath(); - QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); - }); + menu.addAction("Open containing folder", [this, &fileInfo] { this->ipcFileOpen(fileInfo.absolutePath()); }); +} + +void MainWindow::ipcDocOpen(QString path, int num) +{ + QStringList args; + args << path; + args << QString::number(num); + this->ipcClient->sendCommand(DocOpen, args); +} + +void MainWindow::ipcFileOpen(QString path) +{ + QStringList args; + args << path; + this->ipcClient->sendCommand(FileOpen, args); } void MainWindow::treeSearchItemActivated(QTreeWidgetItem *item, int i) { - QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1))); + ipcFileOpen(item->text(1)); } void MainWindow::showSearchResultsContextMenu(const QPoint &point) diff --git a/gui/mainwindow.h b/gui/mainwindow.h index f6a3dd0..40eb12f 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -8,8 +8,10 @@ #include #include #include +#include #include "pdfworker.h" #include "../shared/looqsquery.h" +#include "ipcclient.h" namespace Ui { class MainWindow; @@ -20,7 +22,7 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent, IPCClient &client); ~MainWindow(); signals: void beginSearch(const QString &query); @@ -28,6 +30,7 @@ class MainWindow : public QMainWindow private: Ui::MainWindow *ui; + IPCClient *ipcClient; QFileIconProvider iconProvider; bool pdfDirty; QSqlDatabase db; @@ -45,6 +48,9 @@ class MainWindow : public QMainWindow LooqsQuery currentQuery; int pdfPreviewsPerPage; void createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo); + void ipcDocOpen(QString path, int num); + void ipcFileOpen(QString path); + private slots: void lineEditReturnPressed(); void treeSearchItemActivated(QTreeWidgetItem *item, int i); diff --git a/shared/shared.pro b/shared/shared.pro index 88072ea..1e943ee 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -13,6 +13,8 @@ TEMPLATE = lib CONFIG += staticlib CONFIG += c++17 +INCLUDEPATH += $$PWD/../sandbox/qssb.h/ + # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the diff --git a/submodules/qssb.h b/submodules/qssb.h index 75f607b..692c9b5 160000 --- a/submodules/qssb.h +++ b/submodules/qssb.h @@ -1 +1 @@ -Subproject commit 75f607bc350354ed31fd0977311917e13241e703 +Subproject commit 692c9b54b7b5fdca6a416d91d3f34d15af185c33