Introduced SingleInstance class
This commit is contained in:
parent
8c095ec628
commit
cba2e276b2
|
@ -22,6 +22,7 @@ macro(add_target name type)
|
||||||
include/DOtherSide/Utils.h
|
include/DOtherSide/Utils.h
|
||||||
include/DOtherSide/DosDockClicker.h
|
include/DOtherSide/DosDockClicker.h
|
||||||
include/DOtherSide/DOtherSideStatusWindow.h
|
include/DOtherSide/DOtherSideStatusWindow.h
|
||||||
|
include/DOtherSide/DOtherSideSingleInstance.h
|
||||||
src/DOtherSide.cpp
|
src/DOtherSide.cpp
|
||||||
src/DosQMetaObject.cpp
|
src/DosQMetaObject.cpp
|
||||||
src/DosQDeclarative.cpp
|
src/DosQDeclarative.cpp
|
||||||
|
@ -32,6 +33,7 @@ macro(add_target name type)
|
||||||
src/DosQQuickImageProvider.cpp
|
src/DosQQuickImageProvider.cpp
|
||||||
src/DosDockClicker.cpp
|
src/DosDockClicker.cpp
|
||||||
src/DOtherSideStatusWindow.cpp
|
src/DOtherSideStatusWindow.cpp
|
||||||
|
src/DOtherSideSingleInstance.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
|
|
@ -973,6 +973,26 @@ DOS_API int DOS_CALL dos_qdeclarative_qmlregistersingletontype(const QmlRegister
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/// \defgroup SingleInstance SingleInstance
|
||||||
|
/// \brief Functions related to the SingleInstance cclass
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// \brief Create a new SingleInstance class
|
||||||
|
/// \param uniqueName The UTF-8 string for QLocalServer name
|
||||||
|
/// \note The returned SingleInstance should be freed using the dos_singleinstance_delete() function
|
||||||
|
DOS_API DosSingleInstance *DOS_CALL dos_singleinstance_create(const char *uniqueName);
|
||||||
|
|
||||||
|
/// \brief Returns bool indicating whether this is the first instance or not
|
||||||
|
/// \returns true if this is the first instance
|
||||||
|
/// \param vptr The SingleInstance
|
||||||
|
DOS_API bool DOS_CALL dos_singleinstance_isfirst(DosSingleInstance *vptr);
|
||||||
|
|
||||||
|
/// \brief Free the memory allocated for the SingleInstance
|
||||||
|
/// \param vptr The SingleInstance to be freed
|
||||||
|
DOS_API void DOS_CALL dos_singleinstance_delete(DosSingleInstance *vptr);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef SINGLEINSTANCE_H
|
||||||
|
#define SINGLEINSTANCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLocalServer;
|
||||||
|
|
||||||
|
class SingleInstance : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SingleInstance(const QString &uniqueName, QObject *parent = nullptr);
|
||||||
|
~SingleInstance() override;
|
||||||
|
|
||||||
|
bool isFirstInstance() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void secondInstanceDetected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLocalServer *m_localServer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SINGLEINSTANCE_H
|
|
@ -4,8 +4,6 @@
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
|
||||||
class QLocalServer;
|
|
||||||
|
|
||||||
class StatusWindow: public QQuickWindow
|
class StatusWindow: public QQuickWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -15,7 +13,6 @@ class StatusWindow: public QQuickWindow
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit StatusWindow(QWindow *parent = nullptr);
|
explicit StatusWindow(QWindow *parent = nullptr);
|
||||||
~StatusWindow();
|
|
||||||
|
|
||||||
Q_INVOKABLE void toggleFullScreen();
|
Q_INVOKABLE void toggleFullScreen();
|
||||||
|
|
||||||
|
@ -33,14 +30,12 @@ signals:
|
||||||
void secondInstanceDetected();
|
void secondInstanceDetected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkSingleInstance();
|
|
||||||
void removeTitleBar();
|
void removeTitleBar();
|
||||||
void showTitleBar();
|
void showTitleBar();
|
||||||
void initCallbacks();
|
void initCallbacks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isFullScreen;
|
bool m_isFullScreen;
|
||||||
QLocalServer *m_localServer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STATUSWINDOW_H
|
#endif // STATUSWINDOW_H
|
||||||
|
|
|
@ -95,6 +95,9 @@ typedef void DosQQuickImageProvider;
|
||||||
/// A pointer to a QPixmap
|
/// A pointer to a QPixmap
|
||||||
typedef void DosPixmap;
|
typedef void DosPixmap;
|
||||||
|
|
||||||
|
/// A pointer to SingleInstance
|
||||||
|
typedef void DosSingleInstance;
|
||||||
|
|
||||||
/// A pixmap callback to be supplied to an image provider
|
/// A pixmap callback to be supplied to an image provider
|
||||||
/// \param id Image source id
|
/// \param id Image source id
|
||||||
/// \param width pointer to the width of the image
|
/// \param width pointer to the width of the image
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#include "DOtherSide/DosQQuickImageProvider.h"
|
#include "DOtherSide/DosQQuickImageProvider.h"
|
||||||
#include "DOtherSide/DosDockClicker.h"
|
#include "DOtherSide/DosDockClicker.h"
|
||||||
#include "DOtherSide/DOtherSideStatusWindow.h"
|
#include "DOtherSide/DOtherSideStatusWindow.h"
|
||||||
|
#include "DOtherSide/DOtherSideSingleInstance.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -1292,3 +1293,23 @@ char *dos_qurl_replaceHostAndAddPath(char* url, char* newScheme, char* newHost,
|
||||||
|
|
||||||
return convert_to_cstring(newQurl.toString());
|
return convert_to_cstring(newQurl.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DosSingleInstance *dos_singleinstance_create(const char *uniqueName)
|
||||||
|
{
|
||||||
|
return new SingleInstance(QString::fromUtf8(uniqueName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dos_singleinstance_delete(DosSingleInstance *vptr)
|
||||||
|
{
|
||||||
|
auto dsi = static_cast<SingleInstance *>(vptr);
|
||||||
|
delete dsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dos_singleinstance_isfirst(DosSingleInstance *vptr)
|
||||||
|
{
|
||||||
|
auto dsi = static_cast<SingleInstance *>(vptr);
|
||||||
|
if (dsi) {
|
||||||
|
return dsi->isFirstInstance();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "DOtherSide/DOtherSideSingleInstance.h"
|
||||||
|
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
SingleInstance::SingleInstance(const QString &uniqueName, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_localServer(new QLocalServer(this))
|
||||||
|
{
|
||||||
|
QString socketName = uniqueName;
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
socketName = QString("/tmp/%1").arg(socketName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QLocalSocket localSocket;
|
||||||
|
localSocket.connectToServer(socketName);
|
||||||
|
|
||||||
|
// the first instance start will be delayed by this timeout (ms) to ensure there are no other instances.
|
||||||
|
// note: this is an ad-hoc timeout value selected based on prior experience.
|
||||||
|
if (!localSocket.waitForConnected(100)) {
|
||||||
|
connect(m_localServer, &QLocalServer::newConnection, this, &SingleInstance::secondInstanceDetected);
|
||||||
|
if (!m_localServer->listen(socketName)) {
|
||||||
|
qWarning() << "QLocalServer::listen(" << socketName << ") failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleInstance::~SingleInstance()
|
||||||
|
{
|
||||||
|
if (m_localServer->isListening()) {
|
||||||
|
m_localServer->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SingleInstance::isFirstInstance() const
|
||||||
|
{
|
||||||
|
return m_localServer->isListening();
|
||||||
|
}
|
|
@ -1,16 +1,9 @@
|
||||||
#include "DOtherSide/DOtherSideStatusWindow.h"
|
#include "DOtherSide/DOtherSideStatusWindow.h"
|
||||||
|
|
||||||
#include <QLocalServer>
|
|
||||||
#include <QLocalSocket>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QCryptographicHash>
|
|
||||||
|
|
||||||
StatusWindow::StatusWindow(QWindow *parent)
|
StatusWindow::StatusWindow(QWindow *parent)
|
||||||
: QQuickWindow(parent),
|
: QQuickWindow(parent),
|
||||||
m_isFullScreen(false),
|
m_isFullScreen(false)
|
||||||
m_localServer(new QLocalServer(this))
|
|
||||||
{
|
{
|
||||||
checkSingleInstance();
|
|
||||||
removeTitleBar();
|
removeTitleBar();
|
||||||
|
|
||||||
connect(this, &QQuickWindow::windowStateChanged, [&](Qt::WindowState windowState) {
|
connect(this, &QQuickWindow::windowStateChanged, [&](Qt::WindowState windowState) {
|
||||||
|
@ -26,13 +19,6 @@ StatusWindow::StatusWindow(QWindow *parent)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusWindow::~StatusWindow()
|
|
||||||
{
|
|
||||||
if (m_localServer->isListening()) {
|
|
||||||
m_localServer->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusWindow::toggleFullScreen()
|
void StatusWindow::toggleFullScreen()
|
||||||
{
|
{
|
||||||
if (m_isFullScreen) {
|
if (m_isFullScreen) {
|
||||||
|
@ -46,28 +32,3 @@ bool StatusWindow::isFullScreen() const
|
||||||
{
|
{
|
||||||
return m_isFullScreen;
|
return m_isFullScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusWindow::checkSingleInstance()
|
|
||||||
{
|
|
||||||
const auto currentDir = QDir::currentPath();
|
|
||||||
auto socketName = QString(QCryptographicHash::hash(currentDir.toUtf8(), QCryptographicHash::Md5).toHex());
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
socketName = QString("/tmp/%1").arg(socketName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QLocalSocket localSocket;
|
|
||||||
localSocket.connectToServer(socketName);
|
|
||||||
|
|
||||||
// the first instance start will be delayed by this timeout (ms) to ensure there are no other instances.
|
|
||||||
// note: this is an ad-hoc timeout value selected based on prior experience.
|
|
||||||
const bool connected = localSocket.waitForConnected(100);
|
|
||||||
if (!connected) {
|
|
||||||
connect(m_localServer, &QLocalServer::newConnection, this, &StatusWindow::secondInstanceDetected);
|
|
||||||
if (!m_localServer->listen(socketName)) {
|
|
||||||
qWarning() << "QLocalServer::listen(" << socketName << ") failed";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qFatal("Terminating app as the second running instance...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue