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)
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)
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)
#include <ctime>
#include <iostream>
-#include <QDBusConnection>
-#include <QDBusMessage>
-#include <QDBusReply>
#include <QIcon>
#include <QLibraryInfo>
#include <QMessageBox>
#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>
#include "AddData.h"
#include "Application.h"
-#include "DBusInteropHelper.h"
#include "Formatter.h"
+#include "InteropHelper.h"
#include "MainWindow.h"
#include "OptionsDialog.h"
#include "Prefs.h"
// try to delegate the work to an existing copy of Transmission
// before starting ourselves...
- DBusInteropHelper interopClient;
+ InteropHelper interopClient;
if (interopClient.isConnected ())
{
bool delegated = false;
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;
}
for (const QString& filename: filenames)
addTorrent (filename);
- DBusInteropHelper::registerObject (this);
+ InteropHelper::registerObject (this);
}
void
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");
if (replyMsg.isValid () && replyMsg.value () > 0)
return true;
}
+#endif
myWindow->trayIcon ().showMessage (title, body);
return true;
tr_main (int argc,
char * argv[])
{
+ InteropHelper::initialize ();
+
Application app (argc, argv);
return app.exec ();
}
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
Formatter.cc
FreeSpaceLabel.cc
IconToolButton.cc
+ InteropHelper.cc
InteropObject.cc
LicenseDialog.cc
MainWindow.cc
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
Formatter.h
FreeSpaceLabel.h
IconToolButton.h
+ InteropHelper.h
InteropObject.h
LicenseDialog.h
MainWindow.h
${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}
${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()
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * 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
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);
--- /dev/null
+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;
+ };
+};
--- /dev/null
+#include "winresrc.h"
+
+#pragma code_page(1252)
+
+LANGUAGE 0, 0
+1 TYPELIB "transmission-qt.tlb"