mirror of
https://github.com/transmission/transmission
synced 2024-12-21 23:32:35 +00:00
Add ActiveQt-based COM interop helper
This commit is contained in:
parent
35b08ce09e
commit
e92449d91f
10 changed files with 350 additions and 19 deletions
|
@ -223,7 +223,8 @@ if(ENABLE_QT)
|
|||
|
||||
set(QT_TARGETS)
|
||||
if(USE_QT5)
|
||||
set(QT5_REQUIRED_MODULES Core Gui Widgets Network DBus LinguistTools)
|
||||
set(QT5_REQUIRED_MODULES Core Gui Widgets Network LinguistTools)
|
||||
set(QT5_OPTIONAL_MODULES DBus AxContainer AxServer)
|
||||
foreach(M ${QT5_REQUIRED_MODULES})
|
||||
find_package(Qt5${M} QUIET)
|
||||
if(Qt5${M}_FOUND)
|
||||
|
@ -235,9 +236,18 @@ if(ENABLE_QT)
|
|||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(QT_TARGETS)
|
||||
foreach(M ${QT5_OPTIONAL_MODULES})
|
||||
find_package(Qt5${M} QUIET)
|
||||
if(Qt5${M}_FOUND)
|
||||
list(APPEND QT_TARGETS Qt5::${M})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
set(QT4_REQUIRED_MODULES QtCore QtGui QtNetwork QtDBus)
|
||||
find_package(Qt4 4.6.2 QUIET COMPONENTS ${QT4_REQUIRED_MODULES})
|
||||
set(QT4_REQUIRED_MODULES QtCore QtGui QtNetwork)
|
||||
set(QT4_OPTIONAL_MODULES QtDBus QAxContainer QAxServer)
|
||||
find_package(Qt4 4.6.2 QUIET COMPONENTS ${QT4_REQUIRED_MODULES} OPTIONAL_COMPONENTS ${QT4_OPTIONAL_MODULES})
|
||||
foreach(M ${QT4_REQUIRED_MODULES})
|
||||
string(TOUPPER "${M}" M_UPPER)
|
||||
if(QT_${M_UPPER}_FOUND)
|
||||
|
@ -247,6 +257,14 @@ if(ENABLE_QT)
|
|||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (QT_TARGETS)
|
||||
foreach(M ${QT4_OPTIONAL_MODULES})
|
||||
string(TOUPPER "${M}" M_UPPER)
|
||||
if(QT_${M_UPPER}_FOUND)
|
||||
list(APPEND QT_TARGETS Qt4::${M})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(QT_FOUND ON)
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
#include <ctime>
|
||||
#include <iostream>
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusReply>
|
||||
#include <QIcon>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMessageBox>
|
||||
|
@ -20,6 +17,12 @@
|
|||
#include <QRect>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#ifdef QT_DBUS_LIB
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusReply>
|
||||
#endif
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-getopt.h>
|
||||
#include <libtransmission/utils.h>
|
||||
|
@ -27,8 +30,8 @@
|
|||
|
||||
#include "AddData.h"
|
||||
#include "Application.h"
|
||||
#include "DBusInteropHelper.h"
|
||||
#include "Formatter.h"
|
||||
#include "InteropHelper.h"
|
||||
#include "MainWindow.h"
|
||||
#include "OptionsDialog.h"
|
||||
#include "Prefs.h"
|
||||
|
@ -157,7 +160,7 @@ Application::Application (int& argc, char ** argv):
|
|||
|
||||
// try to delegate the work to an existing copy of Transmission
|
||||
// before starting ourselves...
|
||||
DBusInteropHelper interopClient;
|
||||
InteropHelper interopClient;
|
||||
if (interopClient.isConnected ())
|
||||
{
|
||||
bool delegated = false;
|
||||
|
@ -175,11 +178,7 @@ Application::Application (int& argc, char ** argv):
|
|||
default: break;
|
||||
}
|
||||
|
||||
if (metainfo.isEmpty ())
|
||||
continue;
|
||||
|
||||
const QVariant result = interopClient.addMetainfo (metainfo);
|
||||
if (result.isValid () && result.toBool ())
|
||||
if (!metainfo.isEmpty () && interopClient.addMetainfo (metainfo))
|
||||
delegated = true;
|
||||
}
|
||||
|
||||
|
@ -294,7 +293,7 @@ Application::Application (int& argc, char ** argv):
|
|||
for (const QString& filename: filenames)
|
||||
addTorrent (filename);
|
||||
|
||||
DBusInteropHelper::registerObject (this);
|
||||
InteropHelper::registerObject (this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -542,6 +541,7 @@ Application::raise ()
|
|||
bool
|
||||
Application::notifyApp (const QString& title, const QString& body) const
|
||||
{
|
||||
#ifdef QT_DBUS_LIB
|
||||
const QLatin1String dbusServiceName ("org.freedesktop.Notifications");
|
||||
const QLatin1String dbusInterfaceName ("org.freedesktop.Notifications");
|
||||
const QLatin1String dbusPath ("/org/freedesktop/Notifications");
|
||||
|
@ -564,6 +564,7 @@ Application::notifyApp (const QString& title, const QString& body) const
|
|||
if (replyMsg.isValid () && replyMsg.value () > 0)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
myWindow->trayIcon ().showMessage (title, body);
|
||||
return true;
|
||||
|
@ -582,6 +583,8 @@ int
|
|||
tr_main (int argc,
|
||||
char * argv[])
|
||||
{
|
||||
InteropHelper::initialize ();
|
||||
|
||||
Application app (argc, argv);
|
||||
return app.exec ();
|
||||
}
|
||||
|
|
|
@ -22,11 +22,26 @@ else()
|
|||
endmacro()
|
||||
endif()
|
||||
|
||||
set(ENABLE_COM_INTEROP OFF)
|
||||
if(MSVC AND ((Qt5AxContainer_FOUND AND Qt5AxServer_FOUND) OR (QT_QAXCONTAINER_FOUND AND QT_QAXSERVER_FOUND)))
|
||||
set(ENABLE_COM_INTEROP ON)
|
||||
endif()
|
||||
|
||||
set(ENABLE_DBUS_INTEROP OFF)
|
||||
if(Qt5DBus_FOUND OR QT_QTDBUS_FOUND)
|
||||
set(ENABLE_DBUS_INTEROP ON)
|
||||
endif()
|
||||
|
||||
if(NOT ENABLE_COM_INTEROP AND NOT ENABLE_DBUS_INTEROP)
|
||||
message(FATAL_ERROR "Neither D-Bus nor COM interop is possible")
|
||||
endif()
|
||||
|
||||
set(${PROJECT_NAME}_SOURCES
|
||||
AboutDialog.cc
|
||||
AddData.cc
|
||||
Application.cc
|
||||
ColumnResizer.cc
|
||||
ComInteropHelper.cc
|
||||
DBusInteropHelper.cc
|
||||
DetailsDialog.cc
|
||||
FaviconCache.cc
|
||||
|
@ -42,6 +57,7 @@ set(${PROJECT_NAME}_SOURCES
|
|||
Formatter.cc
|
||||
FreeSpaceLabel.cc
|
||||
IconToolButton.cc
|
||||
InteropHelper.cc
|
||||
InteropObject.cc
|
||||
LicenseDialog.cc
|
||||
MainWindow.cc
|
||||
|
@ -69,12 +85,20 @@ set(${PROJECT_NAME}_SOURCES
|
|||
WatchDir.cc
|
||||
)
|
||||
|
||||
if (NOT ENABLE_COM_INTEROP)
|
||||
set_source_files_properties(ComInteropHelper.cc PROPERTIES HEADER_FILE_ONLY ON)
|
||||
endif()
|
||||
if (NOT ENABLE_DBUS_INTEROP)
|
||||
set_source_files_properties(DBusInteropHelper.cc PROPERTIES HEADER_FILE_ONLY ON)
|
||||
endif()
|
||||
|
||||
set(${PROJECT_NAME}_HEADERS
|
||||
AboutDialog.h
|
||||
AddData.h
|
||||
Application.h
|
||||
BaseDialog.h
|
||||
ColumnResizer.h
|
||||
ComInteropHelper.h
|
||||
CustomVariantType.h
|
||||
DBusInteropHelper.h
|
||||
DetailsDialog.h
|
||||
|
@ -91,6 +115,7 @@ set(${PROJECT_NAME}_HEADERS
|
|||
Formatter.h
|
||||
FreeSpaceLabel.h
|
||||
IconToolButton.h
|
||||
InteropHelper.h
|
||||
InteropObject.h
|
||||
LicenseDialog.h
|
||||
MainWindow.h
|
||||
|
@ -182,17 +207,28 @@ include_directories(
|
|||
${EVENT2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_definitions(
|
||||
"-DTRANSLATIONS_DIR=\"${CMAKE_INSTALL_FULL_DATADIR}/${TR_NAME}/translations\""
|
||||
-DQT_NO_CAST_FROM_ASCII
|
||||
)
|
||||
|
||||
tr_win32_app_info(${PROJECT_NAME}_WIN32_RC_FILE
|
||||
"Transmission Qt Client"
|
||||
"transmission-qt"
|
||||
"transmission-qt.exe"
|
||||
"qtr.ico")
|
||||
|
||||
if(ENABLE_COM_INTEROP)
|
||||
find_program(MIDL_EXECUTABLE midl)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/transmission-qt.tlb
|
||||
COMMAND
|
||||
${MIDL_EXECUTABLE} /tlb ${CMAKE_CURRENT_BINARY_DIR}/transmission-qt.tlb transmission-qt.idl
|
||||
DEPENDS
|
||||
transmission-qt.idl
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_WIN32_RC_FILE transmission-qt.tlb.rc transmission-qt.idl ${CMAKE_CURRENT_BINARY_DIR}/transmission-qt.tlb)
|
||||
set_source_files_properties(transmission-qt.idl ${CMAKE_CURRENT_BINARY_DIR}/transmission-qt.tlb PROPERTIES HEADER_FILE_ONLY ON)
|
||||
endif()
|
||||
|
||||
add_executable(${TR_NAME}-qt WIN32
|
||||
${${PROJECT_NAME}_SOURCES}
|
||||
${${PROJECT_NAME}_UI_SOURCES}
|
||||
|
@ -209,6 +245,12 @@ target_link_libraries(${TR_NAME}-qt
|
|||
${EVENT2_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_definitions(${TR_NAME}-qt PRIVATE
|
||||
"TRANSLATIONS_DIR=\"${CMAKE_INSTALL_FULL_DATADIR}/${TR_NAME}/translations\""
|
||||
QT_NO_CAST_FROM_ASCII
|
||||
$<$<BOOL:${ENABLE_COM_INTEROP}>:ENABLE_COM_INTEROP>
|
||||
$<$<BOOL:${ENABLE_DBUS_INTEROP}>:ENABLE_DBUS_INTEROP>)
|
||||
|
||||
if(MSVC)
|
||||
tr_append_target_property(${TR_NAME}-qt LINK_FLAGS "/ENTRY:mainCRTStartup")
|
||||
endif()
|
||||
|
|
68
qt/ComInteropHelper.cc
Normal file
68
qt/ComInteropHelper.cc
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* This file Copyright (C) 2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
|
||||
#include <QAxFactory>
|
||||
#include <QAxObject>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "ComInteropHelper.h"
|
||||
#include "InteropObject.h"
|
||||
|
||||
QAXFACTORY_BEGIN("{1e405fc2-1a3a-468b-8bd6-bfbb58770390}", "{792d1aac-53cc-4dc9-bc29-e5295fdb93a9}")
|
||||
QAXCLASS(InteropObject)
|
||||
QAXFACTORY_END()
|
||||
|
||||
// These are ActiveQt internals; declaring here as I don't like their WinMain much...
|
||||
extern HANDLE qAxInstance;
|
||||
extern bool qAxOutProcServer;
|
||||
extern wchar_t qAxModuleFilename[MAX_PATH];
|
||||
extern QString qAxInit();
|
||||
|
||||
ComInteropHelper::ComInteropHelper ():
|
||||
m_client (new QAxObject (QLatin1String ("Transmission.QtClient")))
|
||||
{
|
||||
}
|
||||
|
||||
ComInteropHelper::~ComInteropHelper ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ComInteropHelper::isConnected () const
|
||||
{
|
||||
return !m_client->isNull ();
|
||||
}
|
||||
|
||||
QVariant
|
||||
ComInteropHelper::addMetainfo (const QString& metainfo)
|
||||
{
|
||||
return m_client->dynamicCall ("AddMetainfo(QString)", metainfo);
|
||||
}
|
||||
|
||||
void
|
||||
ComInteropHelper::initialize ()
|
||||
{
|
||||
qAxOutProcServer = true;
|
||||
::GetModuleFileNameW (0, qAxModuleFilename, MAX_PATH);
|
||||
qAxInstance = ::GetModuleHandleW (NULL);
|
||||
|
||||
::CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
||||
qAxInit ();
|
||||
}
|
||||
|
||||
void
|
||||
ComInteropHelper::registerObject (QObject * parent)
|
||||
{
|
||||
QAxFactory::startServer();
|
||||
QAxFactory::registerActiveObject(new InteropObject (parent));
|
||||
}
|
37
qt/ComInteropHelper.h
Normal file
37
qt/ComInteropHelper.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* This file Copyright (C) 2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef QTR_COM_INTEROP_HELPER_H
|
||||
#define QTR_COM_INTEROP_HELPER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QAxObject;
|
||||
class QObject;
|
||||
class QString;
|
||||
class QVariant;
|
||||
|
||||
class ComInteropHelper
|
||||
{
|
||||
public:
|
||||
ComInteropHelper ();
|
||||
~ComInteropHelper ();
|
||||
|
||||
bool isConnected () const;
|
||||
|
||||
QVariant addMetainfo (const QString& metainfo);
|
||||
|
||||
static void initialize ();
|
||||
static void registerObject (QObject * parent);
|
||||
|
||||
private:
|
||||
std::unique_ptr<QAxObject> m_client;
|
||||
};
|
||||
|
||||
#endif // QTR_COM_INTEROP_HELPER_H
|
70
qt/InteropHelper.cc
Normal file
70
qt/InteropHelper.cc
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* This file Copyright (C) 2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
#include "InteropHelper.h"
|
||||
|
||||
bool
|
||||
InteropHelper::isConnected () const
|
||||
{
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
if (myDbusClient.isConnected ())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
if (myComClient.isConnected ())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
InteropHelper::addMetainfo (const QString& metainfo)
|
||||
{
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
{
|
||||
const QVariant response = myDbusClient.addMetainfo (metainfo);
|
||||
if (response.isValid () && response.toBool ())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
{
|
||||
const QVariant response = myComClient.addMetainfo (metainfo);
|
||||
if (response.isValid () && response.toBool ())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
InteropHelper::initialize ()
|
||||
{
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
ComInteropHelper::initialize ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
InteropHelper::registerObject (QObject * parent)
|
||||
{
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
DBusInteropHelper::registerObject (parent);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
ComInteropHelper::registerObject (parent);
|
||||
#endif
|
||||
}
|
43
qt/InteropHelper.h
Normal file
43
qt/InteropHelper.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file Copyright (C) 2015 Mnemosyne LLC
|
||||
*
|
||||
* It may be used under the GNU GPL versions 2 or 3
|
||||
* or any future license endorsed by Mnemosyne LLC.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef QTR_INTEROP_HELPER_H
|
||||
#define QTR_INTEROP_HELPER_H
|
||||
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
#include "ComInteropHelper.h"
|
||||
#endif
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
#include "DBusInteropHelper.h"
|
||||
#endif
|
||||
|
||||
class QAxObject;
|
||||
class QString;
|
||||
class QVariant;
|
||||
|
||||
class InteropHelper
|
||||
{
|
||||
public:
|
||||
bool isConnected () const;
|
||||
|
||||
bool addMetainfo (const QString& metainfo);
|
||||
|
||||
static void initialize ();
|
||||
static void registerObject (QObject * parent);
|
||||
|
||||
private:
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
DBusInteropHelper myDbusClient;
|
||||
#endif
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
ComInteropHelper myComClient;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // QTR_INTEROP_HELPER_H
|
|
@ -15,7 +15,18 @@
|
|||
class InteropObject: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#ifdef ENABLE_DBUS_INTEROP
|
||||
Q_CLASSINFO ("D-Bus Interface", "com.transmissionbt.Transmission")
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_COM_INTEROP
|
||||
Q_CLASSINFO ("ClassID", "{0e2c952c-0597-491f-ba26-249d7e6fab49}")
|
||||
Q_CLASSINFO ("InterfaceID", "{9402f54f-4906-4f20-ad73-afcfeb5b228d}")
|
||||
Q_CLASSINFO ("RegisterObject", "yes")
|
||||
Q_CLASSINFO ("CoClassAlias", "QtClient")
|
||||
Q_CLASSINFO ("Description", "Transmission Qt Client Class")
|
||||
#endif
|
||||
|
||||
public:
|
||||
InteropObject (QObject * parent = nullptr);
|
||||
|
|
33
qt/transmission-qt.idl
Normal file
33
qt/transmission-qt.idl
Normal file
|
@ -0,0 +1,33 @@
|
|||
import "ocidl.idl";
|
||||
|
||||
[
|
||||
uuid(1E405FC2-1A3A-468B-8BD6-BFBB58770390),
|
||||
version(1.0),
|
||||
helpstring("Transmission Qt Client Type Library 1.0")
|
||||
]
|
||||
library TransmissionLib
|
||||
{
|
||||
[
|
||||
uuid(9402F54F-4906-4F20-AD73-AFCFEB5B228D),
|
||||
helpstring("QtClient Interface")
|
||||
]
|
||||
dispinterface IQtClient
|
||||
{
|
||||
properties:
|
||||
|
||||
methods:
|
||||
[id(1)] VARIANT_BOOL PresentWindow();
|
||||
[id(2)] VARIANT_BOOL AddMetainfo([in] BSTR p_metainfo);
|
||||
};
|
||||
|
||||
[
|
||||
aggregatable,
|
||||
appobject,
|
||||
helpstring("Transmission Qt Client Class"),
|
||||
uuid(0E2C952C-0597-491F-BA26-249D7E6FAB49)
|
||||
]
|
||||
coclass QtClient
|
||||
{
|
||||
[default] dispinterface IQtClient;
|
||||
};
|
||||
};
|
6
qt/transmission-qt.tlb.rc
Normal file
6
qt/transmission-qt.tlb.rc
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "winresrc.h"
|
||||
|
||||
#pragma code_page(1252)
|
||||
|
||||
LANGUAGE 0, 0
|
||||
1 TYPELIB "transmission-qt.tlb"
|
Loading…
Reference in a new issue