{"id":14982557,"url":"https://github.com/itay-grudev/singleapplication","last_synced_at":"2025-05-14T18:06:20.204Z","repository":{"id":6065894,"uuid":"7291677","full_name":"itay-grudev/SingleApplication","owner":"itay-grudev","description":"Replacement of QtSingleApplication for Qt 5 and Qt 6 with support for inter-instance communication.","archived":false,"fork":false,"pushed_at":"2025-04-04T14:34:43.000Z","size":510,"stargazers_count":941,"open_issues_count":14,"forks_count":227,"subscribers_count":42,"default_branch":"master","last_synced_at":"2025-05-14T18:06:12.554Z","etag":null,"topics":["application","c-plus-plus","cpp","hacktoberfest","qt","qt5","qt6","qtsingleapplication","singleapplication","singleton","subsequent-instances"],"latest_commit_sha":null,"homepage":"https://itay-grudev.github.io/SingleApplication/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itay-grudev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"itay-grudev"}},"created_at":"2012-12-23T00:03:18.000Z","updated_at":"2025-04-29T18:51:06.000Z","dependencies_parsed_at":"2024-02-03T20:34:19.601Z","dependency_job_id":"e6e9fbbf-9f77-4d77-8fcd-62a4d67a0e58","html_url":"https://github.com/itay-grudev/SingleApplication","commit_stats":{"total_commits":284,"total_committers":39,"mean_commits":7.282051282051282,"dds":0.7535211267605634,"last_synced_commit":"494772e98cef0aa88124f154feb575cc60b08b38"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itay-grudev%2FSingleApplication","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itay-grudev%2FSingleApplication/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itay-grudev%2FSingleApplication/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itay-grudev%2FSingleApplication/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itay-grudev","download_url":"https://codeload.github.com/itay-grudev/SingleApplication/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198514,"owners_count":22030965,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application","c-plus-plus","cpp","hacktoberfest","qt","qt5","qt6","qtsingleapplication","singleapplication","singleton","subsequent-instances"],"created_at":"2024-09-24T14:05:38.675Z","updated_at":"2025-05-14T18:06:15.194Z","avatar_url":"https://github.com/itay-grudev.png","language":"C++","readme":"# SingleApplication\n\n[![CI](https://github.com/itay-grudev/SingleApplication/workflows/CI:%20Build%20Test/badge.svg?branch=master)](https://github.com/itay-grudev/SingleApplication/actions)\n\nThis is a replacement of the QtSingleApplication for `Qt5` and `Qt6`.\n\nKeeps the Primary Instance of your Application and kills each subsequent\ninstances. It can (if enabled) spawn secondary (non-related to the primary)\ninstances and can send data to the primary instance from secondary instances.\n\n# [Documentation](https://itay-grudev.github.io/SingleApplication/)\n\nYou can find the full usage reference and examples [here](https://itay-grudev.github.io/SingleApplication/classSingleApplication.html).\n\n## Usage\n\nThe `SingleApplication` class inherits from whatever `Q[Core|Gui]Application`\nclass you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the\ndefault). Further usage is similar to the use of the `Q[Core|Gui]Application`\nclasses.\n\nYou can use the library as if you use any other `QCoreApplication` derived\nclass:\n\n```cpp\n#include \u003cQApplication\u003e\n#include \u003cSingleApplication.h\u003e\n\nint main( int argc, char* argv[] )\n{\n    SingleApplication app( argc, argv );\n\n    return app.exec();\n}\n```\n\nTo include the library files I would recommend that you add it as a git\nsubmodule to your project. Here is how:\n\n```bash\ngit submodule add https://github.com/itay-grudev/SingleApplication.git singleapplication\n```\n\n**Qmake:**\n\nThen include the `singleapplication.pri` file in your `.pro` project file.\n\n```qmake\ninclude(singleapplication/singleapplication.pri)\nDEFINES += QAPPLICATION_CLASS=QApplication\n```\n\n**CMake:**\n\nThen include the subdirectory in your `CMakeLists.txt` project file.\n\n```cmake\nset(QAPPLICATION_CLASS QApplication CACHE STRING \"Inheritance class for SingleApplication\")\nadd_subdirectory(src/third-party/singleapplication)\ntarget_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)\n```\n\nDirectly including this repository as a Git submodule, or even just a shallow copy of the\nsource code into new projects might not be ideal when using CMake.\nAnother option is using CMake's `FetchContent` module, available since version `3.11`.\n```cmake\n\n# Define the minumun CMake version, as an example 3.24\ncmake_minimum_required(VERSION 3.24)\n\n# Include the module\ninclude(FetchContent)\n\n# If using Qt6, override DEFAULT_MAJOR_VERSION\nset(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING \"Qt version to use, defaults to 6\")\n\n# Set QAPPLICATION_CLASS\nset(QAPPLICATION_CLASS QApplication CACHE STRING \"Inheritance class for SingleApplication\")\n\n\n# Declare how is the source going to be obtained\nFetchContent_Declare(\n  SingleApplication\n  GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication\n  GIT_TAG        master\n  #GIT_TAG        e22a6bc235281152b0041ce39d4827b961b66ea6\n)\n\n# Fetch the repository and make it available to the build\nFetchContent_MakeAvailable(SingleApplication)\n\n# Then simply use find_package as usual\nfind_package(SingleApplication)\n\n# Finally add it to the target_link_libraries() section\ntarget_link_libraries(ClientePOS PRIVATE\n    Qt${QT_VERSION_MAJOR}::Widgets\n    Qt${QT_VERSION_MAJOR}::Network\n    Qt${QT_VERSION_MAJOR}::Sql\n\n    SingleApplication::SingleApplication\n)\n\n```\n\n\nThe library sets up a `QLocalServer` and a `QSharedMemory` block. The first\ninstance of your Application is your Primary Instance. It would check if the\nshared memory block exists and if not it will start a `QLocalServer` and listen\nfor connections. Each subsequent instance of your application would check if the\nshared memory block exists and if it does, it will connect to the QLocalServer\nto notify the primary instance that a new instance had been started, after which\nit would terminate with status code `0`. In the Primary Instance\n`SingleApplication` would emit the `instanceStarted()` signal upon detecting\nthat a new instance had been started.\n\nThe library uses `stdlib` to terminate the program with the `exit()` function.\n\nAlso don't forget to specify which `QCoreApplication` class your app is using if it\nis not `QCoreApplication` as in examples above.\n\n## Freestanding mode\n\nTraditionally, the functionality of this library is implemented as part of the Qt\napplication class. The base class is defined by the macro `QAPPLICATION_CLASS`.\n\nIn freestanding mode, `SingleApplication` is not derived from a Qt application\nclass. Instead, an instance of a Qt application class is created as normal,\nfollowed by a separate instance of the `SingleApplication` class.\n\n```cpp\n#include \u003cQApplication\u003e\n#include \u003cSingleApplication.h\u003e\n\nint main( int argc, char* argv[] )\n{\n    // The normal application class with a type of your choice\n    QApplication app( argc, argv );\n\n    // Separate single application object (argc and argv are discarded)\n    SingleApplication single( argc, argv /*, options ...*/ );\n\n    // Do your stuff\n\n    return app.exec();\n}\n```\n\n_Note:_ With the discarded arguments and the class name that sounds like a Qt\napplication class without being one, this looks like a workaround – it is a\nworkaround. For 4.x, the single instance functionality could be moved to\nsomething like a `SingleManager` class, which would then be used to implement\n`SingleApplication`. This can't be done in 3.x, because moving\n`SingleApplication::Mode` to `SingleManager::Mode` would be a breaking change.\n\nTo enable the freestanding mode set `QAPPLICATION_CLASS` to\n`FreeStandingSingleApplication`. This is a fake base class with no additional\nfunctionality.\n\nThe standalone mode allows us to use a precompiled version of this library,\nbecause we don't need the `QAPPLICATION_CLASS` macro to define our Qt application\nclass at build time. Furthermore, we can use `std::optional\u003cSingleApplication\u003e`\nto decide at runtime whether we want single application functionality or not.\n\nUse the standard CMake workflow to create a precompiled static library version,\nincluding CMake config files.\n\n```bash\ncmake -DQAPPLICATION_CLASS=FreeStandingSingleApplication -DSINGLEAPPLICATION_INSTALL=ON SingleApplicationDir\ncmake --build .\ncmake --install\n```\n\nThis can be used via:\n\n```cmake\nfind_package(SingleApplication REQUIRED)\ntarget_link_libraries(YourTarget SingleApplication::SingleApplication)\n```\n\n_Note:_ The `QAPPLICATION_CLASS` macro is eliminated during CMake install.\n\n## Instance started signal\n\nThe `SingleApplication` class implements a `instanceStarted()` signal. You can\nbind to that signal to raise your application's window when a new instance had\nbeen started, for example.\n\n```cpp\n// window is a QWindow instance\nQObject::connect(\n    \u0026app,\n    \u0026SingleApplication::instanceStarted,\n    \u0026window,\n    \u0026QWindow::raise\n);\n```\n\nUsing `SingleApplication::instance()` is a neat way to get the\n`SingleApplication` instance for binding to it's signals anywhere in your\nprogram.\n\n_Note:_ On Windows the ability to bring the application windows to the\nforeground is restricted. See [Windows specific implementations](Windows.md)\nfor a workaround and an example implementation.\n\n\n## Secondary Instances\n\nIf you want to be able to launch additional Secondary Instances (not related to\nyour Primary Instance) you have to enable that with the third parameter of the\n`SingleApplication` constructor. The default is `false` meaning no Secondary\nInstances. Here is an example of how you would start a Secondary Instance send\na message with the command line arguments to the primary instance and then shut\ndown.\n\n```cpp\nint main(int argc, char *argv[])\n{\n    SingleApplication app( argc, argv, true );\n\n    if( app.isSecondary() ) {\n        app.sendMessage(  app.arguments().join(' ')).toUtf8() );\n        app.exit( 0 );\n    }\n\n    return app.exec();\n}\n```\n\n_Note:_ A secondary instance won't cause the emission of the\n`instanceStarted()` signal by default. See `SingleApplication::Mode` for more\ndetails.*\n\nYou can check whether your instance is a primary or secondary with the following\nmethods:\n\n```cpp\napp.isPrimary();\n// or\napp.isSecondary();\n```\n\n_Note:_ If your Primary Instance is terminated a newly launched instance\nwill replace the Primary one even if the Secondary flag has been set.*\n\n## Examples\n\nThere are five examples provided in this repository:\n\n* Basic example that prevents a secondary instance from starting [`examples/basic`](examples/basic)\n* An example of a graphical application raising it's parent window [`examples/calculator`](examples/calculator)\n* A console application sending the primary instance it's command line parameters [`examples/sending_arguments`](examples/sending_arguments)\n* A variant of `sending_arguments` where `SingleApplication`is used in freestanding mode [`examples/separate_object`](examples/separate_object)\n* A graphical application with Windows specific additions raising it's parent window [`examples/windows_raise_widget`](examples/windows_raise_widget)\n\n## Versioning\n\nEach major version introduces either very significant changes or is not\nbackwards compatible with the previous version. Minor versions only add\nadditional features, bug fixes or performance improvements and are backwards\ncompatible with the previous release. See [CHANGELOG.md](CHANGELOG.md) for\nmore details.\n\n## Implementation\n\nThe library is implemented with a `QSharedMemory` block which is thread safe and\nguarantees a race condition will not occur. It also uses a `QLocalSocket` to\nnotify the main process that a new instance had been spawned and thus invoke the\n`instanceStarted()` signal and for messaging the primary instance.\n\nAdditionally the library can recover from being forcefully killed on *nix\nsystems and will reset the memory block given that there are no other\ninstances running.\n\n## License\n\nThis library and it's supporting documentation, with the exception of the Qt\ncalculator examples which is distributed under the BSD license, are released\nunder the terms of `The MIT License (MIT)` with an extra condition, that:\n\n```txt\nPermission is not granted to use this software or any of the associated files\nas sample data for the purposes of building machine learning models.\n```\n","funding_links":["https://github.com/sponsors/itay-grudev"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitay-grudev%2Fsingleapplication","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitay-grudev%2Fsingleapplication","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitay-grudev%2Fsingleapplication/lists"}