Enable app class independent usage (#203)
Some checks failed
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j2, -D QT_DEFAULT_MAJOR_VERSION=6, make, ubuntu-20.04, 6.2.4) (push) Failing after 9s
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j2, -D QT_DEFAULT_MAJOR_VERSION=6, make, ubuntu-20.04, 6.5.0) (push) Failing after 9s
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j2, make, ubuntu-20.04, 5.15.0) (push) Failing after 9s
Documentation / Doxygen (push) Failing after 3h14m57s
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j3, -D QT_DEFAULT_MAJOR_VERSION=6, make, macos-13, 6.2.4) (push) Has been cancelled
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j3, -D QT_DEFAULT_MAJOR_VERSION=6, make, macos-13, 6.5.0) (push) Has been cancelled
CI: Build Test / Build (-Wall -Wextra -pedantic -Werror, -j3, make, macos-13, 5.15.0) (push) Has been cancelled
CI: Build Test / Build (/W4 /WX /MP, -D QT_DEFAULT_MAJOR_VERSION=6, nmake, windows-latest, 6.2.4) (push) Has been cancelled
CI: Build Test / Build (/W4 /WX /MP, -D QT_DEFAULT_MAJOR_VERSION=6, nmake, windows-latest, 6.5.0) (push) Has been cancelled
CI: Build Test / Build (/W4 /WX /MP, nmake, windows-latest, 5.15.0) (push) Has been cancelled

This is a pure extension and fully backwards compatible.

* Adds support for running it as a pre-compiled library while still being able to
choose my `QXxxApplication` class at build time.
* Be able to decide at runtime whether to use the single
instance stuff (without starting a server and so on).
This commit is contained in:
Benjamin Buch 2025-01-24 15:05:53 +01:00 committed by GitHub
parent 565ebd1c3d
commit 0ba7b6ce42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 365 additions and 19 deletions

View File

@ -80,6 +80,12 @@ jobs:
cmake . ${{ matrix.additional_arguments }} cmake . ${{ matrix.additional_arguments }}
cmake --build . cmake --build .
- name: Build separate_object example with CMake
working-directory: examples/separate_object/
run: |
cmake . ${{ matrix.additional_arguments }}
cmake --build .
- name: Build windows_raise_widget example with CMake - name: Build windows_raise_widget example with CMake
working-directory: examples/windows_raise_widget/ working-directory: examples/windows_raise_widget/
run: | run: |
@ -107,6 +113,13 @@ jobs:
qmake qmake
${{ matrix.make }} ${{ matrix.make }}
- name: Build separate_object example with QMake
if: ${{ !contains(matrix.platform, 'macos') }}
working-directory: examples/separate_object/
run: |
qmake
${{ matrix.make }}
- name: Build windows_raise_widget example with QMake - name: Build windows_raise_widget example with QMake
if: ${{ !contains(matrix.platform, 'macos') }} if: ${{ !contains(matrix.platform, 'macos') }}
working-directory: examples/windows_raise_widget/ working-directory: examples/windows_raise_widget/

View File

