(trunk qt) Remember between runs whether we were running a local or remote session. Add a gui dialog for switching sessions during runtime.

This commit is contained in:
Charles Kerr 2009-05-03 17:37:39 +00:00
parent 40c976a794
commit e249d894ac
11 changed files with 185 additions and 61 deletions

View File

@ -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, "<path>" },
{ '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, "<URL>" },
{ '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<int>)), mySession, SLOT(initTorrents(QSet<int>)) );
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<int> 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( )

View File

@ -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( )

View File

@ -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 );

View File

@ -64,6 +64,7 @@
<property name="title">
<string>&amp;Torrent</string>
</property>
<addaction name="separator"/>
<addaction name="action_Add"/>
<addaction name="action_New"/>
<addaction name="separator"/>
@ -89,6 +90,8 @@
<addaction name="action_SelectAll"/>
<addaction name="action_DeselectAll"/>
<addaction name="separator"/>
<addaction name="action_SessionDialog"/>
<addaction name="separator"/>
<addaction name="action_Preferences"/>
</widget>
<widget class="QMenu" name="menu_Help">
@ -520,6 +523,14 @@
<string>Tray &amp;Icon</string>
</property>
</action>
<action name="action_SessionDialog">
<property name="text">
<string>&amp;Change Session...</string>
</property>
<property name="toolTip">
<string extracomment="Start a local session or connect to a running session">Choose Session</string>
</property>
</action>
</widget>
<resources>
<include location="application.qrc"/>

View File

@ -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 );
}
/***

View File

@ -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,

View File

@ -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

View File

@ -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()));
myHttp.setHost( myUrl.host( ), myUrl.port( ) );
myHttp.setUser( myUrl.userName( ), myUrl.password( ) );
myBuffer.open( QIODevice::ReadWrite );
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)) );
if( paused )
exec( "{ \"method\": \"torrent-stop\" }" );
myBuffer.open( QIODevice::ReadWrite );
}
Session :: ~Session( )
{
stop( );
}
/***
****
***/
void
Session :: stop( )
{
myHttp.abort( );
myUrl.clear( );
if( mySession )
{
tr_sessionClose( mySession );
mySession = 0;
}
}
void
Session :: restart( )
{
stop( );
start( );
}
void
Session :: start( )
{
if( myPrefs.get<bool>(Prefs::SESSION_IS_REMOTE) )
{
const int port( myPrefs.get<int>(Prefs::SESSION_REMOTE_PORT) );
const bool auth( myPrefs.get<bool>(Prefs::SESSION_REMOTE_AUTH) );
const QString host( myPrefs.get<QString>(Prefs::SESSION_REMOTE_HOST) );
const QString user( myPrefs.get<QString>(Prefs::SESSION_REMOTE_USERNAME) );
const QString pass( myPrefs.get<QString>(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<int>& ids )
}
void
Session :: pause( const QSet<int>& ids )
Session :: pauseTorrents( const QSet<int>& ids )
{
sendTorrentRequest( "torrent-stop", ids );
}
void
Session :: start( const QSet<int>& ids )
Session :: startTorrents( const QSet<int>& 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( ) )

View File

@ -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<int>& torrentIds = QSet<int>() );
void start( const QSet<int>& torrentIds = QSet<int>() );
void pauseTorrents( const QSet<int>& torrentIds = QSet<int>() );
void startTorrents( const QSet<int>& torrentIds = QSet<int>() );
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;

View File

@ -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( );
}
/***

View File

@ -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;