Merge pull request #15451 from Ondsel-Development/fix-single-instance-windows

Core: Fix single instance windows
This commit is contained in:
Chris Hennes
2024-07-29 10:42:47 -05:00
committed by GitHub
7 changed files with 58 additions and 38 deletions

View File

@@ -2001,10 +2001,9 @@ bool onlySingleInstance(GUISingleApplication& mainApp)
fn = QDir::cleanPath(fn);
}
QByteArray msg = fn.toUtf8();
msg.prepend("OpenFile:");
if (!mainApp.sendMessage(msg)) {
qWarning("Failed to send message to server");
fn.prepend(QLatin1String("OpenFile:"));
if (!mainApp.sendMessage(fn)) {
qWarning("Failed to send OpenFile message to server");
break;
}
}

View File

@@ -28,7 +28,7 @@
# include <QAbstractSpinBox>
# include <QByteArray>
# include <QComboBox>
# include <QDataStream>
# include <QTextStream>
# include <QFileInfo>
# include <QFileOpenEvent>
# include <QSessionManager>
@@ -218,7 +218,7 @@ public:
QTimer *timer;
QLocalServer *server{nullptr};
QString serverName;
QList<QByteArray> messages;
QList<QString> messages;
bool running{false};
};
@@ -237,15 +237,16 @@ bool GUISingleApplication::isRunning() const
return d_ptr->running;
}
bool GUISingleApplication::sendMessage(const QByteArray &message, int timeout)
bool GUISingleApplication::sendMessage(const QString &message, int timeout)
{
QLocalSocket socket;
bool connected = false;
for(int i = 0; i < 2; i++) {
socket.connectToServer(d_ptr->serverName);
connected = socket.waitForConnected(timeout/2);
if (connected || i > 0)
if (connected || i > 0) {
break;
}
int ms = 250;
#if defined(Q_OS_WIN)
Sleep(DWORD(ms));
@@ -253,41 +254,60 @@ bool GUISingleApplication::sendMessage(const QByteArray &message, int timeout)
usleep(ms*1000);
#endif
}
if (!connected)
if (!connected) {
return false;
}
QDataStream ds(&socket);
ds << message;
socket.waitForBytesWritten(timeout);
return true;
QTextStream ts(&socket);
#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)
ts.setCodec("UTF-8");
#else
ts.setEncoding(QStringConverter::Utf8);
#endif
#if QT_VERSION <= QT_VERSION_CHECK(5, 15, 0)
ts << message << endl;
#else
ts << message << Qt::endl;
#endif
return socket.waitForBytesWritten(timeout);
}
void GUISingleApplication::readFromSocket()
{
auto socket = qobject_cast<QLocalSocket*>(sender());
if (socket) {
QTextStream in(socket);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
in.setCodec("UTF-8");
#else
in.setEncoding(QStringConverter::Utf8);
#endif
while (socket->canReadLine()) {
d_ptr->timer->stop();
QString message = in.readLine();
Base::Console().Log("Received message: %s\n", message.toStdString());
d_ptr->messages.push_back(message);
d_ptr->timer->start(1000);
}
}
}
void GUISingleApplication::receiveConnection()
{
QLocalSocket *socket = d_ptr->server->nextPendingConnection();
if (!socket)
if (!socket) {
return;
}
connect(socket, &QLocalSocket::disconnected,
socket, &QLocalSocket::deleteLater);
if (socket->waitForReadyRead()) {
QDataStream in(socket);
if (!in.atEnd()) {
d_ptr->timer->stop();
QByteArray message;
in >> message;
Base::Console().Log("Received message: %s\n", message.constData());
d_ptr->messages.push_back(message);
d_ptr->timer->start(1000);
}
}
socket->disconnectFromServer();
connect(socket, &QLocalSocket::readyRead, this, &GUISingleApplication::readFromSocket);
}
void GUISingleApplication::processMessages()
{
QList<QByteArray> msg = d_ptr->messages;
QList<QString> msg = d_ptr->messages;
d_ptr->messages.clear();
Q_EMIT messageReceived(msg);
}

View File

@@ -69,14 +69,15 @@ public:
~GUISingleApplication() override;
bool isRunning() const;
bool sendMessage(const QByteArray &message, int timeout = 5000);
bool sendMessage(const QString &message, int timeout = 5000);
private Q_SLOTS:
void receiveConnection();
void processMessages();
void readFromSocket();
Q_SIGNALS:
void messageReceived(const QList<QByteArray> &);
void messageReceived(const QList<QString> &);
private:
class Private;

View File

@@ -1557,16 +1557,16 @@ void MainWindow::hideEvent(QHideEvent* e)
QMainWindow::hideEvent(e);
}
void MainWindow::processMessages(const QList<QByteArray> & msg)
void MainWindow::processMessages(const QList<QString> & msg)
{
// handle all the messages to open files
try {
WaitCursor wc;
std::list<std::string> files;
QByteArray action("OpenFile:");
QString action = QString::fromStdString("OpenFile:");
for (const auto & it : msg) {
if (it.startsWith(action))
files.emplace_back(it.mid(action.size()).constData());
files.emplace_back(it.mid(action.size()).toStdString());
}
files = App::Application::processFiles(files);
for (const auto & file : files) {

View File

@@ -350,7 +350,7 @@ private Q_SLOTS:
/**
* \internal
*/
void processMessages(const QList<QByteArray> &);
void processMessages(const QList<QString> &);
/**
* \internal
*/

View File

@@ -247,8 +247,8 @@ void StartupPostProcess::setWindowTitle()
void StartupPostProcess::setProcessMessages()
{
if (!loadFromPythonModule) {
QObject::connect(qtApp, SIGNAL(messageReceived(const QList<QByteArray> &)),
mainWindow, SLOT(processMessages(const QList<QByteArray> &)));
QObject::connect(qtApp, SIGNAL(messageReceived(const QList<QString> &)),
mainWindow, SLOT(processMessages(const QList<QString> &)));
}
}

View File

@@ -77,12 +77,12 @@ Section -Configure
WriteRegStr SHCTX "${APP_DIR_REGKEY}" "" "$INSTDIR\${APP_RUN}"
WriteRegStr SHCTX "Software\Classes\${APP_REGNAME_DOC}" "" "${APP_NAME} Document"
WriteRegStr SHCTX "Software\Classes\${APP_REGNAME_DOC}\DefaultIcon" "" "$INSTDIR\${APP_RUN},0"
WriteRegStr SHCTX "Software\Classes\${APP_REGNAME_DOC}\Shell\open\command" "" '"$INSTDIR\${APP_RUN}" "%1"'
WriteRegStr SHCTX "Software\Classes\${APP_REGNAME_DOC}\Shell\open\command" "" '"$INSTDIR\${APP_RUN}" --single-instance "%1"'
# we need to update also the automatically created entry about the FreeCAD.exe
# otherwise .FCStd-files will could be opened with an older FreeCAD version
ReadRegStr $0 SHCTX "Software\Classes\Applications\${BIN_FREECAD}\shell\open\command" ""
${if} $0 != "" # if something was found
WriteRegStr SHCTX "Software\Classes\Applications\${BIN_FREECAD}\shell\open\command" "" '"$INSTDIR\${APP_RUN}" "%1"'
WriteRegStr SHCTX "Software\Classes\Applications\${BIN_FREECAD}\shell\open\command" "" '"$INSTDIR\${APP_RUN}" --single-instance "%1"'
${endif}
# .FCStd
WriteRegStr SHCTX "Software\Classes\${APP_EXT}" "" "${APP_REGNAME_DOC}"