@ -1,5 +1,10 @@
# Changelog # Changelog
## 3.6.0
* Freestanding mode where `SingleApplication` doesn't derive from `QCodeApplication` _Benjamin Buch_
* CMake install with CMake config files for freestanding mode _Benjamin Buch_
## 3.5.1 ## 3.5.1
* Bug Fix: Maximum QNativeIpcKey key size on macOS. - _Jonas Kvinge_ * Bug Fix: Maximum QNativeIpcKey key size on macOS. - _Jonas Kvinge_

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.12.0) cmake_minimum_required(VERSION 3.12.0)
project(SingleApplication LANGUAGES CXX DESCRIPTION "Replacement for QtSingleApplication") project(SingleApplication VERSION 3.6.0 LANGUAGES CXX DESCRIPTION "Replacement for QtSingleApplication")
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@ -8,12 +8,22 @@ add_library(${PROJECT_NAME} STATIC
singleapplication.cpp singleapplication.cpp
singleapplication_p.cpp singleapplication_p.cpp
) )
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
# User configurable options
if(NOT QT_DEFAULT_MAJOR_VERSION) if(NOT QT_DEFAULT_MAJOR_VERSION)
set(QT_DEFAULT_MAJOR_VERSION 5 CACHE STRING "Qt version to use (5 or 6), defaults to 5") set(QT_DEFAULT_MAJOR_VERSION 5 CACHE STRING "Qt version to use (5 or 6), defaults to 5")
endif() endif()
if(NOT QAPPLICATION_CLASS)
set(QAPPLICATION_CLASS QCoreApplication CACHE STRING "Qt application base class or FreeStandingSingleApplication")
endif()
option(SINGLEAPPLICATION_INSTALL OFF "Enable freestanding mode install including config files")
if(SINGLEAPPLICATION_INSTALL AND NOT QAPPLICATION_CLASS STREQUAL "FreeStandingSingleApplication")
message(FATAL_ERROR "SINGLEAPPLICATION_INSTALL requires QAPPLICATION_CLASS == FreeStandingSingleApplication")
endif()
# Find dependencies # Find dependencies
set(QT_COMPONENTS Core Network) set(QT_COMPONENTS Core Network)
set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network) set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network)
@ -24,8 +34,6 @@ if(QAPPLICATION_CLASS STREQUAL QApplication)
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication) elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
list(APPEND QT_COMPONENTS Gui) list(APPEND QT_COMPONENTS Gui)
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui) list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui)
else()
set(QAPPLICATION_CLASS QCoreApplication)
endif() endif()
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED) find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED)
@ -41,8 +49,15 @@ if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE advapi32) target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
endif() endif()
if(SINGLEAPPLICATION_INSTALL)
target_compile_definitions(${PROJECT_NAME} PRIVATE QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
else()
target_compile_definitions(${PROJECT_NAME} PUBLIC QAPPLICATION_CLASS=${QAPPLICATION_CLASS}) target_compile_definitions(${PROJECT_NAME} PUBLIC QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE target_compile_definitions(${PROJECT_NAME} PRIVATE
QT_NO_CAST_TO_ASCII QT_NO_CAST_TO_ASCII
QT_NO_CAST_FROM_ASCII QT_NO_CAST_FROM_ASCII
@ -81,3 +96,52 @@ if(DOXYGEN_FOUND)
README.md README.md
) )
endif() endif()
if(SINGLEAPPLICATION_INSTALL)
# Create a header veriant where QAPPLICATION_CLASS is replaced with FreeStandingSingleApplication
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/singleapplication.h" SINGLEAPPLICATION_H_CONTENT)
string(REGEX REPLACE
"#ifndef QAPPLICATION_CLASS[^\n]*\n[ \t]*#define QAPPLICATION_CLASS QCoreApplication[^\n]*\n[ \t]*#endif[^\n]*\n"
""
SINGLEAPPLICATION_H_CONTENT
"${SINGLEAPPLICATION_H_CONTENT}")
string(REGEX REPLACE
"#include QT_STRINGIFY\\(QAPPLICATION_CLASS\\)"
"#include \"FreeStandingSingleApplication\""
SINGLEAPPLICATION_H_CONTENT
"${SINGLEAPPLICATION_H_CONTENT}")
string(REPLACE
"QAPPLICATION_CLASS"
"FreeStandingSingleApplication"
SINGLEAPPLICATION_H_CONTENT
"${SINGLEAPPLICATION_H_CONTENT}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/singleapplication.h" "${SINGLEAPPLICATION_H_CONTENT}")
# CMake install
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/singleapplication.h" "SingleApplication" "FreeStandingSingleApplication"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"SingleApplicationConfigVersion.cmake"
VERSION "${PACKAGE_VERSION}"
COMPATIBILITY SameMajorVersion)
configure_file("SingleApplicationConfig.cmake.in" "SingleApplicationConfig.cmake" @ONLY)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/SingleApplicationConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/SingleApplicationConfigVersion.cmake"
DESTINATION "lib/cmake/SingleApplication")
install(TARGETS SingleApplication EXPORT SingleApplicationTargets)
install(EXPORT SingleApplicationTargets
FILE "SingleApplicationTargets.cmake"
NAMESPACE "SingleApplication::"
DESTINATION "lib/cmake/SingleApplication")
else()
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
endif()

View File

