Skip to content
Permalink
Browse files

Implement "Application instances manager"

  • Loading branch information...
glassez committed Feb 8, 2019
1 parent c0557c2 commit c7f3693ad1c6ea3b7f86271a2762d15acc4efe49
@@ -719,7 +719,6 @@ ac_user_opts='
enable_option_checking
enable_dependency_tracking
enable_silent_rules
with_qtsingleapplication
enable_debug
enable_stacktrace
enable_gui
@@ -1399,9 +1398,6 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-qtsingleapplication=[system|shipped]
Use the shipped qtsingleapplication library or the
system one (default=shipped)
--with-boost[=ARG] use Boost library from a standard location
(ARG=yes), from the specified location (ARG=<path>),
or disable it (ARG=no) [ARG=yes]
@@ -4187,14 +4183,6 @@ QBT_CXX="$CXX"
# Define --wth-* and --enable-* arguments


# Check whether --with-qtsingleapplication was given.
if test "${with_qtsingleapplication+set}" = set; then :
withval=$with_qtsingleapplication;
else
with_qtsingleapplication=shipped
fi


# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
enableval=$enable_debug;
@@ -5294,23 +5282,6 @@ fi
$as_echo "$as_me: Boost.System LIB: \"$BOOST_SYSTEM_LIB\"" >&6;}
LIBS="$BOOST_SYSTEM_LIB $LIBS"

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which qtsingleapplication to use" >&5
$as_echo_n "checking which qtsingleapplication to use... " >&6; }
case "x$with_qtsingleapplication" in #(
"xshipped") :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shipped" >&5
$as_echo "shipped" >&6; }
QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG usesystemqtsingleapplication" ;; #(
"xsystem") :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
$as_echo "system" >&6; }
QBT_ADD_CONFIG="$QBT_ADD_CONFIG usesystemqtsingleapplication" ;; #(
*) :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_qtsingleapplication" >&5
$as_echo "$with_qtsingleapplication" >&6; }
as_fn_error $? "Unknown option \"$with_qtsingleapplication\". Use either \"system\" or \"shipped\"." "$LINENO" 5 ;;
esac


pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libtorrent" >&5
@@ -14,12 +14,6 @@ QBT_CXX="$CXX"

# Define --wth-* and --enable-* arguments

AC_ARG_WITH(qtsingleapplication,
[AS_HELP_STRING([--with-qtsingleapplication=@<:@system|shipped@:>@],
[Use the shipped qtsingleapplication library or the system one (default=shipped)])],
[],
[with_qtsingleapplication=shipped])

AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug],
[Enable debug build])],
@@ -183,17 +177,6 @@ AX_BOOST_SYSTEM()
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
LIBS="$BOOST_SYSTEM_LIB $LIBS"

AC_MSG_CHECKING([which qtsingleapplication to use])
AS_CASE(["x$with_qtsingleapplication"],
["xshipped"],
[AC_MSG_RESULT([shipped])
QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG usesystemqtsingleapplication"],
["xsystem"],
[AC_MSG_RESULT([system])
QBT_ADD_CONFIG="$QBT_ADD_CONFIG usesystemqtsingleapplication"],
[AC_MSG_RESULT([$with_qtsingleapplication])
AC_MSG_ERROR([Unknown option "$with_qtsingleapplication". Use either "system" or "shipped".])])

PKG_CHECK_MODULES(libtorrent,
[libtorrent-rasterbar >= 1.1.10],
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
@@ -68,18 +68,6 @@ endif()

configure_file(config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h)

find_package(QtSingleApplication)
set_package_properties(QtSingleApplication PROPERTIES
URL "https://code.qt.io/cgit/qt-solutions/qt-solutions.git/"
DESCRIPTION "Qt library to start applications only once per user"
TYPE RECOMMENDED
PURPOSE "Use the system qtsingleapplication library or shipped one otherwise"
)

if (NOT QtSingleApplication_FOUND)
add_subdirectory(app/qtsingleapplication)
endif ()

add_subdirectory(app)
add_subdirectory(base)

@@ -1,12 +1,16 @@
add_executable(qBittorrent
application.h
applicationinstancemanager.h
cmdoptions.h
filelogger.h
qtlocalpeer/qtlocalpeer.h
upgrade.h
application.cpp
applicationinstancemanager.cpp
cmdoptions.cpp
filelogger.cpp
main.cpp
qtlocalpeer/qtlocalpeer.cpp
upgrade.cpp
)

@@ -135,8 +139,6 @@ target_sources(qBittorrent PRIVATE ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE})

get_target_property(QBT_EXECUTABLE_NAME qBittorrent OUTPUT_NAME)

target_link_libraries(qBittorrent PRIVATE ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)

if (APPLE)
set(qbt_BUNDLE_NAME ${QBT_EXECUTABLE_NAME})

@@ -1,30 +1,20 @@
INCLUDEPATH += $$PWD

usesystemqtsingleapplication {
nogui {
CONFIG += qtsinglecoreapplication
} else {
CONFIG += qtsingleapplication
}
} else {
nogui {
include(qtsingleapplication/qtsinglecoreapplication.pri)
} else {
include(qtsingleapplication/qtsingleapplication.pri)
}
}

HEADERS += \
$$PWD/application.h \
$$PWD/applicationinstancemanager.h \
$$PWD/cmdoptions.h \
$$PWD/filelogger.h \
$$PWD/qtlocalpeer/qtlocalpeer.h \
$$PWD/upgrade.h

SOURCES += \
$$PWD/application.cpp \
$$PWD/applicationinstancemanager.cpp \
$$PWD/cmdoptions.cpp \
$$PWD/filelogger.cpp \
$$PWD/main.cpp \
$$PWD/qtlocalpeer/qtlocalpeer.cpp \
$$PWD/upgrade.cpp

stacktrace {
@@ -82,6 +82,7 @@
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/string.h"
#include "applicationinstancemanager.h"
#include "filelogger.h"

#ifndef DISABLE_WEBUI
@@ -116,7 +117,8 @@ namespace
}

Application::Application(const QString &id, int &argc, char **argv)
: BaseApplication(id, argc, argv)
: BaseApplication(argc, argv)
, m_instanceManager(new ApplicationInstanceManager {id, this})
, m_running(false)
, m_shutdownAct(ShutdownDialogAction::Exit)
, m_commandLineArgs(parseCommandLine(this->arguments()))
@@ -156,7 +158,7 @@ Application::Application(const QString &id, int &argc, char **argv)
connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
#endif

connect(this, &Application::messageReceived, this, &Application::processMessage);
connect(m_instanceManager, &ApplicationInstanceManager::messageReceived, this, &Application::processMessage);
connect(this, &QCoreApplication::aboutToQuit, this, &Application::cleanup);

if (isFileLoggerEnabled())
@@ -417,7 +419,7 @@ void Application::allTorrentsFinished()

bool Application::sendParams(const QStringList &params)
{
return sendMessage(params.join(PARAMS_SEPARATOR));
return m_instanceManager->sendMessage(params.join(PARAMS_SEPARATOR));
}

// As program parameters, we can get paths or urls.
@@ -572,34 +574,12 @@ int Application::exec(const QStringList &params)
return BaseApplication::exec();
}

