(trunk qt) #2840 "opening magnets with qt client opens new instances" -- fixed in trunk for 2.00

This commit is contained in:
Charles Kerr 2010-04-27 03:10:32 +00:00
parent 04272a6c30
commit 487783d1e2
8 changed files with 200 additions and 27 deletions

View File

@ -14,6 +14,9 @@
#include <ctime>
#include <iostream>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusMessage>
#include <QDialogButtonBox>
#include <QIcon>
#include <QLabel>
@ -26,6 +29,7 @@
#include <libtransmission/version.h>
#include "app.h"
#include "dbus-adaptor.h"
#include "mainwin.h"
#include "options.h"
#include "prefs.h"
@ -37,6 +41,10 @@
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[] =
@ -218,6 +226,14 @@ MyApp :: MyApp( int& argc, char ** argv ):
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
@ -298,19 +314,29 @@ MyApp :: refreshTorrents( )
}
}
/***
****
***/
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 );
}
/***
****
@ -319,6 +345,50 @@ MyApp :: addTorrent( const QString& filename )
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( );
}

View File

@ -30,6 +30,9 @@ class MyApp: public QApplication
MyApp( int& argc, char ** argv );
virtual ~MyApp( );
public:
void raise( );
private:
Prefs * myPrefs;
Session * mySession;
@ -45,6 +48,8 @@ class MyApp: public QApplication
void consentGiven( );
void refreshPref( int key );
void refreshTorrents( );
public slots:
void addTorrent( const QString& );
private:

34
qt/dbus-adaptor.cc Normal file
View File

@ -0,0 +1,34 @@
/*
* 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;
}

37
qt/dbus-adaptor.h Normal file
View File

@ -0,0 +1,37 @@
/*
* 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

View File

@ -1114,13 +1114,20 @@ TrMainWindow :: openTorrent( )
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 );

View File

@ -91,6 +91,9 @@ class TrMainWindow: public QMainWindow
void updateNetworkIcon( );
QWidgetList myHidden;
public slots:
void openURL( QString );
private slots:
void onDetailsDestroyed( );
void onShowModeClicked( );

View File

@ -7,7 +7,7 @@ LICENSE = "GPL"
target.path = /bin
INSTALLS += target
CONFIG += qt thread debug link_pkgconfig
CONFIG += qt qdbus thread debug link_pkgconfig
QT += network
PKGCONFIG = fontconfig libcurl openssl
@ -23,8 +23,8 @@ TRANSLATIONS += transmission_en.ts transmission_ru.ts
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 \

View File

@ -858,6 +858,17 @@ Session :: addTorrent( QString filename )
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 )
{
@ -868,23 +879,29 @@ 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 );