@ -0,0 +1,41 @@
// Copyright (c) Itay Grudev 2015 - 2023
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// Permission is not granted to use this software or any of the associated files
// as sample data for the purposes of building machine learning models.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FREE_STANDING_SINGLE_APPLICATION_H
#define FREE_STANDING_SINGLE_APPLICATION_H
#include <QCoreApplication>
/**
* @brief Fake Qt application base class
* Use this as base if you want to use SingleApplication as a free standing object that must be
* explicitly instanciated after your Qt application object.
*
* This enables you to use SingleApplication as a precompiled library and/or to decide at runtime
* if you want to use a SingleApplication instance or not.
*/
struct FreeStandingSingleApplication: QObject{
FreeStandingSingleApplication( int&, char** ) {}
};
#endif

View File

@ -119,6 +119,67 @@ The library uses `stdlib` to terminate the program with the `exit()` function.
Also don't forget to specify which `QCoreApplication` class your app is using if it Also don't forget to specify which `QCoreApplication` class your app is using if it
is not `QCoreApplication` as in examples above. is not `QCoreApplication` as in examples above.
## Freestanding mode
Traditionally, the functionality of this library is implemented as part of the Qt
application class. The base class is defined by the macro `QAPPLICATION_CLASS`.
In freestanding mode, `SingleApplication` is not derived from a Qt application
class. Instead, an instance of a Qt application class is created as normal,
followed by a separate instance of the `SingleApplication` class.
```cpp
#include <QApplication>
#include <SingleApplication.h>
int main( int argc, char* argv[] )
{
// The normal application class with a type of your choice
QApplication app( argc, argv );
// Separate single application object (argc and argv are discarded)
SingleApplication single( argc, argv /*, options ...*/ );
// Do your stuff
return app.exec();
}
```
_Note:_ With the discarded arguments and the class name that sounds like a Qt
application class without being one, this looks like a workaround it is a
workaround. For 4.x, the single instance functionality could be moved to
something like a `SingleManager` class, which would then be used to implement
`SingleApplication`. This can't be done in 3.x, because moving
`SingleApplication::Mode` to `SingleManager::Mode` would be a breaking change.
To enable the freestanding mode set `QAPPLICATION_CLASS` to
`FreeStandingSingleApplication`. This is a fake base class with no additional
functionality.
The standalone mode allows us to use a precompiled version of this library,
because we don't need the `QAPPLICATION_CLASS` macro to define our Qt application
class at build time. Furthermore, we can use `std::optional<SingleApplication>`
to decide at runtime whether we want single application functionality or not.
Use the standard CMake workflow to create a precompiled static library version,
including CMake config files.
```bash
cmake -DQAPPLICATION_CLASS=FreeStandingSingleApplication -DSINGLEAPPLICATION_INSTALL=ON SingleApplicationDir
cmake --build .
cmake --install
```
This can be used via:
```cmake
find_package(SingleApplication REQUIRED)
target_link_libraries(YourTarget SingleApplication::SingleApplication)
```
_Note:_ The `QAPPLICATION_CLASS` macro is eliminated during CMake install.
## Instance started signal ## Instance started signal
The `SingleApplication` class implements a `instanceStarted()` signal. You can The `SingleApplication` class implements a `instanceStarted()` signal. You can
@ -185,11 +246,13 @@ will replace the Primary one even if the Secondary flag has been set.*
## Examples ## Examples
There are three examples provided in this repository: There are five examples provided in this repository:
* Basic example that prevents a secondary instance from starting [`examples/basic`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/basic) * Basic example that prevents a secondary instance from starting [`examples/basic`](examples/basic)
* An example of a graphical application raising it's parent window [`examples/calculator`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/calculator) * An example of a graphical application raising it's parent window [`examples/calculator`](examples/calculator)
* A console application sending the primary instance it's command line parameters [`examples/sending_arguments`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/sending_arguments) * A console application sending the primary instance it's command line parameters [`examples/sending_arguments`](examples/sending_arguments)
* A variant of `sending_arguments` where `SingleApplication`is used in freestanding mode [`examples/separate_object`](examples/separate_object)
* A graphical application with Windows specific additions raising it's parent window [`examples/windows_raise_widget`](examples/windows_raise_widget)
## Versioning ## Versioning

View File

@ -0,0 +1,5 @@
include(CMakeFindDependencyMacro)
find_dependency(Qt@QT_DEFAULT_MAJOR_VERSION@ COMPONENTS Core Network REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/SingleApplicationTargets.cmake")

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.7.0)
project(separate_object LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
# SingleApplication base class
set(QAPPLICATION_CLASS FreeStandingSingleApplication)
add_subdirectory(../.. SingleApplication)
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core REQUIRED)
add_executable(${PROJECT_NAME}
main.cpp
messagereceiver.cpp
messagereceiver.h
main.cpp
)
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)

