aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/poi.toml2
-rw-r--r--smolbote.qbs2
-rw-r--r--src/browser.cpp129
-rw-r--r--src/browser.h20
-rw-r--r--src/main.cpp29
-rw-r--r--src/singleapplication.cpp71
-rw-r--r--src/singleapplication.h51
-rw-r--r--src/widgets/mainwindowmenubar.cpp4
8 files changed, 210 insertions, 98 deletions
diff --git a/data/poi.toml b/data/poi.toml
index e2f37e6..34fb697 100644
--- a/data/poi.toml
+++ b/data/poi.toml
@@ -12,8 +12,6 @@ search="https://duckduckgo.com/?q=$term&kp=-1"
# Browser: application-wide settings
[browser]
-singleInstance=true
-localSocket="smolbote-singlelock"
#sessionPath="$cache/session.json"
# Profile
diff --git a/smolbote.qbs b/smolbote.qbs
index 60bd062..074b44b 100644
--- a/smolbote.qbs
+++ b/smolbote.qbs
@@ -60,6 +60,8 @@ Project {
"src/browser.h",
"src/interfaces.h",
"src/main.cpp",
+ "src/singleapplication.cpp",
+ "src/singleapplication.h",
]
cpp.defines: {
if(project.deprecatedWarnings)
diff --git a/src/browser.cpp b/src/browser.cpp
index f95d01a..ce36123 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -28,10 +28,9 @@
#include "interfaces.h"
Browser::Browser(int &argc, char *argv[]) :
- QApplication(argc, argv)
+ SingleApplication(argc, argv)
{
m_settings = nullptr;
- m_localServer = nullptr;
m_networkAccessManager = nullptr;
m_urlRequestInterceptor = nullptr;
@@ -40,6 +39,13 @@ Browser::Browser(int &argc, char *argv[]) :
m_blocklistManager = nullptr;
m_plugin = nullptr;
+
+ setApplicationName("smolbote");
+#ifdef GIT_VERSION
+ setApplicationVersion(GIT_VERSION);
+#else
+ setApplicationVersion("1.0.0");
+#endif
}
Browser::~Browser()
@@ -69,51 +75,8 @@ QString Browser::applicationLongVersion() const
#endif
}
-bool Browser::prepare(QStringList urls)
+void Browser::loadPlugins()
{
- if(m_settings->value("browser.singleInstance", true).toBool()) {
- QString serverName = m_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.");
- }
- }
-
- if(m_settings->isEmpty()) {
- // There are no keys in the settings
- QMessageBox::information(0,
- tr("Configuration is empty"),
- tr("The configuration file <i>%1</i> is empty. Using default values").arg(m_settings->filePath()));
- }
-
- m_networkAccessManager = new QNetworkAccessManager();
- m_bookmarksManager = new BookmarksWidget;
- m_downloadManager = new DownloadsWidget;
- m_blocklistManager = new BlockerManager;
-
- QtWebEngine::initialize();
-
// Loading plugins
qDebug(">> Looking for plugins...");
@@ -139,12 +102,13 @@ bool Browser::prepare(QStringList urls)
}
qDebug("<< Plugins end...");
+}
+void Browser::loadProfiles()
+{
// TODO properly
profile("");
profile("Default");
-
- return true;
}
Browser *Browser::instance()
@@ -159,21 +123,33 @@ Settings *Browser::settings()
QNetworkAccessManager *Browser::network()
{
+ if(!m_networkAccessManager) {
+ m_networkAccessManager = new QNetworkAccessManager();
+ }
return m_networkAccessManager;
}
BookmarksWidget *Browser::bookmarks()
{
+ if(!m_bookmarksManager) {
+ m_bookmarksManager = new BookmarksWidget();
+ }
return m_bookmarksManager;
}
DownloadsWidget *Browser::downloads()
{
+ if(!m_downloadManager) {
+ m_downloadManager = new DownloadsWidget();
+ }
return m_downloadManager;
}
BlockerManager *Browser::blocklists()
{
+ if(!m_blocklistManager) {
+ m_blocklistManager = new BlockerManager();
+ }
return m_blocklistManager;
}
@@ -203,6 +179,21 @@ void Browser::setConfigPath(const QString &path)
else {
m_settings = new Settings();
}
+
+ if(m_settings->isEmpty()) {
+ // There are no keys in the settings
+ QMessageBox::information(0,
+ tr("Configuration is empty"),
+ tr("The configuration file <i>%1</i> is empty. Using default values").arg(m_settings->filePath()));
+ }
+}
+
+MainWindow *Browser::mainWindow()
+{
+ if(m_windows.isEmpty()) {
+ addWindow(new MainWindow());
+ }
+ return m_windows.first();
}
void Browser::addWindow(MainWindow *window)
@@ -219,12 +210,24 @@ void Browser::addWindow(MainWindow *window)
window->show();
}
-MainWindow *Browser::mainWindow()
+void Browser::addWindow(const QStringList params)
{
- if(m_windows.isEmpty()) {
- addWindow(new MainWindow());
+ QString p; // get default profile
+ QStringList urls;
+
+ for(int i = 0; i < params.length(); i++) {
+ if(params.at(i) == "-p" || params.at(i) == "--profile") {
+ i++;
+ p = params.at(i);
+ } else if(!params.at(i).startsWith('-')) {
+ urls.append(params.at(i));
+ }
}
- return m_windows.first();
+
+ MainWindow *w = new MainWindow(urls);
+ w->setProfile(profile(p));
+
+ addWindow(w);
}
void Browser::removeWindow(MainWindow *window)
@@ -244,7 +247,7 @@ WebEngineProfile* Browser::profile(const QString name)
if(!m_urlRequestInterceptor) {
m_urlRequestInterceptor = new UrlRequestInterceptor(this);
- m_urlRequestInterceptor->setSubscription(m_blocklistManager);
+ m_urlRequestInterceptor->setSubscription(blocklists());
}
m_profiles[name]->setRequestInterceptor(m_urlRequestInterceptor);
@@ -264,25 +267,7 @@ QStringList Browser::profiles()
return l;
}
-QObject *Browser::plugin()
+QObject *Browser::plugin(const QString name)
{
return m_plugin;
}
-
-void Browser::handleNewConnection()
-{
- QLocalSocket *socket = m_localServer->nextPendingConnection();
- if(!socket) {
- // null socket -> return
- return;
- }
-
- socket->waitForReadyRead();
- const QStringList urls = QString(socket->readAll()).split('|');
- delete socket;
-
- QStringList::const_iterator i;
- for(i = urls.constBegin(); i != urls.constEnd(); ++i) {
- mainWindow()->newTab(QUrl::fromUserInput(*i));
- }
-}
diff --git a/src/browser.h b/src/browser.h
index 2c30bcc..75102c6 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -21,11 +21,10 @@
#ifndef BROWSER_H
#define BROWSER_H
-#include <QApplication>
+#include "singleapplication.h"
#include <QVector>
#include "forms/bookmarkswidget.h"
#include "forms/downloadswidget.h"
-#include <QLocalServer>
#include "settings.h"
#include <QNetworkAccessManager>
#include "webengine/webengineprofile.h"
@@ -38,7 +37,7 @@
#define sNetwork Browser::instance()->network()
class MainWindow;
-class Browser : public QApplication
+class Browser : public SingleApplication
{
Q_OBJECT
@@ -48,7 +47,9 @@ public:
QString applicationLongVersion() const;
- bool prepare(QStringList urls);
+ void setConfigPath(const QString &path);
+ void loadPlugins();
+ void loadProfiles();
static Browser *instance();
@@ -58,24 +59,21 @@ public:
DownloadsWidget *downloads();
BlockerManager *blocklists();
- void setConfigPath(const QString &path);
- void addWindow(MainWindow* window);
MainWindow *mainWindow();
WebEngineProfile *profile(const QString name);
QStringList profiles();
- QObject *plugin();
+ QObject *plugin(const QString name);
+ QStringList plugins();
public slots:
+ void addWindow(MainWindow* window);
+ void addWindow(const QStringList params);
void removeWindow(MainWindow* window);
-private slots:
- void handleNewConnection();
-
private:
Settings *m_settings;
- QLocalServer *m_localServer;
QVector<MainWindow *> m_windows;
QHash<QString, WebEngineProfile *> m_profiles;
diff --git a/src/main.cpp b/src/main.cpp
index e1f4c5c..bf4c29f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,15 +26,10 @@
int main(int argc, char *argv[])
{
Browser app(argc, argv);
- app.setApplicationName("smolbote");
-#ifdef GIT_VERSION
- app.setApplicationVersion(GIT_VERSION);
-#else
- app.setApplicationVersion("1.0.0");
-#endif
- app.setWindowIcon(QIcon(QLatin1String(":/icon.svg")));
- // This lets the web view automatically scale on high-dpi displays.
- app.setAttribute(Qt::AA_EnableHighDpiScaling);
+ if(app.isRunning()) {
+ qDebug("Another instance is running, returning...");
+ return 0;
+ }
QCommandLineParser parser;
parser.setApplicationDescription("yet another Qt browser");
@@ -45,12 +40,24 @@ int main(int argc, char *argv[])
parser.addOption(configOption);
QCommandLineOption profileOption(QStringList() << "p" << "profile", "Use this profile.", "PROFILE");
parser.addOption(profileOption);
+ QCommandLineOption nopluginsOption(QStringList() << "n" << "noplugins", "Don't load plugins");
+ parser.addOption(nopluginsOption);
parser.process(app);
+
+ app.setWindowIcon(QIcon(QLatin1String(":/icon.svg")));
+ // This lets the web view automatically scale on high-dpi displays.
+ app.setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ // Set configuration
app.setConfigPath(parser.value(configOption));
- if(!app.prepare(parser.positionalArguments())) {
- return 0;
+ // Load profiles
+ app.loadProfiles();
+
+ // Load plugins
+ if(!parser.isSet(nopluginsOption)) {
+ app.loadPlugins();
}
MainWindow *w = new MainWindow(parser.positionalArguments());
diff --git a/src/singleapplication.cpp b/src/singleapplication.cpp
new file mode 100644
index 0000000..3a23bfb
--- /dev/null
+++ b/src/singleapplication.cpp
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ **
+ ** smolbote: yet another qute browser
+ ** Copyright (C) 2017 Xian Nox
+ **
+ ** This program is free software: you can redistribute it and/or modify
+ ** it under the terms of the GNU General Public License as published by
+ ** the Free Software Foundation, either version 3 of the License, or
+ ** (at your option) any later version.
+ **
+ ** This program is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ** GNU General Public License for more details.
+ **
+ ** You should have received a copy of the GNU General Public License
+ ** along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **
+ ******************************************************************************/
+
+#include "singleapplication.h"
+#include <QLocalSocket>
+
+SingleApplication::SingleApplication(int &argc, char **argv) : QApplication(argc, argv)
+{
+ m_localServer = new QLocalServer(this);
+ connect(m_localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
+
+ // if we can't send the arguments to a listening local server, start one
+ if(!sendMessage(arguments())) {
+ // remove any unused socket
+ QLocalServer::removeServer(LOCALSERVER_KEY);
+ if(!m_localServer->listen(LOCALSERVER_KEY)) {
+ qWarning("Cannot bind local server [%s]", qUtf8Printable(LOCALSERVER_KEY));
+ }
+ }
+
+}
+
+bool SingleApplication::isRunning()
+{
+ return !m_localServer->isListening();
+}
+
+bool SingleApplication::sendMessage(const QStringList &params)
+{
+ QLocalSocket socket;
+ socket.connectToServer(LOCALSERVER_KEY);
+ if(socket.waitForConnected(LOCALSERVER_TIMEOUT)) {
+ socket.write(params.join('|').toUtf8());
+ socket.waitForBytesWritten();
+ return true;
+ }
+
+ return false;
+}
+
+void SingleApplication::receiveMessage()
+{
+ QLocalSocket *socket = m_localServer->nextPendingConnection();
+ if(!socket) {
+ // null socket --> return
+ return;
+ }
+
+ socket->waitForReadyRead();
+ const QStringList params = QString(socket->readAll()).split('|');
+ socket->deleteLater();
+
+ emit messageAvailable(params);
+}
diff --git a/src/singleapplication.h b/src/singleapplication.h
new file mode 100644
index 0000000..7b1fce9
--- /dev/null
+++ b/src/singleapplication.h
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ **
+ ** smolbote: yet another qute browser
+ ** Copyright (C) 2017 Xian Nox
+ **
+ ** This program is free software: you can redistribute it and/or modify
+ ** it under the terms of the GNU General Public License as published by
+ ** the Free Software Foundation, either version 3 of the License, or
+ ** (at your option) any later version.
+ **
+ ** This program is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ** GNU General Public License for more details.
+ **
+ ** You should have received a copy of the GNU General Public License
+ ** along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **
+ ******************************************************************************/
+
+#ifndef SINGLEAPPLICATION_H
+#define SINGLEAPPLICATION_H
+
+#include <QApplication>
+#include <QLocalServer>
+#include <QVector>
+#include <QUrl>
+
+class SingleApplication : public QApplication
+{
+ Q_OBJECT
+public:
+ explicit SingleApplication(int &argc, char **argv);
+
+ bool isRunning();
+ bool sendMessage(const QStringList &params);
+
+signals:
+ void messageAvailable(const QStringList params);
+
+private slots:
+ void receiveMessage();
+
+private:
+ const int LOCALSERVER_TIMEOUT = 500;
+ const QString LOCALSERVER_KEY = "smolbote_KEY";
+
+ QLocalServer *m_localServer;
+};
+
+#endif // SINGLEAPPLICATION_H
diff --git a/src/widgets/mainwindowmenubar.cpp b/src/widgets/mainwindowmenubar.cpp
index cd27a98..4ad9d67 100644
--- a/src/widgets/mainwindowmenubar.cpp
+++ b/src/widgets/mainwindowmenubar.cpp
@@ -54,8 +54,8 @@ MainWindowMenuBar::MainWindowMenuBar(MainWindow *parent) :
toolsMenu->addSeparator();
toolsMenu->addAction(tr("Filter"), qApp->blocklists(), SLOT(show()), QKeySequence::fromString(sSettings->value("blocker.shortcut").toString()));
- if(qApp->plugin()) {
- GuiInterface *gui = qobject_cast<GuiInterface *>(qApp->plugin());
+ if(qApp->plugin("")) {
+ GuiInterface *gui = qobject_cast<GuiInterface *>(qApp->plugin(""));
if(gui) {
toolsMenu->addAction(gui->action());
} else {