#include <ctime>
#include <iostream>
+#include <QDBusConnection>
+#include <QDBusError>
+#include <QDBusMessage>
#include <QDialogButtonBox>
#include <QIcon>
#include <QLabel>
#include <libtransmission/version.h>
#include "app.h"
+#include "dbus-adaptor.h"
#include "mainwin.h"
#include "options.h"
#include "prefs.h"
namespace
{
+ const char * DBUS_SERVICE ( "com.transmissionbt.Transmission" );
+ const char * DBUS_OBJECT_PATH ( "/com/transmissionbt/Transmission" );
+ const char * DBUS_INTERFACE ( "com.transmissionbt.Transmission" );
+
const char * MY_NAME( "transmission" );
const tr_option opts[] =
for( QStringList::const_iterator it=filenames.begin(), end=filenames.end(); it!=end; ++it )
mySession->addTorrent( *it );
+
+ // register as the dbus handler for Transmission
+ new TrDBusAdaptor( this );
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ if (!bus.registerService("com.transmissionbt.Transmission"))
+ fprintf(stderr, "%s\n", qPrintable(bus.lastError().message()));
+ if( !bus.registerObject( "/com/transmissionbt/Transmission", this ))
+ fprintf(stderr, "%s\n", qPrintable(bus.lastError().message()));
}
void
}
}
+/***
+****
+***/
+
void
-MyApp :: addTorrent( const QString& filename )
+MyApp :: addTorrent( const QString& key )
{
- if( myPrefs->getBool( Prefs :: OPTIONS_PROMPT ) ) {
- Options * o = new Options( *mySession, *myPrefs, filename, myWindow );
+ if( !myPrefs->getBool( Prefs :: OPTIONS_PROMPT ) )
+ mySession->addTorrent( key );
+ else if( !QFile( key ).exists( ) )
+ myWindow->openURL( key );
+ else {
+ Options * o = new Options( *mySession, *myPrefs, key, myWindow );
o->show( );
- QApplication :: alert( o );
- } else {
- mySession->addTorrent( filename );
- QApplication :: alert ( myWindow );
}
+ raise( );
}
+void
+MyApp :: raise( )
+{
+ QApplication :: alert ( myWindow );
+}
/***
****
int
main( int argc, char * argv[] )
{
+ // find .torrents, URLs, magnet links, etc in the command-line args
+ int c;
+ QStringList addme;
+ const char * optarg;
+ char ** argvv = argv;
+ while( ( c = tr_getopt( getUsage( ), argc, (const char **)argvv, opts, &optarg ) ) )
+ if( c == TR_OPT_UNK )
+ addme.append( optarg );
+
+ // try to delegate the work to an existing copy of Transmission
+ // before starting ourselves...
+ bool delegated = false;
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ for( int i=0, n=addme.size(); i<n; ++i )
+ {
+ const QString key = addme[i];
+
+ QDBusMessage request = QDBusMessage::createMethodCall( DBUS_SERVICE,
+ DBUS_OBJECT_PATH,
+ DBUS_INTERFACE,
+ "AddMetainfo" );
+ QList<QVariant> arguments;
+ arguments.push_back( QVariant( key ) );
+ request.setArguments( arguments );
+
+ QDBusMessage response = bus.call( request );
+ arguments = response.arguments( );
+ delegated |= (arguments.size()==1) && arguments[0].toBool();
+ }
+ if( addme.empty() )
+ {
+ QDBusMessage request = QDBusMessage::createMethodCall( DBUS_SERVICE,
+ DBUS_OBJECT_PATH,
+ DBUS_INTERFACE,
+ "PresentWindow" );
+ QDBusMessage response = bus.call( request );
+ QList<QVariant> arguments = response.arguments( );
+ delegated |= (arguments.size()==1) && arguments[0].toBool();
+ }
+
+ if( delegated )
+ return 0;
+
+ tr_optind = 1;
MyApp app( argc, argv );
return app.exec( );
}
MyApp( int& argc, char ** argv );
virtual ~MyApp( );
+ public:
+ void raise( );
+
private:
Prefs * myPrefs;
Session * mySession;
void consentGiven( );
void refreshPref( int key );
void refreshTorrents( );
+
+ public slots:
void addTorrent( const QString& );
private:
--- /dev/null
+/*
+ * This file Copyright (C) 2010 Mnemosyne LLC
+ *
+ * This file is licensed by the GPL version 2. Works owned by the
+ * Transmission project are granted a special exemption to clause 2(b)
+ * so that the bulk of its code can remain under the MIT license.
+ * This exemption does not extend to derived works not owned by
+ * the Transmission project.
+ *
+ * $Id:$
+ */
+
+#include "app.h"
+#include "dbus-adaptor.h"
+
+TrDBusAdaptor :: TrDBusAdaptor( MyApp* app ):
+ QDBusAbstractAdaptor( app ),
+ myApp( app )
+{
+}
+
+bool
+TrDBusAdaptor :: PresentWindow( )
+{
+ myApp->raise( );
+ return true;
+}
+
+bool
+TrDBusAdaptor :: AddMetainfo( const QString& str )
+{
+ myApp->addTorrent( str );
+ return true;
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2010 Mnemosyne LLC
+ *
+ * This file is licensed by the GPL version 2. Works owned by the
+ * Transmission project are granted a special exemption to clause 2(b)
+ * so that the bulk of its code can remain under the MIT license.
+ * This exemption does not extend to derived works not owned by
+ * the Transmission project.
+ *
+ * $Id:$
+ */
+
+#ifndef QTR_DBUS_ADAPTOR_H
+#define QTR_DBUS_ADAPTOR_H
+
+class MyApp;
+
+#include <QDBusAbstractAdaptor>
+
+class TrDBusAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO( "D-Bus Interface", "com.transmissionbt.Transmission" )
+
+ private:
+ MyApp * myApp;
+
+ public:
+ TrDBusAdaptor( MyApp* );
+ virtual ~TrDBusAdaptor() { }
+
+ public slots:
+ bool PresentWindow();
+ bool AddMetainfo( const QString& );
+};
+
+#endif
void
TrMainWindow :: openURL( )
+{
+ QString tmp;
+ openURL( tmp );
+}
+
+void
+TrMainWindow :: openURL( QString url )
{
bool ok;
const QString key = QInputDialog::getText( this,
tr( "Add URL or Magnet Link" ),
tr( "Add URL or Magnet Link" ),
QLineEdit::Normal,
- QString( ),
+ url,
&ok );
if( ok && !key.isEmpty( ) )
mySession.addTorrent( key );
void updateNetworkIcon( );
QWidgetList myHidden;
+ public slots:
+ void openURL( QString );
+
private slots:
void onDetailsDestroyed( );
void onShowModeClicked( );
target.path = /bin
INSTALLS += target
-CONFIG += qt thread debug link_pkgconfig
+CONFIG += qt qdbus thread debug link_pkgconfig
QT += network
PKGCONFIG = fontconfig libcurl openssl
FORMS += mainwin.ui
RESOURCES += application.qrc
-SOURCES += about.cc app.cc details.cc file-tree.cc filters.cc hig.cc \
- license.cc mainwin.cc make-dialog.cc options.cc prefs.cc \
+SOURCES += about.cc app.cc dbus-adaptor.cc details.cc file-tree.cc filters.cc \
+ hig.cc license.cc mainwin.cc make-dialog.cc options.cc prefs.cc \
prefs-dialog.cc qticonloader.cc relocate.cc session.cc \
session-dialog.cc squeezelabel.cc stats-dialog.cc torrent.cc \
torrent-delegate.cc torrent-delegate-min.cc torrent-filter.cc \
addTorrent( filename, myPrefs.getString( Prefs::DOWNLOAD_DIR ) );
}
+namespace
+{
+ bool isLink( const QString& str )
+ {
+ return str.startsWith( "magnet:?" )
+ || str.startsWith( "http://" )
+ || str.startsWith( "https://" )
+ || str.startsWith( "ftp://" );
+ }
+}
+
void
Session :: addTorrent( QString key, QString localPath )
{
tr_bencDictAddStr( args, "download-dir", qPrintable(localPath) );
tr_bencDictAddBool( args, "paused", !myPrefs.getBool( Prefs::START ) );
- // if "key" is a readable local file, add it as metadata...
- // otherwise it's probably a URL or magnet link, so pass it along
- // for the daemon to handle
- QFile file( key );
- file.open( QIODevice::ReadOnly );
- const QByteArray raw( file.readAll( ) );
- file.close( );
- if( !raw.isEmpty( ) )
- {
- int b64len = 0;
- char * b64 = tr_base64_encode( raw.constData(), raw.size(), &b64len );
- tr_bencDictAddRaw( args, "metainfo", b64, b64len );
- tr_free( b64 );
- }
- else
- {
+ // figure out what to do with "key"....
+ bool keyHandled = false;
+ if( !keyHandled && isLink( key )) {
tr_bencDictAddStr( args, "filename", key.toUtf8().constData() );
+ keyHandled = true; // it's a URL or magnet link...
+ }
+ if( !keyHandled ) {
+ QFile file( key );
+ file.open( QIODevice::ReadOnly );
+ const QByteArray raw( file.readAll( ) );
+ file.close( );
+ if( !raw.isEmpty( ) ) {
+ int b64len = 0;
+ char * b64 = tr_base64_encode( raw.constData(), raw.size(), &b64len );
+ tr_bencDictAddRaw( args, "metainfo", b64, b64len );
+ tr_free( b64 );
+ keyHandled = true; // it's a local file...
+ }
+ }
+ if( !keyHandled ) {
+ const QByteArray tmp = key.toUtf8();
+ tr_bencDictAddRaw( args, "metainfo", tmp.constData(), tmp.length() );
+ keyHandled; // treat it as base64
}
exec( &top );