View File

@ -0,0 +1,53 @@
// Copyright (c) Itay Grudev 2015 - 2023
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// Permission is not granted to use this software or any of the associated files
// as sample data for the purposes of building machine learning models.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <singleapplication.h>
#include "messagereceiver.h"
int main(int argc, char *argv[])
{
QCoreApplication app( argc, argv );
// Separate single instance object (that allows secondary instances)
SingleApplication single_instance_guard( argc, argv, true );
MessageReceiver msgReceiver;
// If this is a secondary instance
if( single_instance_guard.isSecondary() ) {
single_instance_guard.sendMessage( app.arguments().join(' ').toUtf8() );
qDebug() << "App already running.";
qDebug() << "Primary instance PID: " << single_instance_guard.primaryPid();
qDebug() << "Primary instance user: " << single_instance_guard.primaryUser();
return 0;
} else {
QObject::connect(
&single_instance_guard,
&SingleApplication::receivedMessage,
&msgReceiver,
&MessageReceiver::receivedMessage
);
}
return app.exec();
}

View File

@ -0,0 +1,35 @@
// Copyright (c) Itay Grudev 2015 - 2023
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// Permission is not granted to use this software or any of the associated files
// as sample data for the purposes of building machine learning models.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <QDebug>
#include "messagereceiver.h"
MessageReceiver::MessageReceiver(QObject *parent) : QObject(parent)
{
}
void MessageReceiver::receivedMessage(int instanceId, QByteArray message)
{
qDebug() << "Received message from instance: " << instanceId;
qDebug() << "Message Text: " << message;
}

View File

@ -0,0 +1,38 @@
// Copyright (c) Itay Grudev 2015 - 2023
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// Permission is not granted to use this software or any of the associated files
// as sample data for the purposes of building machine learning models.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef MESSAGERECEIVER_H
#define MESSAGERECEIVER_H
#include <QObject>
class MessageReceiver : public QObject
{
Q_OBJECT
public:
explicit MessageReceiver(QObject *parent = 0);
public slots:
void receivedMessage( int instanceId, QByteArray message );
};
#endif // MESSAGERECEIVER_H

View File

@ -0,0 +1,9 @@
# Single Application implementation
include(../../singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=FreeStandingSingleApplication
SOURCES += main.cpp \
messagereceiver.cpp
HEADERS += \
messagereceiver.h

View File

@ -142,31 +142,31 @@ void SingleApplicationPrivate::genBlockServerName()
#else #else
appData.addData( QByteArrayView{"SingleApplication"} ); appData.addData( QByteArrayView{"SingleApplication"} );
#endif #endif
appData.addData( SingleApplication::app_t::applicationName().toUtf8() ); appData.addData( QCoreApplication::applicationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationName().toUtf8() ); appData.addData( QCoreApplication::organizationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() ); appData.addData( QCoreApplication::organizationDomain().toUtf8() );
if ( ! appDataList.isEmpty() ) if ( ! appDataList.isEmpty() )
appData.addData( appDataList.join(QString()).toUtf8() ); appData.addData( appDataList.join(QString()).toUtf8() );
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){ if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() ); appData.addData( QCoreApplication::applicationVersion().toUtf8() );
} }
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){ if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() ); appData.addData( QCoreApplication::applicationFilePath().toLower().toUtf8() );
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
// If the application is running as an AppImage then the APPIMAGE env var should be used // If the application is running as an AppImage then the APPIMAGE env var should be used
// instead of applicationPath() as each instance is launched with its own executable path // instead of applicationPath() as each instance is launched with its own executable path
const QByteArray appImagePath = qgetenv( "APPIMAGE" ); const QByteArray appImagePath = qgetenv( "APPIMAGE" );
if( appImagePath.isEmpty() ){ // Not running as AppImage: use path to executable file if( appImagePath.isEmpty() ){ // Not running as AppImage: use path to executable file
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() ); appData.addData( QCoreApplication::applicationFilePath().toUtf8() );
} else { // Running as AppImage: Use absolute path to AppImage file } else { // Running as AppImage: Use absolute path to AppImage file
appData.addData( appImagePath ); appData.addData( appImagePath );
}; };
#else #else
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() ); appData.addData( QCoreApplication::applicationFilePath().toUtf8() );
#endif #endif
} }