#ifndef DISABLE_GUI
#ifdef Q_OS_WIN
bool Application::isRunning()
{
const bool running = BaseApplication::isRunning();
QSharedMemory *sharedMem = new QSharedMemory(id() + QLatin1String("-shared-memory-key"), this);
if (!running) {
// First instance creates shared memory and store PID
if (sharedMem->create(sizeof(DWORD)) && sharedMem->lock()) {
*(static_cast<DWORD*>(sharedMem->data())) = ::GetCurrentProcessId();
sharedMem->unlock();
}
}
else {
// Later instances attach to shared memory and retrieve PID
if (sharedMem->attach() && sharedMem->lock()) {
::AllowSetForegroundWindow(*(static_cast<DWORD*>(sharedMem->data())));
sharedMem->unlock();
}
}

if (!sharedMem->isAttached())
qWarning() << "Failed to initialize shared memory: " << sharedMem->errorString();

return running;
return !m_instanceManager->isFirstInstance();
}
#endif // Q_OS_WIN

#ifndef DISABLE_GUI
#ifdef Q_OS_MAC
bool Application::event(QEvent *ev)
{
@@ -740,11 +720,11 @@ void Application::cleanup()
#ifndef DISABLE_GUI
if (m_window) {
#ifdef Q_OS_WIN
typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND);
using PSHUTDOWNBRDESTROY = BOOL (WINAPI *)(HWND);
const auto shutdownBRDestroy = Utils::Misc::loadWinAPI<PSHUTDOWNBRDESTROY>("User32.dll", "ShutdownBlockReasonDestroy");
// Only available on Vista+
if (shutdownBRDestroy)
shutdownBRDestroy((HWND)m_window->effectiveWinId());
shutdownBRDestroy(reinterpret_cast<HWND>(m_window->effectiveWinId()));
#endif // Q_OS_WIN
delete m_window;
}
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015, 2019 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@@ -27,25 +27,24 @@
* exception statement from your version.
*/

#ifndef APPLICATION_H
#define APPLICATION_H
#pragma once

#include <QPointer>
#include <QStringList>
#include <QTranslator>

#ifndef DISABLE_GUI
#include "qtsingleapplication.h"
typedef QtSingleApplication BaseApplication;
#include <QApplication>
using BaseApplication = QApplication;
class MainWindow;

#ifdef Q_OS_WIN
class QSessionManager;
#endif // Q_OS_WIN

#else
#include "qtsinglecoreapplication.h"
typedef QtSingleCoreApplication BaseApplication;
#include <QCoreApplication>
using BaseApplication = QCoreApplication;
#endif // DISABLE_GUI

#include "base/types.h"
@@ -55,6 +54,7 @@ typedef QtSingleCoreApplication BaseApplication;
class WebUI;
#endif

class ApplicationInstanceManager;
class FileLogger;

namespace BitTorrent
@@ -77,9 +77,7 @@ class Application : public BaseApplication
Application(const QString &id, int &argc, char **argv);
~Application() override;

#if (defined(Q_OS_WIN) && !defined(DISABLE_GUI))
bool isRunning();
#endif
int exec(const QStringList &params);
bool sendParams(const QStringList &params);

@@ -122,6 +120,7 @@ private slots:
#endif

private:
ApplicationInstanceManager *m_instanceManager;
bool m_running;
ShutdownDialogAction m_shutdownAct;
QBtCommandLineParameters m_commandLineArgs;
@@ -147,5 +146,3 @@ private slots:
void sendNotificationEmail(const BitTorrent::TorrentHandle *torrent);
void validateCommandLineParameters();
};

#endif // APPLICATION_H

0 comments on commit c7f3693

Please sign in to comment.
You can’t perform that action at this time.