]> granicus.if.org Git - transmission/commitdiff
(trunk qt) #2840 "opening magnets with qt client opens new instances" -- fixed in...
authorCharles Kerr <charles@transmissionbt.com>
Tue, 27 Apr 2010 03:10:32 +0000 (03:10 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Tue, 27 Apr 2010 03:10:32 +0000 (03:10 +0000)
qt/app.cc
qt/app.h
qt/dbus-adaptor.cc [new file with mode: 0644]
qt/dbus-adaptor.h [new file with mode: 0644]
qt/mainwin.cc
qt/mainwin.h
qt/qtr.pro
qt/session.cc

index 3b5199967ee6437eaaec1ebf434fda3340a81f36..431bc432d922ab55c0ac6d969002eac4323392d1 100644 (file)
--- a/qt/app.cc
+++ b/qt/app.cc
@@ -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"
 
 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( );
 }
index 4e02caeff19fe5f401a2f0f544da79e4d038323a..4d8b2c052f59ac40f412c75893909a994839c230 100644 (file)
--- a/qt/app.h
+++ b/qt/app.h
@@ -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:
diff --git a/qt/dbus-adaptor.cc b/qt/dbus-adaptor.cc
new file mode 100644 (file)
index 0000000..624a6c5
--- /dev/null
@@ -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;
+}
diff --git a/qt/dbus-adaptor.h b/qt/dbus-adaptor.h
new file mode 100644 (file)
index 0000000..da94e9f
--- /dev/null
@@ -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
index cbd1fe05a4b0143360dc65b3e236ac8454a42c84..2f333a7f05e87d1c07c2dee81fe1e1ae2f26ccee 100644 (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 );
index 2d4096adae92c87c6fe03e9a80e345559988c52a..537145a4b8b4d0bbd89ba6706f07336d752c7936 100644 (file)
@@ -91,6 +91,9 @@ class TrMainWindow: public QMainWindow
         void updateNetworkIcon( );
         QWidgetList myHidden;
 
+    public slots:
+        void openURL( QString );
+
     private slots:
         void onDetailsDestroyed( );
         void onShowModeClicked( );
index f87baafbe49ec5eb8ffb536cd0fc95eb2d9d1548..140957b434646ec3fad5ea8947184217643af946 100644 (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 \
index bd6e0eeed736e5b00510b3fef8d443c51f08d7d0..ae80017eabc40debb32c0432dd73d6a6e01c4743 100644 (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 );