From f3b6ecf0983dbb85a61faee21f41160df63cc575 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Tue, 21 Feb 2017 16:40:25 +0100 Subject: Single instance --- smolbote.qbs | 12 ++++-- src/browser.cpp | 75 ++++++++++++++++++++++++++++++++++++-- src/browser.h | 8 ++++ src/main.cpp | 18 ++++++--- src/mainwindow.cpp | 31 +++++++--------- src/mainwindow.h | 7 ++-- src/webengine/webengineprofile.cpp | 23 +++++++----- src/webengine/webengineprofile.h | 1 + test/config.ini | 5 +++ 9 files changed, 137 insertions(+), 43 deletions(-) diff --git a/smolbote.qbs b/smolbote.qbs index 1ef8407..032a93e 100644 --- a/smolbote.qbs +++ b/smolbote.qbs @@ -13,10 +13,11 @@ Project { // feature of Qt which as been marked as deprecated (the exact warnings // depend on your compiler). Please consult the documentation of the // deprecated API in order to know how to port your code away from it. - - // The code also fails to compile if you use APIs deprecated before Qt 5,7. property bool deprecatedWarnings: true + // The code also fails to compile if you use APIs deprecated before Qt 5.7. + property string deprecatedBefore: "0x050700" + CppApplication { id: poi name: "poi" @@ -36,10 +37,15 @@ Project { } } + // Platform-specifics go like this +// Properties { +// condition: qbs.targetOS.contains("windows") +// } + cpp.includePaths: ['src'] cpp.defines: { if(project.deprecatedWarnings) - defines.push("QT_DEPRECATED_WARNINGS", "QT_DISABLE_DEPRECATED_BEFORE=0x050700"); + defines.push("QT_DEPRECATED_WARNINGS", "QT_DISABLE_DEPRECATED_BEFORE="+project.deprecatedBefore); if(git.found) defines.push('VERSION="'+git.version+'"'); return defines; diff --git a/src/browser.cpp b/src/browser.cpp index 1ca9abb..46af166 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -24,11 +24,9 @@ #include Browser::Browser(int &argc, char *argv[]) : - QApplication(argc, argv), - m_bookmarksManager(new BookmarksDialog), - m_downloadManager(new DownloadDialog) + QApplication(argc, argv) { - QtWebEngine::initialize(); + setApplicationName("smolbote"); } Browser::~Browser() @@ -40,6 +38,50 @@ Browser::~Browser() delete m_downloadManager; } +/*! + * Anything that needs to run after the QCommandLineParser but before showing a main window + */ +bool Browser::preLaunch(QStringList urls) +{ + Settings settings; + + if(settings.value("browser/singleInstance", true).toBool()) { + QString serverName = settings.value("browser/localSocket", "smolbote-singlelock").toString(); + + // Check for other running instance + QLocalSocket socket; + socket.connectToServer(serverName); + if(socket.waitForConnected(500)) { + QTextStream stream(&socket); + stream << urls.join('|'); + stream.flush(); + socket.waitForBytesWritten(); + return false; + } + + // There is no other instance + m_localServer = new QLocalServer(this); + connect(m_localServer, SIGNAL(newConnection()), this, SLOT(handleNewConnection())); + if (!m_localServer->listen(serverName) && m_localServer->serverError() == QAbstractSocket::AddressInUseError) { + // Could not create local server because the socket is already in use + QLocalServer::removeServer(serverName); + if (!m_localServer->listen(serverName)) { + // Couldn't free the socket + qWarning("Could not create local socket %s.", qPrintable(serverName)); + } + } else { + qDebug("Created local socket."); + } + } + + m_bookmarksManager = new BookmarksDialog; + m_downloadManager = new DownloadDialog; + + QtWebEngine::initialize(); + + return true; +} + Browser *Browser::instance() { return static_cast(QCoreApplication::instance()); @@ -80,7 +122,32 @@ void Browser::addWindow(MainWindow *window) window->show(); } +MainWindow *Browser::mainWindow() +{ + if(m_windows.isEmpty()) { + addWindow(new MainWindow()); + } + return m_windows.first(); +} + void Browser::removeWindow(MainWindow *window) { m_windows.removeOne(window); } + +void Browser::handleNewConnection() +{ + QLocalSocket *socket = m_localServer->nextPendingConnection(); + if(!socket) { + // null socket -> return + return; + } + + socket->waitForReadyRead(); + QStringList urls = QString(socket->readAll()).split('|'); + delete socket; + + for(QString s : urls) { + mainWindow()->addNewTab(QUrl::fromUserInput(s)); + } +} diff --git a/src/browser.h b/src/browser.h index 2344997..2d3c2b0 100644 --- a/src/browser.h +++ b/src/browser.h @@ -25,6 +25,7 @@ #include #include "forms/bookmarksdialog.h" #include "forms/downloaddialog.h" +#include class MainWindow; class Browser : public QApplication @@ -35,6 +36,8 @@ public: Browser(int &argc, char *argv[]); ~Browser(); + bool preLaunch(QStringList urls); + static Browser *instance(); BookmarksDialog *bookmarks(); @@ -42,11 +45,16 @@ public: void setConfigPath(const QString &path); void addWindow(MainWindow* window); + MainWindow *mainWindow(); public slots: void removeWindow(MainWindow* window); +private slots: + void handleNewConnection(); + private: + QLocalServer *m_localServer; QVector m_windows; BookmarksDialog *m_bookmarksManager; DownloadDialog *m_downloadManager; diff --git a/src/main.cpp b/src/main.cpp index 8dcfb03..656472c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,7 +26,6 @@ int main(int argc, char *argv[]) { Browser app(argc, argv); - app.setApplicationName("smolbote"); #ifdef VERSION app.setApplicationVersion(VERSION); #endif @@ -36,17 +35,24 @@ int main(int argc, char *argv[]) parser.setApplicationDescription("yet another Qt browser"); parser.addHelpOption(); parser.addVersionOption(); - - parser.addPositionalArgument("URL", "URL to open"); - + parser.addPositionalArgument("URL", "URL(s) to open"); QCommandLineOption configOption(QStringList() << "c" << "config", "Set configuration file.", "PATH"); parser.addOption(configOption); + QCommandLineOption profileOption(QStringList() << "p" << "profile", "Use this profile.", "PROFILE"); + parser.addOption(profileOption); parser.process(app); app.setConfigPath(parser.value(configOption)); - - app.addWindow(new MainWindow(parser.positionalArguments())); + if(!app.preLaunch(parser.positionalArguments())) { + return 0; + } + + MainWindow *w = new MainWindow(parser.positionalArguments()); + if(parser.isSet(profileOption)) { + w->loadProfile(parser.value(profileOption)); + } + app.addWindow(w); return app.exec(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1f979ca..fa7f01d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -114,10 +114,10 @@ MainWindow::~MainWindow() void MainWindow::addNewTab(const QUrl &url) { if(!url.isEmpty()) { - tabBar->addTab(profile, url); + tabBar->addTab(m_profile, url); } else { Settings settings; - tabBar->addTab(profile, settings.value("newtab").toUrl()); + tabBar->addTab(m_profile, settings.value("newtab").toUrl()); } } @@ -146,24 +146,24 @@ void MainWindow::about() void MainWindow::loadProfile(const QString &name) { - if(profile) { - profile->deleteLater(); + if(m_profile) { + m_profile->deleteLater(); } if(name.isEmpty()) { + //profileName = tr("Off the record"); + m_profile = new WebEngineProfile(this); qDebug("Creating off-the-record profile"); - profileName = tr("Off the record"); - profile = new WebEngineProfile(this); } else { - profileName = name; - qDebug("Using profile: %s", qUtf8Printable(profileName)); - profile = new WebEngineProfile(profileName, this); + //profileName = name; + m_profile = new WebEngineProfile(name, this); + qDebug("Using profile: %s", qUtf8Printable(m_profile->storageName())); } UrlRequestInterceptor *interceptor = new UrlRequestInterceptor(this); interceptor->setSubscription(blocklistManager->subscription()); - profile->setRequestInterceptor(interceptor); - connect(profile, SIGNAL(downloadRequested(QWebEngineDownloadItem*)), Browser::instance()->downloads(), SLOT(addDownload(QWebEngineDownloadItem*))); + m_profile->setRequestInterceptor(interceptor); + connect(m_profile, SIGNAL(downloadRequested(QWebEngineDownloadItem*)), Browser::instance()->downloads(), SLOT(addDownload(QWebEngineDownloadItem*))); } void MainWindow::loadProfileGUI() @@ -172,7 +172,7 @@ void MainWindow::loadProfileGUI() QString name = QInputDialog::getText(this, tr("Load Profile"), tr("Enter Profile name"), QLineEdit::Normal, QString(""), &ok); if(ok) { loadProfile(name); - tabBar->setProfile(profile); + tabBar->setProfile(m_profile); } } @@ -212,15 +212,12 @@ void MainWindow::handleUrlChanged() void MainWindow::handleTitleUpdated(const QString &title) { - // For some reason, the long dash gets garbled if read from the settings - //setWindowTitle(title + settings.value("window/title").toString()); - Settings settings; - setWindowTitle(settings.value("window/title").toString().replace("$title", title).replace("$profile", profileName)); + setWindowTitle(settings.value("window/title").toString().replace("$title", title).replace("$profile", m_profile->storageName())); } void MainWindow::execProfileEditor() { - ProfileDialog *dialog = new ProfileDialog(profile, this); + ProfileDialog *dialog = new ProfileDialog(m_profile, this); dialog->exec(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index a93935b..0c1f659 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -45,6 +45,8 @@ public: MainWindow(const QStringList urlList, QWidget *parent = 0); ~MainWindow(); + void loadProfile(const QString &name); + public slots: void addNewTab(const QUrl &url = QUrl("")); @@ -54,7 +56,6 @@ protected: private slots: void about(); - void loadProfile(const QString &name); void loadProfileGUI(); void execProfileEditor(); @@ -65,9 +66,7 @@ private slots: private: BlockerDialog *blocklistManager; - - QString profileName; - WebEngineProfile *profile = nullptr; + WebEngineProfile *m_profile = nullptr; // ui Ui::MainWindow *ui; diff --git a/src/webengine/webengineprofile.cpp b/src/webengine/webengineprofile.cpp index 826bc44..de806df 100644 --- a/src/webengine/webengineprofile.cpp +++ b/src/webengine/webengineprofile.cpp @@ -30,8 +30,9 @@ WebEngineProfile::WebEngineProfile(QObject *parent) : WebEngineProfile::WebEngineProfile(const QString &storageName, QObject *parent) : QWebEngineProfile(storageName, parent) { - qDebug("Reading WebEngineProfile..."); - QSettings config(persistentStoragePath() + "/profile.ini", QSettings::IniFormat); + QString profilePath = persistentStoragePath() + "/profile.ini"; + qDebug("Reading profile from [%s]", qUtf8Printable(profilePath)); + QSettings config(profilePath, QSettings::IniFormat); config.beginGroup("http"); setHttpUserAgent(config.value("userAgent").toString()); @@ -40,12 +41,16 @@ WebEngineProfile::WebEngineProfile(const QString &storageName, QObject *parent) WebEngineProfile::~WebEngineProfile() { - if(!this->isOffTheRecord()) { - // save settings - QSettings config(persistentStoragePath() + "/profile.ini", QSettings::IniFormat); - config.beginGroup("http"); - config.setValue("userAgent", httpUserAgent()); - config.endGroup(); - config.sync(); + if(!isOffTheRecord()) { + saveProfile(); } } + +void WebEngineProfile::saveProfile() +{ + QSettings config(persistentStoragePath() + "/profile.ini", QSettings::IniFormat); + config.beginGroup("http"); + config.setValue("userAgent", httpUserAgent()); + config.endGroup(); + config.sync(); +} diff --git a/src/webengine/webengineprofile.h b/src/webengine/webengineprofile.h index dc07f4b..1845c99 100644 --- a/src/webengine/webengineprofile.h +++ b/src/webengine/webengineprofile.h @@ -35,6 +35,7 @@ public: signals: public slots: + void saveProfile(); }; #endif // WEBENGINEPROFILE_H diff --git a/test/config.ini b/test/config.ini index 38bd119..f3310d6 100644 --- a/test/config.ini +++ b/test/config.ini @@ -1,3 +1,7 @@ +[browser] +singleInstance=true +localSocket=smolbote-singlelock + [general] homepage=https://duckduckgo.com newtab=about:blank @@ -12,6 +16,7 @@ path=bookmarks.xbel [window] height=720 width=1280 +title=$title — smolbote [$profile] [shortcuts] bookmarks=Ctrl+Shift+B -- cgit v1.2.1