mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-26 00:23:55 -07:00
[Application] Add single instance guard and mime types.
Took 2 hours 39 minutes Took 18 minutes Took 5 minutes Took 12 seconds
This commit is contained in:
parent
45d0cedb5c
commit
c413b0627d
8 changed files with 189 additions and 1 deletions
|
|
@ -28,7 +28,9 @@
|
|||
#include "interface/pixel_map_generator.h"
|
||||
#include "interface/theme_manager.h"
|
||||
#include "interface/widgets/dialogs/dlg_settings.h"
|
||||
#include "interface/widgets/tabs/tab_supervisor.h"
|
||||
#include "interface/window_main.h"
|
||||
#include "single_instance_manager.h"
|
||||
#include "version_string.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
|
@ -174,6 +176,7 @@ int main(int argc, char *argv[])
|
|||
SetUnhandledExceptionFilter(CockatriceUnhandledExceptionFilter);
|
||||
#endif
|
||||
|
||||
// Logging setup
|
||||
#ifdef Q_OS_APPLE
|
||||
// <build>/cockatrice/cockatrice.app/Contents/MacOS/cockatrice
|
||||
const QByteArray configPath = "../../../qtlogging.ini";
|
||||
|
|
@ -191,6 +194,7 @@ int main(int argc, char *argv[])
|
|||
// Set the QT_LOGGING_CONF environment variable
|
||||
qputenv("QT_LOGGING_CONF", configPath);
|
||||
}
|
||||
|
||||
qSetMessagePattern(
|
||||
"\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} "
|
||||
"%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{"
|
||||
|
|
@ -200,6 +204,7 @@ int main(int argc, char *argv[])
|
|||
QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
|
||||
|
||||
qInstallMessageHandler(CockatriceLogger);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
app.addLibraryPath(app.applicationDirPath() + "/plugins");
|
||||
#endif
|
||||
|
|
@ -215,6 +220,7 @@ int main(int argc, char *argv[])
|
|||
qApp->setAttribute(Qt::AA_DontShowIconsInMenus, true);
|
||||
#endif
|
||||
|
||||
// Translations
|
||||
#ifdef Q_OS_MAC
|
||||
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
|
||||
#elif defined(Q_OS_WIN)
|
||||
|
|
@ -223,6 +229,7 @@ int main(int argc, char *argv[])
|
|||
translationPath = qApp->applicationDirPath() + "/../share/cockatrice/translations";
|
||||
#endif
|
||||
|
||||
// Command-line parser
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Cockatrice");
|
||||
parser.addHelpOption();
|
||||
|
|
@ -271,6 +278,21 @@ int main(int argc, char *argv[])
|
|||
// then reload the DB. otherwise just reload the DB
|
||||
SpoilerBackgroundUpdater spoilerBackgroundUpdater;
|
||||
|
||||
// --- Handle files or URLs passed at startup ---
|
||||
SingleInstanceManager instance;
|
||||
QStringList startupFiles;
|
||||
|
||||
// Collect command-line files/URLs
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
QString arg = QString::fromLocal8Bit(argv[i]);
|
||||
startupFiles.append(arg);
|
||||
}
|
||||
|
||||
if (!instance.tryRun(startupFiles)) {
|
||||
// Another instance received our files, exit
|
||||
return 0;
|
||||
}
|
||||
|
||||
ui.show();
|
||||
qCInfo(MainLog) << "ui.show() finished";
|
||||
|
||||
|
|
@ -280,7 +302,47 @@ int main(int argc, char *argv[])
|
|||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
app.exec();
|
||||
|
||||
for (const QString &file : startupFiles) {
|
||||
if (file.startsWith("cockatrice://")) {
|
||||
// ui.openUrl(QUrl(file));
|
||||
} else if (QFileInfo(file).exists()) {
|
||||
std::optional<LoadedDeck> deckOpt =
|
||||
DeckLoader::loadFromFile(file, DeckFileFormat::getFormatFromName(file), true);
|
||||
if (deckOpt) {
|
||||
ui.getTabSupervisor()->openDeckInNewTab(deckOpt.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to future file/URL events from other instances
|
||||
QObject::connect(&instance, &SingleInstanceManager::filesReceived, [&ui](const QStringList &files) {
|
||||
for (const QString &file : files) {
|
||||
if (file.startsWith("cockatrice://")) {
|
||||
// ui.openUrl(QUrl(file));
|
||||
} else if (QFileInfo(file).exists()) {
|
||||
std::optional<LoadedDeck> deckOpt =
|
||||
DeckLoader::loadFromFile(file, DeckFileFormat::getFormatFromName(file), true);
|
||||
if (deckOpt) {
|
||||
ui.getTabSupervisor()->openDeckInNewTab(deckOpt.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// macOS: handle files opened via Finder after startup
|
||||
QObject::connect(&app, &QApplication::fileOpen, [&ui](const QString &filePath) {
|
||||
qDebug() << "macOS opened file:" << filePath;
|
||||
std::optional<LoadedDeck> deckOpt =
|
||||
DeckLoader::loadFromFile(filePath, DeckFileFormat::getFormatFromName(filePath), true);
|
||||
if (deckOpt) {
|
||||
ui.getTabSupervisor()->openDeckInNewTab(deckOpt.value());
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
int ret = app.exec();
|
||||
|
||||
qCInfo(MainLog) << "Event loop finished, terminating...";
|
||||
delete rng;
|
||||
|
|
|
|||
1
cockatrice/src/single_instance_manager.cpp
Normal file
1
cockatrice/src/single_instance_manager.cpp
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include "single_instance_manager.h"
|
||||
66
cockatrice/src/single_instance_manager.h
Normal file
66
cockatrice/src/single_instance_manager.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||
#define COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
|
||||
class SingleInstanceManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SingleInstanceManager(QObject *parent = nullptr) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool tryRun(const QStringList &initialFiles)
|
||||
{
|
||||
serverName = "CockatriceSingleInstance";
|
||||
|
||||
QLocalSocket socket;
|
||||
socket.connectToServer(serverName);
|
||||
if (socket.waitForConnected(100)) {
|
||||
// Another instance is running, send files/URLs to it
|
||||
QDataStream out(&socket);
|
||||
out << initialFiles;
|
||||
socket.flush();
|
||||
socket.waitForBytesWritten(1000);
|
||||
|
||||
return false; // Do not continue in this process
|
||||
}
|
||||
|
||||
// No other instance, create server
|
||||
server = new QLocalServer(this);
|
||||
connect(server, &QLocalServer::newConnection, this, &SingleInstanceManager::receiveFiles);
|
||||
if (!server->listen(serverName)) {
|
||||
QLocalServer::removeServer(serverName);
|
||||
server->listen(serverName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
signals:
|
||||
void filesReceived(const QStringList &files);
|
||||
|
||||
private slots:
|
||||
void receiveFiles()
|
||||
{
|
||||
QLocalSocket *clientConnection = server->nextPendingConnection();
|
||||
connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
|
||||
clientConnection->waitForReadyRead(1000);
|
||||
|
||||
QDataStream in(clientConnection);
|
||||
QStringList files;
|
||||
in >> files;
|
||||
|
||||
emit filesReceived(files);
|
||||
clientConnection->disconnectFromServer();
|
||||
}
|
||||
|
||||
private:
|
||||
QString serverName;
|
||||
QLocalServer *server = nullptr;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue