From e249d894ac189536d5d59fcd49b3cf0855be7077 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 3 May 2009 17:37:39 +0000 Subject: [PATCH] (trunk qt) Remember between runs whether we were running a local or remote session. Add a gui dialog for switching sessions during runtime. --- qt/app.cc | 29 +++++++------ qt/mainwin.cc | 49 +++++++++++++++++----- qt/mainwin.h | 3 ++ qt/mainwin.ui | 11 +++++ qt/prefs.cc | 10 +++++ qt/prefs.h | 6 +++ qt/qtr.pro | 8 ++-- qt/session.cc | 100 +++++++++++++++++++++++++++++++------------- qt/session.h | 15 +++++-- qt/torrent-model.cc | 14 +++++-- qt/torrent-model.h | 1 + 11 files changed, 185 insertions(+), 61 deletions(-) diff --git a/qt/app.cc b/qt/app.cc index 053754839..fecfcbfcf 100644 --- a/qt/app.cc +++ b/qt/app.cc @@ -27,8 +27,9 @@ #include "mainwin.h" #include "options.h" #include "prefs.h" -#include "torrent-model.h" #include "session.h" +#include "session-dialog.h" +#include "torrent-model.h" #include "utils.h" #include "watchdir.h" @@ -40,8 +41,6 @@ namespace { { 'g', "config-dir", "Where to look for configuration files", "g", 1, "" }, { 'm', "minimized", "Start minimized in system tray", "m", 0, NULL }, - { 'p', "paused", "Pause all torrents on sartup", "p", 0, NULL }, - { 'r', "remote", "Remotely control a pre-existing session", "r", 1, "" }, { 'v', "version", "Show version number and exit", "v", 0, NULL }, { 0, NULL, NULL, NULL, 0, NULL } }; @@ -96,17 +95,13 @@ MyApp :: MyApp( int& argc, char ** argv ): // parse the command-line arguments int c; - bool paused = false; bool minimized = false; const char * optarg; const char * configDir = 0; - const char * url = 0; while( ( c = tr_getopt( getUsage( ), argc, (const char**)argv, opts, &optarg ) ) ) { switch( c ) { case 'g': configDir = optarg; break; case 'm': minimized = true; break; - case 'p': paused = true; break; - case 'r': url = optarg; break; case 'v': Utils::toStderr( QObject::tr( "transmission %1" ).arg( LONG_VERSION_STRING ) ); exit( 0 ); break; case TR_OPT_ERR: Utils::toStderr( QObject::tr( "Invalid option" ) ); showUsage( ); break; default: Utils::toStderr( QObject::tr( "Got opt %1" ).arg((int)c) ); showUsage( ); break; @@ -117,26 +112,29 @@ MyApp :: MyApp( int& argc, char ** argv ): if( configDir == 0 ) configDir = tr_getDefaultConfigDir( MY_NAME ); + // is this the first time we've run transmission? + const bool firstTime = !QFile(QDir(configDir).absoluteFilePath("settings.json")).exists(); + myPrefs = new Prefs ( configDir ); - mySession = new Session( configDir, *myPrefs, url, paused ); + mySession = new Session( configDir, *myPrefs ); myModel = new TorrentModel( *myPrefs ); myWindow = new TrMainWindow( *mySession, *myPrefs, *myModel, minimized ); myWatchDir = new WatchDir( *myModel ); - /* when the session gets torrent info, update the model */ + // when the session gets torrent info, update the model connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myModel, SLOT(updateTorrents(tr_benc*,bool)) ); connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myWindow, SLOT(refreshActionSensitivity()) ); connect( mySession, SIGNAL(torrentsRemoved(tr_benc*)), myModel, SLOT(removeTorrents(tr_benc*)) ); - /* when the model sees a torrent for the first time, ask the session for full info on it */ + // when the model sees a torrent for the first time, ask the session for full info on it connect( myModel, SIGNAL(torrentsAdded(QSet)), mySession, SLOT(initTorrents(QSet)) ); mySession->initTorrents( ); mySession->refreshSessionStats( ); - /* when torrents are added to the watch directory, tell the session */ + // when torrents are added to the watch directory, tell the session connect( myWatchDir, SIGNAL(torrentFileAdded(QString)), this, SLOT(addTorrent(QString)) ); - /* init from preferences */ + // init from preferences QList initKeys; initKeys << Prefs::DIR_WATCH; foreach( int key, initKeys ) @@ -162,6 +160,13 @@ MyApp :: MyApp( int& argc, char ** argv ): timer->start( ); maybeUpdateBlocklist( ); + + if( !firstTime ) + mySession->restart( ); + else { + QDialog * d = new SessionDialog( *mySession, *myPrefs, myWindow ); + d->show( ); + } } MyApp :: ~MyApp( ) diff --git a/qt/mainwin.cc b/qt/mainwin.cc index 4c8a4d566..ff90cf6cb 100644 --- a/qt/mainwin.cc +++ b/qt/mainwin.cc @@ -36,6 +36,7 @@ #include "prefs.h" #include "prefs-dialog.h" #include "session.h" +#include "session-dialog.h" #include "speed.h" #include "stats-dialog.h" #include "torrent-delegate.h" @@ -100,12 +101,6 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode ui.setupUi( this ); - QString title( "Transmission" ); - const QUrl remoteUrl( session.getRemoteUrl( ) ); - if( !remoteUrl.isEmpty( ) ) - title += tr( " - %1" ).arg( remoteUrl.toString(QUrl::RemoveUserInfo) ); - setWindowTitle( title ); - QStyle * style = this->style(); int i = style->pixelMetric( QStyle::PM_SmallIconSize, 0, this ); @@ -162,6 +157,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode connect( ui.action_Contents, SIGNAL(triggered()), this, SLOT(openHelp())); connect( ui.action_OpenFolder, SIGNAL(triggered()), this, SLOT(openFolder())); connect( ui.action_Properties, SIGNAL(triggered()), this, SLOT(openProperties())); + connect( ui.action_SessionDialog, SIGNAL(triggered()), this, SLOT(openSessionDialog())); connect( ui.listView, SIGNAL(activated(const QModelIndex&)), ui.action_Properties, SLOT(trigger())); // context menu @@ -252,6 +248,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode foreach( int key, initKeys ) refreshPref( key ); + connect( &mySession, SIGNAL(sourceChanged()), this, SLOT(onSessionSourceChanged()) ); connect( &mySession, SIGNAL(statsUpdated()), this, SLOT(refreshStatusBar()) ); connect( &mySession, SIGNAL(dataReadProgress()), this, SLOT(dataReadProgress()) ); connect( &mySession, SIGNAL(dataSendProgress()), this, SLOT(dataSendProgress()) ); @@ -265,6 +262,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode refreshActionSensitivity( ); refreshStatusBar( ); + refreshTitle( ); refreshVisibleCount( ); } @@ -276,6 +274,20 @@ TrMainWindow :: ~TrMainWindow( ) ***** ****/ +void +TrMainWindow :: onSessionSourceChanged( ) +{ + myModel.clear( ); + refreshTitle( ); + refreshVisibleCount( ); + refreshActionSensitivity( ); + refreshStatusBar( ); +} + +/**** +***** +****/ + #define PREF_VARIANTS_KEY "pref-variants-list" void @@ -576,6 +588,13 @@ TrMainWindow :: openProperties( ) myDetailsDialog->show( ); } +void +TrMainWindow :: openSessionDialog( ) +{ + SessionDialog * d = new SessionDialog( mySession, myPrefs, this ); + d->show( ); +} + void TrMainWindow :: openFolder( ) { @@ -596,6 +615,16 @@ TrMainWindow :: openHelp( ) QDesktopServices :: openUrl( QUrl( QString( url ) ) ); } +void +TrMainWindow :: refreshTitle( ) +{ + QString title( "Transmission" ); + const QUrl url( mySession.getRemoteUrl( ) ); + if( !url.isEmpty() ) + title += tr( " - %1" ).arg( url.toString(QUrl::RemoveUserInfo) ); + setWindowTitle( title ); +} + void TrMainWindow :: refreshVisibleCount( ) { @@ -723,22 +752,22 @@ TrMainWindow :: getSelectedTorrents( ) const void TrMainWindow :: startSelected( ) { - mySession.start( getSelectedTorrents( ) ); + mySession.startTorrents( getSelectedTorrents( ) ); } void TrMainWindow :: pauseSelected( ) { - mySession.pause( getSelectedTorrents( ) ); + mySession.pauseTorrents( getSelectedTorrents( ) ); } void TrMainWindow :: startAll( ) { - mySession.start( ); + mySession.startTorrents( ); } void TrMainWindow :: pauseAll( ) { - mySession.pause( ); + mySession.pauseTorrents( ); } void TrMainWindow :: removeSelected( ) diff --git a/qt/mainwin.h b/qt/mainwin.h index 5d8998466..0ba303ed3 100644 --- a/qt/mainwin.h +++ b/qt/mainwin.h @@ -103,6 +103,7 @@ class TrMainWindow: public QMainWindow void showSessionRatio( ); void showSessionTransfer( ); void refreshVisibleCount( ); + void refreshTitle( ); void refreshStatusBar( ); void openTorrent( ); void newTorrent( ); @@ -112,12 +113,14 @@ class TrMainWindow: public QMainWindow void openHelp( ); void openFolder( ); void openProperties( ); + void openSessionDialog( ); void toggleSpeedMode( ); void dataReadProgress( ); void dataSendProgress( ); void toggleWindows( ); void onSetPrefs( ); void onSetPrefs( bool ); + void onSessionSourceChanged( ); private slots: void setSortPref ( int ); diff --git a/qt/mainwin.ui b/qt/mainwin.ui index b4e843448..e8c8971d1 100644 --- a/qt/mainwin.ui +++ b/qt/mainwin.ui @@ -64,6 +64,7 @@ &Torrent + @@ -89,6 +90,8 @@ + + @@ -520,6 +523,14 @@ Tray &Icon + + + &Change Session... + + + Choose Session + + diff --git a/qt/prefs.cc b/qt/prefs.cc index 31b5b1d93..4191c1817 100644 --- a/qt/prefs.cc +++ b/qt/prefs.cc @@ -56,6 +56,12 @@ Prefs::PrefItem Prefs::myItems[] = { MAIN_WINDOW_X, "main-window-x", QVariant::Int }, { MAIN_WINDOW_Y, "main-window-y", QVariant::Int }, { FILTER_MODE, "filter-mode", TrTypes::FilterModeType }, + { SESSION_IS_REMOTE, "remote-session-enabled", QVariant::Bool }, + { SESSION_REMOTE_HOST, "remote-session-host", QVariant::String }, + { SESSION_REMOTE_PORT, "remote-session-port", QVariant::Int }, + { SESSION_REMOTE_AUTH, "remote-session-requres-authentication", QVariant::Bool }, + { SESSION_REMOTE_USERNAME, "remote-session-username", QVariant::String }, + { SESSION_REMOTE_PASSWORD, "remote-session-password", QVariant::String }, /* libtransmission settings */ { ALT_SPEED_LIMIT_UP, TR_PREFS_KEY_ALT_SPEED_UP, QVariant::Int }, @@ -256,6 +262,10 @@ Prefs :: initDefaults( tr_benc * d ) tr_bencDictAddInt( d, keyStr(MINIMAL_VIEW), false ); tr_bencDictAddInt( d, keyStr(START), true ); tr_bencDictAddInt( d, keyStr(TRASH_ORIGINAL), false ); + tr_bencDictAddStr( d, keyStr(SESSION_REMOTE_HOST), "localhost" ); + tr_bencDictAddInt( d, keyStr(SESSION_REMOTE_PORT), 9091 ); + tr_bencDictAddBool( d, keyStr(SESSION_IS_REMOTE), false ); + tr_bencDictAddBool( d, keyStr(SESSION_REMOTE_AUTH), false ); } /*** diff --git a/qt/prefs.h b/qt/prefs.h index e238ded44..082513857 100644 --- a/qt/prefs.h +++ b/qt/prefs.h @@ -59,6 +59,12 @@ class Prefs: public QObject MAIN_WINDOW_X, MAIN_WINDOW_Y, FILTER_MODE, + SESSION_IS_REMOTE, + SESSION_REMOTE_HOST, + SESSION_REMOTE_PORT, + SESSION_REMOTE_AUTH, + SESSION_REMOTE_USERNAME, + SESSION_REMOTE_PASSWORD, /* core prefs */ FIRST_CORE_PREF, diff --git a/qt/qtr.pro b/qt/qtr.pro index 4024b630d..b229a3994 100644 --- a/qt/qtr.pro +++ b/qt/qtr.pro @@ -24,10 +24,10 @@ FORMS += mainwin.ui RESOURCES += application.qrc SOURCES += about.cc app.cc details.cc file-tree.cc filters.cc hig.cc \ mainwin.cc make-dialog.cc options.cc prefs.cc prefs-dialog.cc \ - qticonloader.cc session.cc squeezelabel.cc stats-dialog.cc \ - torrent.cc torrent-delegate.cc torrent-delegate-min.cc \ - torrent-filter.cc torrent-model.cc triconpushbutton.cc \ - utils.cc watchdir.cc + qticonloader.cc session.cc session-dialog.cc squeezelabel.cc \ + stats-dialog.cc torrent.cc torrent-delegate.cc \ + torrent-delegate-min.cc torrent-filter.cc torrent-model.cc \ + triconpushbutton.cc utils.cc watchdir.cc HEADERS += $$replace(SOURCES, .cc, .h) HEADERS += speed.h types.h diff --git a/qt/session.cc b/qt/session.cc index f7d07b2d0..be01659b2 100644 --- a/qt/session.cc +++ b/qt/session.cc @@ -32,6 +32,7 @@ #include "prefs.h" #include "qticonloader.h" #include "session.h" +#include "session-dialog.h" #include "torrent.h" // #define DEBUG_HTTP @@ -174,11 +175,11 @@ Session :: updatePref( int key ) **** ***/ -Session :: Session( const char * configDir, Prefs& prefs, const char * url, bool paused ): +Session :: Session( const char * configDir, Prefs& prefs ): myBlocklistSize( -1 ), myPrefs( prefs ), mySession( 0 ), - myUrl( url ) + myConfigDir( configDir ) { myStats.ratio = TR_RATIO_NA; myStats.uploadedBytes = 0; @@ -188,44 +189,85 @@ Session :: Session( const char * configDir, Prefs& prefs, const char * url, bool myStats.secondsActive = 0; myCumulativeStats = myStats; - if( url != 0 ) + connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int))); + connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool))); + connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress())); + connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress())); + connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) ); + + myBuffer.open( QIODevice::ReadWrite ); +} + +Session :: ~Session( ) +{ + stop( ); +} + +/*** +**** +***/ + +void +Session :: stop( ) +{ + myHttp.abort( ); + myUrl.clear( ); + + if( mySession ) { - connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int))); - connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool))); - connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress())); - connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress())); - myHttp.setHost( myUrl.host( ), myUrl.port( ) ); - myHttp.setUser( myUrl.userName( ), myUrl.password( ) ); - myBuffer.open( QIODevice::ReadWrite ); - - if( paused ) - exec( "{ \"method\": \"torrent-stop\" }" ); + tr_sessionClose( mySession ); + mySession = 0; + } +} + +void +Session :: restart( ) +{ + stop( ); + start( ); +} + +void +Session :: start( ) +{ + if( myPrefs.get(Prefs::SESSION_IS_REMOTE) ) + { + const int port( myPrefs.get(Prefs::SESSION_REMOTE_PORT) ); + const bool auth( myPrefs.get(Prefs::SESSION_REMOTE_AUTH) ); + const QString host( myPrefs.get(Prefs::SESSION_REMOTE_HOST) ); + const QString user( myPrefs.get(Prefs::SESSION_REMOTE_USERNAME) ); + const QString pass( myPrefs.get(Prefs::SESSION_REMOTE_PASSWORD) ); + + QUrl url; + url.setScheme( "http" ); + url.setHost( host ); + url.setPort( port ); + if( auth ) { + url.setUserName( user ); + url.setPassword( pass ); + } + myUrl = url; + + myHttp.setHost( host, port ); + myHttp.setUser( user, pass ); } else { tr_benc settings; tr_bencInitDict( &settings, 0 ); tr_sessionGetDefaultSettings( &settings ); - tr_sessionLoadSettings( &settings, configDir, "qt" ); - mySession = tr_sessionInit( "qt", configDir, true, &settings ); + tr_sessionLoadSettings( &settings, myConfigDir.toUtf8().constData(), "qt" ); + mySession = tr_sessionInit( "qt", myConfigDir.toUtf8().constData(), true, &settings ); tr_bencFree( &settings ); tr_ctor * ctor = tr_ctorNew( mySession ); - if( paused ) - tr_ctorSetPaused( ctor, TR_FORCE, TRUE ); int torrentCount; tr_torrent ** torrents = tr_sessionLoadTorrents( mySession, ctor, &torrentCount ); tr_free( torrents ); tr_ctorFree( ctor ); } - connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) ); -} - -Session :: ~Session( ) -{ - if( mySession ) - tr_sessionClose( mySession ); + emit sourceChanged( ); } bool @@ -386,13 +428,13 @@ Session :: sendTorrentRequest( const char * request, const QSet& ids ) } void -Session :: pause( const QSet& ids ) +Session :: pauseTorrents( const QSet& ids ) { sendTorrentRequest( "torrent-stop", ids ); } void -Session :: start( const QSet& ids ) +Session :: startTorrents( const QSet& ids ) { sendTorrentRequest( "torrent-start", ids ); } @@ -496,7 +538,7 @@ Session :: exec( const char * request ) { tr_rpc_request_exec_json( mySession, request, strlen( request ), localSessionCallback, this ); } - else + else if( !myUrl.isEmpty( ) ) { const QByteArray data( request, strlen( request ) ); static const QString path( "/transmission/rpc" ); @@ -537,7 +579,7 @@ Session :: onRequestFinished( int id, bool error ) const QByteArray& response( myBuffer.buffer( ) ); const char * json( response.constData( ) ); int jsonLength( response.size( ) ); - if( json[jsonLength-1] == '\n' ) --jsonLength; + if( jsonLength>0 && json[jsonLength-1] == '\n' ) --jsonLength; parseResponse( json, jsonLength ); } @@ -742,7 +784,7 @@ Session :: addTorrent( QString filename ) { QFile file( filename ); file.open( QIODevice::ReadOnly ); - QByteArray raw( file.readAll( ) ); + const QByteArray raw( file.readAll( ) ); file.close( ); if( !raw.isEmpty( ) ) diff --git a/qt/session.h b/qt/session.h index 571a309d6..1f88a0fa9 100644 --- a/qt/session.h +++ b/qt/session.h @@ -37,11 +37,18 @@ class Session: public QObject Q_OBJECT public: - Session( const char * configDir, Prefs& prefs, const char * remoteUrl, bool paused ); + Session( const char * configDir, Prefs& prefs ); ~Session( ); static const int ADD_TORRENT_TAG; + public: + void stop( ); + void restart( ); + + private: + void start( ); + public: const QUrl& getRemoteUrl( ) const { return myUrl; } const struct tr_session_stats& getStats( ) const { return myStats; } @@ -84,8 +91,8 @@ class Session: public QObject public slots: - void pause( const QSet& torrentIds = QSet() ); - void start( const QSet& torrentIds = QSet() ); + void pauseTorrents( const QSet& torrentIds = QSet() ); + void startTorrents( const QSet& torrentIds = QSet() ); void refreshSessionInfo( ); void refreshSessionStats( ); void refreshActiveTorrents( ); @@ -106,6 +113,7 @@ class Session: public QObject void onRequestFinished( int id, bool error ); signals: + void sourceChanged( ); void portTested( bool isOpen ); void statsUpdated( ); void sessionUpdated( ); @@ -119,6 +127,7 @@ class Session: public QObject int64_t myBlocklistSize; Prefs& myPrefs; tr_session * mySession; + QString myConfigDir; QUrl myUrl; QBuffer myBuffer; QHttp myHttp; diff --git a/qt/torrent-model.cc b/qt/torrent-model.cc index f6f1bd1d2..27511c0ff 100644 --- a/qt/torrent-model.cc +++ b/qt/torrent-model.cc @@ -19,6 +19,16 @@ #include "torrent-delegate.h" #include "torrent-model.h" +void +TorrentModel :: clear( ) +{ + myIdToRow.clear( ); + myIdToTorrent.clear( ); + foreach( Torrent * tor, myTorrents ) delete tor; + myTorrents.clear( ); + reset( ); +} + int TorrentModel :: rowCount( const QModelIndex& parent ) const { @@ -78,9 +88,7 @@ TorrentModel :: TorrentModel( Prefs& prefs ): TorrentModel :: ~TorrentModel( ) { - foreach( Torrent * tor, myTorrents ) - delete tor; - myTorrents.clear( ); + clear( ); } /*** diff --git a/qt/torrent-model.h b/qt/torrent-model.h index 039f52389..856c28ed1 100644 --- a/qt/torrent-model.h +++ b/qt/torrent-model.h @@ -42,6 +42,7 @@ class TorrentModel: public QAbstractListModel Prefs& myPrefs; public: + void clear( ); bool hasTorrent( const QString& hashString ) const; virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; -- 2.40.0