(trunk qt) handle multiple torrent selection in the properties dialog
This commit is contained in:
parent
03fa0b3e7d
commit
d82b4a5fc6
437
qt/details.cc
437
qt/details.cc
|
@ -15,6 +15,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "squeezelabel.h"
|
#include "squeezelabel.h"
|
||||||
#include "torrent.h"
|
#include "torrent.h"
|
||||||
|
#include "torrent-model.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
class Prefs;
|
class Prefs;
|
||||||
|
@ -119,30 +121,36 @@ class PeerItem: public QTreeWidgetItem
|
||||||
****
|
****
|
||||||
***/
|
***/
|
||||||
|
|
||||||
Details :: Details( Session& session, Torrent& torrent, QWidget * parent ):
|
Details :: Details( Session& session, TorrentModel& model, QWidget * parent ):
|
||||||
QDialog( parent, Qt::Dialog ),
|
QDialog( parent, Qt::Dialog ),
|
||||||
mySession( session ),
|
mySession( session ),
|
||||||
myTorrent( torrent )
|
myModel( model ),
|
||||||
|
myHavePendingRefresh( false )
|
||||||
{
|
{
|
||||||
QVBoxLayout * layout = new QVBoxLayout( this );
|
QVBoxLayout * layout = new QVBoxLayout( this );
|
||||||
|
|
||||||
setWindowTitle( tr( "%1 Properties" ).arg( torrent.name( ) ) );
|
setWindowTitle( tr( "Torrent Properties" ) );
|
||||||
|
|
||||||
QTabWidget * t = new QTabWidget( this );
|
QTabWidget * t = new QTabWidget( this );
|
||||||
t->addTab( createActivityTab( ), tr( "Activity" ) );
|
QWidget * w;
|
||||||
t->addTab( createPeersTab( ), tr( "Peers" ) );
|
t->addTab( w = createActivityTab( ), tr( "Activity" ) );
|
||||||
t->addTab( createTrackerTab( ), tr( "Tracker" ) );
|
myWidgets << w;
|
||||||
t->addTab( createInfoTab( ), tr( "Information" ) );
|
t->addTab( w = createPeersTab( ), tr( "Peers" ) );
|
||||||
t->addTab( createFilesTab( ), tr( "Files" ) );
|
myWidgets << w;
|
||||||
t->addTab( createOptionsTab( ), tr( "Options" ) );
|
t->addTab( w = createTrackerTab( ), tr( "Tracker" ) );
|
||||||
|
myWidgets << w;
|
||||||
|
t->addTab( w = createInfoTab( ), tr( "Information" ) );
|
||||||
|
myWidgets << w;
|
||||||
|
t->addTab( w = createFilesTab( ), tr( "Files" ) );
|
||||||
|
myWidgets << w;
|
||||||
|
t->addTab( w = createOptionsTab( ), tr( "Options" ) );
|
||||||
|
myWidgets << w;
|
||||||
layout->addWidget( t );
|
layout->addWidget( t );
|
||||||
|
|
||||||
QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
|
QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
|
||||||
connect( buttons, SIGNAL(rejected()), this, SLOT(deleteLater()) ); // "close" triggers rejected
|
connect( buttons, SIGNAL(rejected()), this, SLOT(deleteLater()) ); // "close" triggers rejected
|
||||||
layout->addWidget( buttons );
|
layout->addWidget( buttons );
|
||||||
|
|
||||||
connect( &myTorrent, SIGNAL(torrentChanged(int)), this, SLOT(onTorrentChanged()) );
|
|
||||||
connect( &myTorrent, SIGNAL(destroyed(QObject*)), this, SLOT(deleteLater()) );
|
|
||||||
connect( &myTimer, SIGNAL(timeout()), this, SLOT(onTimer()) );
|
connect( &myTimer, SIGNAL(timeout()), this, SLOT(onTimer()) );
|
||||||
|
|
||||||
onTimer( );
|
onTimer( );
|
||||||
|
@ -154,6 +162,34 @@ Details :: ~Details( )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Details :: setIds( const QSet<int>& ids )
|
||||||
|
{
|
||||||
|
if( ids == myIds )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// stop listening to the old torrents
|
||||||
|
foreach( int id, myIds ) {
|
||||||
|
const Torrent * tor = myModel.getTorrentFromId( id );
|
||||||
|
if( tor )
|
||||||
|
disconnect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onTorrentChanged()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
myIds = ids;
|
||||||
|
|
||||||
|
// listen to the new torrents
|
||||||
|
foreach( int id, myIds ) {
|
||||||
|
const Torrent * tor = myModel.getTorrentFromId( id );
|
||||||
|
if( tor )
|
||||||
|
connect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onTorrentChanged()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( QWidget * w, myWidgets )
|
||||||
|
w->setEnabled( false );
|
||||||
|
|
||||||
|
onTimer( );
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
****
|
****
|
||||||
***/
|
***/
|
||||||
|
@ -161,85 +197,292 @@ Details :: ~Details( )
|
||||||
void
|
void
|
||||||
Details :: onTimer( )
|
Details :: onTimer( )
|
||||||
{
|
{
|
||||||
mySession.refreshExtraStats( myTorrent.id( ) );
|
if( !myIds.empty( ) )
|
||||||
|
mySession.refreshExtraStats( myIds );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Details :: onTorrentChanged( )
|
Details :: onTorrentChanged( )
|
||||||
{
|
{
|
||||||
|
if( !myHavePendingRefresh ) {
|
||||||
|
myHavePendingRefresh = true;
|
||||||
|
QTimer::singleShot( 100, this, SLOT(refresh()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Details :: refresh( )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
QLocale locale;
|
QLocale locale;
|
||||||
|
const int n = myIds.size( );
|
||||||
|
const bool single = n == 1;
|
||||||
|
const QString blank;
|
||||||
const QFontMetrics fm( fontMetrics( ) );
|
const QFontMetrics fm( fontMetrics( ) );
|
||||||
|
QSet<const Torrent*> torrents;
|
||||||
|
const Torrent * tor;
|
||||||
|
QSet<QString> strings;
|
||||||
|
QString string;
|
||||||
|
|
||||||
// activity tab
|
// build a list of torrents
|
||||||
myStateLabel->setText( myTorrent.activityString( ) );
|
foreach( int id, myIds ) {
|
||||||
myProgressLabel->setText( locale.toString( myTorrent.percentDone( )*100.0, 'f', 2 ) );
|
const Torrent * tor = myModel.getTorrentFromId( id );
|
||||||
|
if( tor )
|
||||||
|
torrents << tor;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// activity tab
|
||||||
|
///
|
||||||
|
|
||||||
|
// myStateLabel
|
||||||
|
if( torrents.empty( ) )
|
||||||
|
string = tr( "None" );
|
||||||
|
else {
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->activityString( ) );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
}
|
||||||
|
myStateLabel->setText( string );
|
||||||
|
|
||||||
|
// myProgressLabel
|
||||||
|
if( torrents.empty( ) )
|
||||||
|
string = tr( "None" );
|
||||||
|
else {
|
||||||
|
double sizeWhenDone = 0;
|
||||||
|
double leftUntilDone = 0;
|
||||||
|
foreach( tor, torrents ) {
|
||||||
|
sizeWhenDone += tor->sizeWhenDone( );
|
||||||
|
leftUntilDone += tor->leftUntilDone( );
|
||||||
|
}
|
||||||
|
string = locale.toString( 100.0*((sizeWhenDone-leftUntilDone)/sizeWhenDone), 'f', 2 );
|
||||||
|
}
|
||||||
|
myProgressLabel->setText( string );
|
||||||
|
|
||||||
|
// myHaveLabel
|
||||||
|
int64_t haveTotal = 0;
|
||||||
|
int64_t haveVerified = 0;
|
||||||
|
int64_t verifiedPieces = 0;
|
||||||
|
foreach( tor, torrents ) {
|
||||||
|
haveTotal += tor->haveTotal( );
|
||||||
|
haveVerified += tor->haveVerified( );
|
||||||
|
verifiedPieces += tor->haveVerified( ) / tor->pieceSize( );
|
||||||
|
}
|
||||||
myHaveLabel->setText( tr( "%1 (%2 verified in %L3 pieces)" )
|
myHaveLabel->setText( tr( "%1 (%2 verified in %L3 pieces)" )
|
||||||
.arg( Utils::sizeToString( myTorrent.haveTotal( ) ) )
|
.arg( Utils::sizeToString( haveTotal ) )
|
||||||
.arg( Utils::sizeToString( myTorrent.haveVerified( ) ) )
|
.arg( Utils::sizeToString( haveVerified ) )
|
||||||
.arg( myTorrent.haveVerified()/myTorrent.pieceSize() ) );
|
.arg( verifiedPieces ) );
|
||||||
myDownloadedLabel->setText( Utils::sizeToString( myTorrent.downloadedEver( ) ) );
|
|
||||||
myUploadedLabel->setText( Utils::sizeToString( myTorrent.uploadedEver( ) ) );
|
|
||||||
myFailedLabel->setText( Utils::sizeToString( myTorrent.failedEver( ) ) );
|
|
||||||
myRatioLabel->setText( Utils :: ratioToString( myTorrent.ratio( ) ) );
|
|
||||||
mySwarmSpeedLabel->setText( Utils::speedToString( myTorrent.swarmSpeed( ) ) );
|
|
||||||
myAddedDateLabel->setText( myTorrent.dateAdded().toString() );
|
|
||||||
|
|
||||||
QDateTime dt = myTorrent.lastActivity( );
|
int64_t num = 0;
|
||||||
myActivityLabel->setText( dt.isNull() ? tr("Never") : dt.toString() );
|
foreach( tor, torrents ) num += tor->downloadedEver( );
|
||||||
QString s = myTorrent.getError( );
|
myDownloadedLabel->setText( Utils::sizeToString( num ) );
|
||||||
myErrorLabel->setText( s.isEmpty() ? tr("None") : s );
|
|
||||||
|
|
||||||
// information tab
|
num = 0;
|
||||||
myPiecesLabel->setText( tr( "%L1 Pieces @ %2" ).arg( myTorrent.pieceCount() )
|
foreach( tor, torrents ) num += tor->uploadedEver( );
|
||||||
.arg( Utils::sizeToString(myTorrent.pieceSize()) ) );
|
myUploadedLabel->setText( Utils::sizeToString( num ) );
|
||||||
myHashLabel->setText( myTorrent.hashString( ) );
|
|
||||||
|
|
||||||
myPrivacyLabel->setText( myTorrent.isPrivate( ) ? tr( "Private to this tracker -- PEX disabled" )
|
num = 0;
|
||||||
|
foreach( tor, torrents ) num += tor->failedEver( );
|
||||||
|
myFailedLabel->setText( Utils::sizeToString( num ) );
|
||||||
|
|
||||||
|
double d = 0;
|
||||||
|
foreach( tor, torrents ) d += tor->ratio( );
|
||||||
|
myRatioLabel->setText( Utils :: ratioToString( d / n ) );
|
||||||
|
|
||||||
|
Speed speed;
|
||||||
|
foreach( tor, torrents ) speed += tor->swarmSpeed( );
|
||||||
|
mySwarmSpeedLabel->setText( Utils::speedToString( speed ) );
|
||||||
|
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->dateAdded().toString() );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myAddedDateLabel->setText( string );
|
||||||
|
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) {
|
||||||
|
QDateTime dt = tor->lastActivity( );
|
||||||
|
strings.insert( dt.isNull() ? tr("Never") : dt.toString() );
|
||||||
|
}
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myActivityLabel->setText( string );
|
||||||
|
|
||||||
|
if( torrents.empty( ) )
|
||||||
|
string = tr( "None" );
|
||||||
|
else {
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->getError( ) );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
}
|
||||||
|
myErrorLabel->setText( string );
|
||||||
|
|
||||||
|
///
|
||||||
|
/// information tab
|
||||||
|
///
|
||||||
|
|
||||||
|
// myPiecesLabel
|
||||||
|
int64_t pieceCount = 0;
|
||||||
|
int64_t pieceSize = 0;
|
||||||
|
foreach( tor, torrents ) {
|
||||||
|
pieceCount += tor->pieceCount( );
|
||||||
|
pieceSize += tor->pieceSize( );
|
||||||
|
}
|
||||||
|
myPiecesLabel->setText( tr( "%L1 Pieces @ %2" ).arg( pieceCount )
|
||||||
|
.arg( Utils::sizeToString( pieceSize ) ) );
|
||||||
|
|
||||||
|
// myHashLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->hashString( ) );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myHashLabel->setText( string );
|
||||||
|
|
||||||
|
// myPrivacyLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents )
|
||||||
|
strings.insert( tor->isPrivate( ) ? tr( "Private to this tracker -- PEX disabled" )
|
||||||
: tr( "Public torrent" ) );
|
: tr( "Public torrent" ) );
|
||||||
myCommentBrowser->setText( myTorrent.comment( ) );
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
QString str = myTorrent.creator( );
|
myPrivacyLabel->setText( string );
|
||||||
if( str.isEmpty( ) )
|
|
||||||
str = tr( "Unknown" );
|
|
||||||
myCreatorLabel->setText( str );
|
|
||||||
myDateCreatedLabel->setText( myTorrent.dateCreated( ).toString( ) );
|
|
||||||
myDestinationLabel->setText( myTorrent.getPath( ) );
|
|
||||||
myTorrentFileLabel->setText( myTorrent.torrentFile( ) );
|
|
||||||
|
|
||||||
// options tab
|
// myCommentBrowser
|
||||||
mySessionLimitCheck->setChecked( myTorrent.honorsSessionLimits( ) );
|
strings.clear( );
|
||||||
mySingleDownCheck->setChecked( myTorrent.downloadIsLimited( ) );
|
foreach( tor, torrents ) strings.insert( tor->comment( ) );
|
||||||
mySingleUpCheck->setChecked( myTorrent.uploadIsLimited( ) );
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
mySingleDownSpin->setValue( (int)myTorrent.downloadLimit().kbps() );
|
myCommentBrowser->setText( string );
|
||||||
mySingleUpSpin->setValue( (int)myTorrent.uploadLimit().kbps() );
|
|
||||||
myPeerLimitSpin->setValue( myTorrent.peerLimit( ) );
|
|
||||||
|
|
||||||
|
// myCreatorLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->creator().isEmpty() ? tr( "Unknown" ) : tor->creator() );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myCreatorLabel->setText( string );
|
||||||
|
|
||||||
|
// myDateCreatedLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->dateCreated().toString() );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myDateCreatedLabel->setText( string );
|
||||||
|
|
||||||
|
// myDestinationLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->getPath( ) );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myDestinationLabel->setText( string );
|
||||||
|
|
||||||
|
// myTorrentFileLabel
|
||||||
|
strings.clear( );
|
||||||
|
foreach( tor, torrents ) strings.insert( tor->torrentFile( ) );
|
||||||
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
|
myTorrentFileLabel->setText( string );
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Options Tab
|
||||||
|
///
|
||||||
|
|
||||||
|
if( !torrents.empty( ) )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const Torrent * baseline = *torrents.begin();
|
||||||
|
bool uniform;
|
||||||
|
bool baselineFlag;
|
||||||
|
int baselineInt;
|
||||||
|
|
||||||
|
// mySessionLimitCheck
|
||||||
|
uniform = true;
|
||||||
|
baselineFlag = baseline->honorsSessionLimits( );
|
||||||
|
foreach( tor, torrents ) if( baselineFlag != tor->honorsSessionLimits( ) ) { uniform = false; break; }
|
||||||
|
mySessionLimitCheck->setChecked( uniform && baselineFlag );
|
||||||
|
|
||||||
|
// mySingleDownCheck
|
||||||
|
uniform = true;
|
||||||
|
baselineFlag = baseline->downloadIsLimited( );
|
||||||
|
foreach( tor, torrents ) if( baselineFlag != tor->downloadIsLimited( ) ) { uniform = false; break; }
|
||||||
|
mySingleDownCheck->setChecked( uniform && baselineFlag );
|
||||||
|
|
||||||
|
// mySingleUpCheck
|
||||||
|
uniform = true;
|
||||||
|
baselineFlag = baseline->uploadIsLimited( );
|
||||||
|
foreach( tor, torrents ) if( baselineFlag != tor->uploadIsLimited( ) ) { uniform = false; break; }
|
||||||
|
mySingleUpCheck->setChecked( uniform && baselineFlag );
|
||||||
|
|
||||||
|
// myBandwidthPriorityCombo
|
||||||
|
uniform = true;
|
||||||
|
baselineInt = baseline->getBandwidthPriority( );
|
||||||
|
foreach( tor, torrents ) if ( baselineInt != tor->getBandwidthPriority( ) ) { uniform = false; break; }
|
||||||
|
if( uniform )
|
||||||
|
i = myBandwidthPriorityCombo->findData( baselineInt );
|
||||||
|
else
|
||||||
|
i = -1;
|
||||||
|
myBandwidthPriorityCombo->blockSignals( true );
|
||||||
|
myBandwidthPriorityCombo->setCurrentIndex( i );
|
||||||
|
myBandwidthPriorityCombo->blockSignals( false );
|
||||||
|
|
||||||
|
mySingleDownSpin->blockSignals( true );
|
||||||
|
mySingleDownSpin->setValue( tor->downloadLimit().kbps() );
|
||||||
|
mySingleDownSpin->blockSignals( false );
|
||||||
|
|
||||||
|
mySingleUpSpin->blockSignals( true );
|
||||||
|
mySingleUpSpin->setValue( tor->uploadLimit().kbps() );
|
||||||
|
mySingleUpSpin->blockSignals( false );
|
||||||
|
|
||||||
|
myPeerLimitSpin->blockSignals( true );
|
||||||
|
myPeerLimitSpin->setValue( tor->peerLimit() );
|
||||||
|
myPeerLimitSpin->blockSignals( false );
|
||||||
|
|
||||||
|
// ratio radios
|
||||||
|
uniform = true;
|
||||||
|
baselineInt = tor->seedRatioMode( );
|
||||||
|
foreach( tor, torrents ) if( baselineInt != tor->seedRatioMode( ) ) { uniform = false; break; }
|
||||||
|
if( !uniform ) {
|
||||||
|
mySeedGlobalRadio->setChecked( false );
|
||||||
|
mySeedCustomRadio->setChecked( false );
|
||||||
|
mySeedForeverRadio->setChecked( false );
|
||||||
|
} else {
|
||||||
QRadioButton * rb;
|
QRadioButton * rb;
|
||||||
switch( myTorrent.seedRatioMode( ) ) {
|
switch( baselineInt ) {
|
||||||
case TR_RATIOLIMIT_GLOBAL: rb = mySeedGlobalRadio; break;
|
case TR_RATIOLIMIT_GLOBAL: rb = mySeedGlobalRadio; break;
|
||||||
case TR_RATIOLIMIT_SINGLE: rb = mySeedCustomRadio; break;
|
case TR_RATIOLIMIT_SINGLE: rb = mySeedCustomRadio; break;
|
||||||
case TR_RATIOLIMIT_UNLIMITED: rb = mySeedForeverRadio; break;
|
case TR_RATIOLIMIT_UNLIMITED: rb = mySeedForeverRadio; break;
|
||||||
}
|
}
|
||||||
rb->setChecked( true );
|
rb->setChecked( true );
|
||||||
mySeedCustomSpin->setValue( myTorrent.seedRatioLimit( ) );
|
}
|
||||||
|
|
||||||
|
mySeedCustomSpin->setValue( tor->seedRatioLimit( ) );
|
||||||
|
}
|
||||||
|
|
||||||
// tracker tab
|
// tracker tab
|
||||||
const time_t now( time( 0 ) );
|
const time_t now( time( 0 ) );
|
||||||
myScrapeTimePrevLabel->setText( myTorrent.lastScrapeTime().toString() );
|
myScrapeTimePrevLabel->setText( tor ? tor->lastScrapeTime().toString() : blank );
|
||||||
myScrapeResponseLabel->setText( myTorrent.scrapeResponse() );
|
myScrapeResponseLabel->setText( tor ? tor->scrapeResponse() : blank );
|
||||||
myScrapeTimeNextLabel->setText( Utils :: timeToString( myTorrent.nextScrapeTime().toTime_t() - now ) );
|
myScrapeTimeNextLabel->setText( Utils :: timeToString( tor ? tor->nextScrapeTime().toTime_t() - now : 0 ) );
|
||||||
myAnnounceTimePrevLabel->setText( myTorrent.lastScrapeTime().toString() );
|
myAnnounceTimePrevLabel->setText( tor ? tor->lastScrapeTime().toString() : blank );
|
||||||
myAnnounceTimeNextLabel->setText( Utils :: timeToString( myTorrent.nextAnnounceTime().toTime_t() - now ) );
|
myAnnounceTimeNextLabel->setText( Utils :: timeToString( tor ? tor->nextAnnounceTime().toTime_t() - now : 0 ) );
|
||||||
myAnnounceManualLabel->setText( Utils :: timeToString( myTorrent.manualAnnounceTime().toTime_t() - now ) );
|
myAnnounceManualLabel->setText( Utils :: timeToString( tor ? tor->manualAnnounceTime().toTime_t() - now : 0 ) );
|
||||||
myAnnounceResponseLabel->setText( myTorrent.announceResponse( ) );
|
myAnnounceResponseLabel->setText( tor ? tor->announceResponse( ) : blank );
|
||||||
const QUrl url( myTorrent.announceUrl( ) );
|
|
||||||
myTrackerLabel->setText( url.host( ) );
|
|
||||||
|
|
||||||
// peers tab
|
// myTrackerLabel
|
||||||
mySeedersLabel->setText( locale.toString( myTorrent.seeders( ) ) );
|
strings.clear( );
|
||||||
myLeechersLabel->setText( locale.toString( myTorrent.leechers( ) ) );
|
foreach( tor, torrents ) strings.insert( QUrl(tor->announceUrl()).host() );
|
||||||
myTimesCompletedLabel->setText( locale.toString( myTorrent.timesCompleted( ) ) );
|
string = strings.size()==1 ? *strings.begin() : blank;
|
||||||
const PeerList peers( myTorrent.peers( ) );
|
myTrackerLabel->setText( string );
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Peers tab
|
||||||
|
///
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
foreach( tor, torrents ) i += tor->seeders( );
|
||||||
|
mySeedersLabel->setText( locale.toString( i ) );
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
foreach( tor, torrents ) i += tor->leechers( );
|
||||||
|
myLeechersLabel->setText( locale.toString( i ) );
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
foreach( tor, torrents ) i += tor->timesCompleted( );
|
||||||
|
myTimesCompletedLabel->setText( locale.toString( i ) );
|
||||||
|
|
||||||
|
PeerList peers;
|
||||||
|
foreach( tor, torrents ) peers << tor->peers( );
|
||||||
QMap<QString,QTreeWidgetItem*> peers2;
|
QMap<QString,QTreeWidgetItem*> peers2;
|
||||||
QList<QTreeWidgetItem*> newItems;
|
QList<QTreeWidgetItem*> newItems;
|
||||||
static const QIcon myEncryptionIcon( ":/icons/encrypted.png" );
|
static const QIcon myEncryptionIcon( ":/icons/encrypted.png" );
|
||||||
|
@ -310,7 +553,16 @@ Details :: onTorrentChanged( )
|
||||||
}
|
}
|
||||||
myPeers = peers2;
|
myPeers = peers2;
|
||||||
|
|
||||||
myFileTreeView->update( myTorrent.files( ) );
|
if( single ) {
|
||||||
|
tor = *torrents.begin();
|
||||||
|
myFileTreeView->update( tor->files( ) );
|
||||||
|
} else {
|
||||||
|
myFileTreeView->clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
myHavePendingRefresh = false;
|
||||||
|
foreach( QWidget * w, myWidgets )
|
||||||
|
w->setEnabled( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -357,27 +609,28 @@ Details :: createActivityTab( )
|
||||||
void
|
void
|
||||||
Details :: onHonorsSessionLimitsToggled( bool val )
|
Details :: onHonorsSessionLimitsToggled( bool val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "honorsSessionLimits", val );
|
std::cerr << " honorsSessionLimits clicked to " << val << std::endl;
|
||||||
|
mySession.torrentSet( myIds, "honorsSessionLimits", val );
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
Details :: onDownloadLimitedToggled( bool val )
|
Details :: onDownloadLimitedToggled( bool val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "downloadLimited", val );
|
mySession.torrentSet( myIds, "downloadLimited", val );
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
Details :: onDownloadLimitChanged( int val )
|
Details :: onDownloadLimitChanged( int val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "downloadLimit", val );
|
mySession.torrentSet( myIds, "downloadLimit", val );
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
Details :: onUploadLimitedToggled( bool val )
|
Details :: onUploadLimitedToggled( bool val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "uploadLimited", val );
|
mySession.torrentSet( myIds, "uploadLimited", val );
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
Details :: onUploadLimitChanged( int val )
|
Details :: onUploadLimitChanged( int val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "uploadLimit", val );
|
mySession.torrentSet( myIds, "uploadLimit", val );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RATIO_KEY "seedRatioMode"
|
#define RATIO_KEY "seedRatioMode"
|
||||||
|
@ -386,19 +639,29 @@ void
|
||||||
Details :: onSeedUntilChanged( bool b )
|
Details :: onSeedUntilChanged( bool b )
|
||||||
{
|
{
|
||||||
if( b )
|
if( b )
|
||||||
mySession.torrentSet( myTorrent.id(), RATIO_KEY, sender()->property(RATIO_KEY).toInt() );
|
mySession.torrentSet( myIds, RATIO_KEY, sender()->property(RATIO_KEY).toInt() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Details :: onSeedRatioLimitChanged( double val )
|
Details :: onSeedRatioLimitChanged( double val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "seedRatioLimit", val );
|
mySession.torrentSet( myIds, "seedRatioLimit", val );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Details :: onMaxPeersChanged( int val )
|
Details :: onMaxPeersChanged( int val )
|
||||||
{
|
{
|
||||||
mySession.torrentSet( myTorrent.id(), "peer-limit", val );
|
mySession.torrentSet( myIds, "peer-limit", val );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Details :: onBandwidthPriorityChanged( int index )
|
||||||
|
{
|
||||||
|
if( index != -1 )
|
||||||
|
{
|
||||||
|
const int priority = myBandwidthPriorityCombo->itemData(index).toInt( );
|
||||||
|
mySession.torrentSet( myIds, "bandwidthPriority", priority );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *
|
QWidget *
|
||||||
|
@ -407,17 +670,18 @@ Details :: createOptionsTab( )
|
||||||
//QWidget * l;
|
//QWidget * l;
|
||||||
QSpinBox * s;
|
QSpinBox * s;
|
||||||
QCheckBox * c;
|
QCheckBox * c;
|
||||||
|
QComboBox * m;
|
||||||
QHBoxLayout * h;
|
QHBoxLayout * h;
|
||||||
QRadioButton * r;
|
QRadioButton * r;
|
||||||
QDoubleSpinBox * ds;
|
QDoubleSpinBox * ds;
|
||||||
|
|
||||||
HIG * hig = new HIG( this );
|
HIG * hig = new HIG( this );
|
||||||
hig->addSectionTitle( tr( "Speed Limits" ) );
|
hig->addSectionTitle( tr( "Speed" ) );
|
||||||
|
|
||||||
c = new QCheckBox( tr( "Honor global &limits" ) );
|
c = new QCheckBox( tr( "Honor global &limits" ) );
|
||||||
mySessionLimitCheck = c;
|
mySessionLimitCheck = c;
|
||||||
hig->addWideControl( c );
|
hig->addWideControl( c );
|
||||||
connect( c, SIGNAL(toggled(bool)), this, SLOT(onHonorsSessionLimitsToggled(bool)) );
|
connect( c, SIGNAL(clicked(bool)), this, SLOT(onHonorsSessionLimitsToggled(bool)) );
|
||||||
|
|
||||||
c = new QCheckBox( tr( "Limit &download speed (KB/s)" ) );
|
c = new QCheckBox( tr( "Limit &download speed (KB/s)" ) );
|
||||||
mySingleDownCheck = c;
|
mySingleDownCheck = c;
|
||||||
|
@ -426,7 +690,7 @@ Details :: createOptionsTab( )
|
||||||
s->setRange( 0, INT_MAX );
|
s->setRange( 0, INT_MAX );
|
||||||
hig->addRow( c, s );
|
hig->addRow( c, s );
|
||||||
enableWhenChecked( c, s );
|
enableWhenChecked( c, s );
|
||||||
connect( c, SIGNAL(toggled(bool)), this, SLOT(onDownloadLimitedToggled(bool)) );
|
connect( c, SIGNAL(clicked(bool)), this, SLOT(onDownloadLimitedToggled(bool)) );
|
||||||
connect( s, SIGNAL(valueChanged(int)), this, SLOT(onDownloadLimitChanged(int)));
|
connect( s, SIGNAL(valueChanged(int)), this, SLOT(onDownloadLimitChanged(int)));
|
||||||
|
|
||||||
c = new QCheckBox( tr( "Limit &upload speed (KB/s)" ) );
|
c = new QCheckBox( tr( "Limit &upload speed (KB/s)" ) );
|
||||||
|
@ -436,21 +700,30 @@ Details :: createOptionsTab( )
|
||||||
s->setRange( 0, INT_MAX );
|
s->setRange( 0, INT_MAX );
|
||||||
hig->addRow( c, s );
|
hig->addRow( c, s );
|
||||||
enableWhenChecked( c, s );
|
enableWhenChecked( c, s );
|
||||||
connect( c, SIGNAL(toggled(bool)), this, SLOT(onUploadLimitedToggled(bool)) );
|
connect( c, SIGNAL(clicked(bool)), this, SLOT(onUploadLimitedToggled(bool)) );
|
||||||
connect( s, SIGNAL(valueChanged(int)), this, SLOT(onUploadLimitChanged(int)));
|
connect( s, SIGNAL(valueChanged(int)), this, SLOT(onUploadLimitChanged(int)));
|
||||||
|
|
||||||
|
m = new QComboBox;
|
||||||
|
m->addItem( tr( "Low" ), TR_PRI_LOW );
|
||||||
|
m->addItem( tr( "Normal" ), TR_PRI_NORMAL );
|
||||||
|
m->addItem( tr( "High" ), TR_PRI_HIGH );
|
||||||
|
connect( m, SIGNAL(currentIndexChanged(int)), this, SLOT(onBandwidthPriorityChanged(int)));
|
||||||
|
hig->addRow( tr( "Bandwidth priority:" ), m );
|
||||||
|
myBandwidthPriorityCombo = m;
|
||||||
|
|
||||||
|
|
||||||
hig->addSectionDivider( );
|
hig->addSectionDivider( );
|
||||||
hig->addSectionTitle( tr( "Seed-Until Ratio" ) );
|
hig->addSectionTitle( tr( "Seed-Until Ratio" ) );
|
||||||
|
|
||||||
r = new QRadioButton( tr( "Use &global setting" ) );
|
r = new QRadioButton( tr( "Use &global setting" ) );
|
||||||
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_GLOBAL );
|
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_GLOBAL );
|
||||||
connect( r, SIGNAL(toggled(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
connect( r, SIGNAL(clicked(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
||||||
mySeedGlobalRadio = r;
|
mySeedGlobalRadio = r;
|
||||||
hig->addWideControl( r );
|
hig->addWideControl( r );
|
||||||
|
|
||||||
r = new QRadioButton( tr( "Seed ®ardless of ratio" ) );
|
r = new QRadioButton( tr( "Seed ®ardless of ratio" ) );
|
||||||
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_UNLIMITED );
|
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_UNLIMITED );
|
||||||
connect( r, SIGNAL(toggled(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
connect( r, SIGNAL(clicked(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
||||||
mySeedForeverRadio = r;
|
mySeedForeverRadio = r;
|
||||||
hig->addWideControl( r );
|
hig->addWideControl( r );
|
||||||
|
|
||||||
|
@ -458,7 +731,7 @@ Details :: createOptionsTab( )
|
||||||
h->setSpacing( HIG :: PAD );
|
h->setSpacing( HIG :: PAD );
|
||||||
r = new QRadioButton( tr( "&Stop seeding when a torrent's ratio reaches" ) );
|
r = new QRadioButton( tr( "&Stop seeding when a torrent's ratio reaches" ) );
|
||||||
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_SINGLE );
|
r->setProperty( RATIO_KEY, TR_RATIOLIMIT_SINGLE );
|
||||||
connect( r, SIGNAL(toggled(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
connect( r, SIGNAL(clicked(bool)), this, SLOT(onSeedUntilChanged(bool)));
|
||||||
mySeedCustomRadio = r;
|
mySeedCustomRadio = r;
|
||||||
h->addWidget( r );
|
h->addWidget( r );
|
||||||
ds = new QDoubleSpinBox( );
|
ds = new QDoubleSpinBox( );
|
||||||
|
@ -633,12 +906,12 @@ Details :: onFilePriorityChanged( const QSet<int>& indices, int priority )
|
||||||
case TR_PRI_HIGH: key = "priority-high"; break;
|
case TR_PRI_HIGH: key = "priority-high"; break;
|
||||||
default: key = "priority-normal"; break;
|
default: key = "priority-normal"; break;
|
||||||
}
|
}
|
||||||
mySession.torrentSet( myTorrent.id( ), key, indices.toList( ) );
|
mySession.torrentSet( myIds, key, indices.toList( ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Details :: onFileWantedChanged( const QSet<int>& indices, bool wanted )
|
Details :: onFileWantedChanged( const QSet<int>& indices, bool wanted )
|
||||||
{
|
{
|
||||||
QString key( wanted ? "files-wanted" : "files-unwanted" );
|
QString key( wanted ? "files-wanted" : "files-unwanted" );
|
||||||
mySession.torrentSet( myTorrent.id( ), key, indices.toList( ) );
|
mySession.torrentSet( myIds, key, indices.toList( ) );
|
||||||
}
|
}
|
||||||
|
|
14
qt/details.h
14
qt/details.h
|
@ -18,11 +18,13 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QWidgetList>
|
||||||
|
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
|
|
||||||
class FileTreeView;
|
class FileTreeView;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
|
class QComboBox;
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QDoubleSpinBox;
|
class QDoubleSpinBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
@ -33,6 +35,7 @@ class QTreeWidget;
|
||||||
class QTreeWidgetItem;
|
class QTreeWidgetItem;
|
||||||
class Session;
|
class Session;
|
||||||
class Torrent;
|
class Torrent;
|
||||||
|
class TorrentModel;
|
||||||
|
|
||||||
class Details: public QDialog
|
class Details: public QDialog
|
||||||
{
|
{
|
||||||
|
@ -43,8 +46,9 @@ class Details: public QDialog
|
||||||
void onTimer( );
|
void onTimer( );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Details( Session&, Torrent&, QWidget * parent = 0 );
|
Details( Session&, TorrentModel&, QWidget * parent = 0 );
|
||||||
~Details( );
|
~Details( );
|
||||||
|
void setIds( const QSet<int>& ids );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget * createActivityTab( );
|
QWidget * createActivityTab( );
|
||||||
|
@ -61,8 +65,10 @@ class Details: public QDialog
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Session& mySession;
|
Session& mySession;
|
||||||
Torrent& myTorrent;
|
TorrentModel& myModel;
|
||||||
|
QSet<int> myIds;
|
||||||
QTimer myTimer;
|
QTimer myTimer;
|
||||||
|
bool myHavePendingRefresh;
|
||||||
|
|
||||||
QLabel * myStateLabel;
|
QLabel * myStateLabel;
|
||||||
QLabel * myProgressLabel;
|
QLabel * myProgressLabel;
|
||||||
|
@ -86,6 +92,7 @@ class Details: public QDialog
|
||||||
QRadioButton * mySeedCustomRadio;
|
QRadioButton * mySeedCustomRadio;
|
||||||
QDoubleSpinBox * mySeedCustomSpin;
|
QDoubleSpinBox * mySeedCustomSpin;
|
||||||
QSpinBox * myPeerLimitSpin;
|
QSpinBox * myPeerLimitSpin;
|
||||||
|
QComboBox * myBandwidthPriorityCombo;
|
||||||
|
|
||||||
QLabel * myPiecesLabel;
|
QLabel * myPiecesLabel;
|
||||||
QLabel * myHashLabel;
|
QLabel * myHashLabel;
|
||||||
|
@ -110,10 +117,12 @@ class Details: public QDialog
|
||||||
QLabel * myTimesCompletedLabel;
|
QLabel * myTimesCompletedLabel;
|
||||||
QTreeWidget * myPeerTree;
|
QTreeWidget * myPeerTree;
|
||||||
QMap<QString,QTreeWidgetItem*> myPeers;
|
QMap<QString,QTreeWidgetItem*> myPeers;
|
||||||
|
QWidgetList myWidgets;
|
||||||
|
|
||||||
FileTreeView * myFileTreeView;
|
FileTreeView * myFileTreeView;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void onBandwidthPriorityChanged( int );
|
||||||
void onFilePriorityChanged( const QSet<int>& fileIndices, int );
|
void onFilePriorityChanged( const QSet<int>& fileIndices, int );
|
||||||
void onFileWantedChanged( const QSet<int>& fileIndices, bool );
|
void onFileWantedChanged( const QSet<int>& fileIndices, bool );
|
||||||
void onHonorsSessionLimitsToggled( bool );
|
void onHonorsSessionLimitsToggled( bool );
|
||||||
|
@ -124,6 +133,7 @@ class Details: public QDialog
|
||||||
void onSeedUntilChanged( bool );
|
void onSeedUntilChanged( bool );
|
||||||
void onSeedRatioLimitChanged( double );
|
void onSeedRatioLimitChanged( double );
|
||||||
void onMaxPeersChanged( int );
|
void onMaxPeersChanged( int );
|
||||||
|
void refresh( );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -80,6 +80,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
|
||||||
myPrefsDialog( new PrefsDialog( session, prefs, this ) ),
|
myPrefsDialog( new PrefsDialog( session, prefs, this ) ),
|
||||||
myAboutDialog( new AboutDialog( this ) ),
|
myAboutDialog( new AboutDialog( this ) ),
|
||||||
myStatsDialog( new StatsDialog( session, this ) ),
|
myStatsDialog( new StatsDialog( session, this ) ),
|
||||||
|
myDetailsDialog( 0 ),
|
||||||
myFileDialog( 0 ),
|
myFileDialog( 0 ),
|
||||||
myFilterModel( prefs ),
|
myFilterModel( prefs ),
|
||||||
myTorrentDelegate( new TorrentDelegate( this ) ),
|
myTorrentDelegate( new TorrentDelegate( this ) ),
|
||||||
|
@ -549,14 +550,22 @@ TrMainWindow :: setSortAscendingPref( bool b )
|
||||||
*****
|
*****
|
||||||
****/
|
****/
|
||||||
|
|
||||||
|
void
|
||||||
|
TrMainWindow :: onDetailsDestroyed( )
|
||||||
|
{
|
||||||
|
myDetailsDialog = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TrMainWindow :: openProperties( )
|
TrMainWindow :: openProperties( )
|
||||||
{
|
{
|
||||||
const int id( *getSelectedTorrents().begin() );
|
if( myDetailsDialog == 0 ) {
|
||||||
Torrent * torrent( myModel.getTorrentFromId( id ) );
|
myDetailsDialog = new Details( mySession, myModel, this );
|
||||||
assert( torrent != 0 );
|
connect( myDetailsDialog, SIGNAL(destroyed(QObject*)), this, SLOT(onDetailsDestroyed()));
|
||||||
QDialog * d( new Details( mySession, *torrent, this ) );
|
}
|
||||||
d->show( );
|
|
||||||
|
myDetailsDialog->setIds( getSelectedTorrents( ) );
|
||||||
|
myDetailsDialog->show( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -658,10 +667,10 @@ TrMainWindow :: refreshActionSensitivity( )
|
||||||
ui.action_Verify->setEnabled( haveSelection );
|
ui.action_Verify->setEnabled( haveSelection );
|
||||||
ui.action_Remove->setEnabled( haveSelection );
|
ui.action_Remove->setEnabled( haveSelection );
|
||||||
ui.action_Delete->setEnabled( haveSelection );
|
ui.action_Delete->setEnabled( haveSelection );
|
||||||
|
ui.action_Properties->setEnabled( haveSelection );
|
||||||
ui.action_DeselectAll->setEnabled( haveSelection );
|
ui.action_DeselectAll->setEnabled( haveSelection );
|
||||||
|
|
||||||
const bool oneSelection( selected == 1 );
|
const bool oneSelection( selected == 1 );
|
||||||
ui.action_Properties->setEnabled( oneSelection );
|
|
||||||
ui.action_OpenFolder->setEnabled( oneSelection );
|
ui.action_OpenFolder->setEnabled( oneSelection );
|
||||||
|
|
||||||
ui.action_SelectAll->setEnabled( selected < rowCount );
|
ui.action_SelectAll->setEnabled( selected < rowCount );
|
||||||
|
@ -670,6 +679,9 @@ TrMainWindow :: refreshActionSensitivity( )
|
||||||
ui.action_Start->setEnabled( selectedAndPaused > 0 );
|
ui.action_Start->setEnabled( selectedAndPaused > 0 );
|
||||||
ui.action_Pause->setEnabled( selectedAndPaused < selected );
|
ui.action_Pause->setEnabled( selectedAndPaused < selected );
|
||||||
ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
|
ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
|
||||||
|
|
||||||
|
if( myDetailsDialog )
|
||||||
|
myDetailsDialog->setIds( getSelectedTorrents( ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,6 +35,7 @@ extern "C" {
|
||||||
|
|
||||||
class ActionDelegator;
|
class ActionDelegator;
|
||||||
class Prefs;
|
class Prefs;
|
||||||
|
class Details;
|
||||||
class Session;
|
class Session;
|
||||||
class TorrentDelegate;
|
class TorrentDelegate;
|
||||||
class TorrentDelegateMin;
|
class TorrentDelegateMin;
|
||||||
|
@ -54,6 +55,7 @@ class TrMainWindow: public QMainWindow
|
||||||
QDialog * myPrefsDialog;
|
QDialog * myPrefsDialog;
|
||||||
QDialog * myAboutDialog;
|
QDialog * myAboutDialog;
|
||||||
QDialog * myStatsDialog;
|
QDialog * myStatsDialog;
|
||||||
|
Details * myDetailsDialog;
|
||||||
QFileDialog * myFileDialog;
|
QFileDialog * myFileDialog;
|
||||||
QCheckBox * myFileDialogOptionsCheck;
|
QCheckBox * myFileDialogOptionsCheck;
|
||||||
QSystemTrayIcon myTrayIcon;
|
QSystemTrayIcon myTrayIcon;
|
||||||
|
@ -86,6 +88,7 @@ class TrMainWindow: public QMainWindow
|
||||||
QWidgetList myHidden;
|
QWidgetList myHidden;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void onDetailsDestroyed( );
|
||||||
void onShowModeClicked( );
|
void onShowModeClicked( );
|
||||||
void showAll( );
|
void showAll( );
|
||||||
void showActive( );
|
void showActive( );
|
||||||
|
|
|
@ -297,6 +297,9 @@ PrefsDialog :: createBandwidthTab( )
|
||||||
r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5 );
|
r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5 );
|
||||||
hig->addRow( s, r );
|
hig->addRow( s, r );
|
||||||
|
|
||||||
|
s = tr( "<small>When enabled, Speed Limit Mode overrides the Global Bandwidth Limits</small>" );
|
||||||
|
hig->addWideControl( new QLabel( s ) );
|
||||||
|
|
||||||
QCheckBox * c = checkBoxNew( tr( "Use Speed Limit Mode &between" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED );
|
QCheckBox * c = checkBoxNew( tr( "Use Speed Limit Mode &between" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED );
|
||||||
h = new QHBoxLayout( );
|
h = new QHBoxLayout( );
|
||||||
h->setSpacing( HIG::PAD );
|
h->setSpacing( HIG::PAD );
|
||||||
|
|
|
@ -280,49 +280,61 @@ namespace
|
||||||
const int Session :: ADD_TORRENT_TAG = TAG_ADD_TORRENT;
|
const int Session :: ADD_TORRENT_TAG = TAG_ADD_TORRENT;
|
||||||
|
|
||||||
void
|
void
|
||||||
Session :: torrentSet( int id, const QString& key, double value )
|
Session :: torrentSet( const QSet<int>& ids, const QString& key, double value )
|
||||||
{
|
{
|
||||||
QString s;
|
tr_benc top;
|
||||||
QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
|
tr_bencInitDict( &top, 2 );
|
||||||
std::cerr << qPrintable(s) << std::endl;
|
tr_bencDictAddStr( &top, "method", "torrent-set" );
|
||||||
exec( s.toUtf8().constData() );
|
tr_benc * args = tr_bencDictAddDict( &top, "arguments", 2 );
|
||||||
refreshExtraStats( id );
|
tr_bencDictAddReal( args, key.toUtf8().constData(), value );
|
||||||
|
addOptionalIds( args, ids );
|
||||||
|
std::cerr << tr_bencToJSON(&top) << std::endl;
|
||||||
|
exec( &top );
|
||||||
|
tr_bencFree( &top );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session :: torrentSet( int id, const QString& key, int value )
|
Session :: torrentSet( const QSet<int>& ids, const QString& key, int value )
|
||||||
{
|
{
|
||||||
QString s;
|
tr_benc top;
|
||||||
QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
|
tr_bencInitDict( &top, 2 );
|
||||||
std::cerr << qPrintable(s) << std::endl;
|
tr_bencDictAddStr( &top, "method", "torrent-set" );
|
||||||
exec( s.toUtf8().constData() );
|
tr_benc * args = tr_bencDictAddDict( &top, "arguments", 2 );
|
||||||
refreshExtraStats( id );
|
tr_bencDictAddInt( args, key.toUtf8().constData(), value );
|
||||||
|
addOptionalIds( args, ids );
|
||||||
|
std::cerr << tr_bencToJSON(&top) << std::endl;
|
||||||
|
exec( &top );
|
||||||
|
tr_bencFree( &top );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session :: torrentSet( int id, const QString& key, bool value )
|
Session :: torrentSet( const QSet<int>& ids, const QString& key, bool value )
|
||||||
{
|
{
|
||||||
QString s;
|
tr_benc top;
|
||||||
QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<(value?"true":"false")<<" } }";
|
tr_bencInitDict( &top, 2 );
|
||||||
std::cerr << qPrintable(s) << std::endl;
|
tr_bencDictAddStr( &top, "method", "torrent-set" );
|
||||||
exec( s.toUtf8().constData() );
|
tr_benc * args = tr_bencDictAddDict( &top, "arguments", 2 );
|
||||||
refreshExtraStats( id );
|
tr_bencDictAddBool( args, key.toUtf8().constData(), value );
|
||||||
|
addOptionalIds( args, ids );
|
||||||
|
std::cerr << tr_bencToJSON(&top) << std::endl;
|
||||||
|
exec( &top );
|
||||||
|
tr_bencFree( &top );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session :: torrentSet( int id, const QString& key, const QList<int>& value )
|
Session :: torrentSet( const QSet<int>& ids, const QString& key, const QList<int>& value )
|
||||||
{
|
{
|
||||||
tr_benc top;
|
tr_benc top;
|
||||||
tr_bencInitDict( &top, 2 );
|
tr_bencInitDict( &top, 2 );
|
||||||
tr_bencDictAddStr( &top, "method", "torrent-set" );
|
tr_bencDictAddStr( &top, "method", "torrent-set" );
|
||||||
tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
|
tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
|
||||||
tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
|
addOptionalIds( args, ids );
|
||||||
tr_benc * list( tr_bencDictAddList( args, key.toUtf8().constData(), value.size( ) ) );
|
tr_benc * list( tr_bencDictAddList( args, key.toUtf8().constData(), value.size( ) ) );
|
||||||
foreach( int i, value )
|
foreach( int i, value )
|
||||||
tr_bencListAddInt( list, i );
|
tr_bencListAddInt( list, i );
|
||||||
|
std::cerr << tr_bencToJSON(&top) << std::endl;
|
||||||
exec( &top );
|
exec( &top );
|
||||||
tr_bencFree( &top );
|
tr_bencFree( &top );
|
||||||
refreshExtraStats( id );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -348,14 +360,14 @@ Session :: refreshTorrents( const QSet<int>& ids )
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session :: refreshExtraStats( int id )
|
Session :: refreshExtraStats( const QSet<int>& ids )
|
||||||
{
|
{
|
||||||
tr_benc top;
|
tr_benc top;
|
||||||
tr_bencInitDict( &top, 3 );
|
tr_bencInitDict( &top, 3 );
|
||||||
tr_bencDictAddStr( &top, "method", "torrent-get" );
|
tr_bencDictAddStr( &top, "method", "torrent-get" );
|
||||||
tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
|
tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
|
||||||
tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
|
tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
|
||||||
tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
|
addOptionalIds( args, ids );
|
||||||
addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) + getExtraStatKeys( ));
|
addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) + getExtraStatKeys( ));
|
||||||
exec( &top );
|
exec( &top );
|
||||||
tr_bencFree( &top );
|
tr_bencFree( &top );
|
||||||
|
|
11
qt/session.h
11
qt/session.h
|
@ -77,10 +77,11 @@ class Session: public QObject
|
||||||
void refreshTorrents( const QSet<int>& torrentIds );
|
void refreshTorrents( const QSet<int>& torrentIds );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void torrentSet( int id, const QString& key, bool val );
|
void torrentSet( const QSet<int>& ids, const QString& key, bool val );
|
||||||
void torrentSet( int id, const QString& key, int val );
|
void torrentSet( const QSet<int>& ids, const QString& key, int val );
|
||||||
void torrentSet( int id, const QString& key, double val );
|
void torrentSet( const QSet<int>& ids, const QString& key, double val );
|
||||||
void torrentSet( int id, const QString& key, const QList<int>& val );
|
void torrentSet( const QSet<int>& ids, const QString& key, const QList<int>& val );
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void pause( const QSet<int>& torrentIds = QSet<int>() );
|
void pause( const QSet<int>& torrentIds = QSet<int>() );
|
||||||
|
@ -98,7 +99,7 @@ class Session: public QObject
|
||||||
void updatePref( int key );
|
void updatePref( int key );
|
||||||
|
|
||||||
/** request a refresh for statistics, including the ones only used by the properties dialog, for a specific torrent */
|
/** request a refresh for statistics, including the ones only used by the properties dialog, for a specific torrent */
|
||||||
void refreshExtraStats( int torrent );
|
void refreshExtraStats( const QSet<int>& ids );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onRequestStarted( int id );
|
void onRequestStarted( int id );
|
||||||
|
|
|
@ -108,7 +108,8 @@ Torrent :: myProperties[] =
|
||||||
{ LEECHERS, "leechers", QVariant::Int, STAT_EXTRA },
|
{ LEECHERS, "leechers", QVariant::Int, STAT_EXTRA },
|
||||||
{ TIMES_COMPLETED, "timesCompleted", QVariant::Int, STAT_EXTRA },
|
{ TIMES_COMPLETED, "timesCompleted", QVariant::Int, STAT_EXTRA },
|
||||||
{ PEERS, "peers", TrTypes::PeerList, STAT_EXTRA },
|
{ PEERS, "peers", TrTypes::PeerList, STAT_EXTRA },
|
||||||
{ TORRENT_FILE, "torrentFile", QVariant::String, STAT_EXTRA }
|
{ TORRENT_FILE, "torrentFile", QVariant::String, STAT_EXTRA },
|
||||||
|
{ BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA }
|
||||||
};
|
};
|
||||||
|
|
||||||
Torrent :: KeyList
|
Torrent :: KeyList
|
||||||
|
|
|
@ -139,6 +139,7 @@ class Torrent: public QObject
|
||||||
TIMES_COMPLETED,
|
TIMES_COMPLETED,
|
||||||
PEERS,
|
PEERS,
|
||||||
TORRENT_FILE,
|
TORRENT_FILE,
|
||||||
|
BANDWIDTH_PRIORITY,
|
||||||
|
|
||||||
PROPERTY_COUNT
|
PROPERTY_COUNT
|
||||||
};
|
};
|
||||||
|
@ -200,6 +201,7 @@ class Torrent: public QObject
|
||||||
bool setDateTime ( int key, const QDateTime& );
|
bool setDateTime ( int key, const QDateTime& );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int getBandwidthPriority( ) const { return getInt( BANDWIDTH_PRIORITY ); }
|
||||||
int id( ) const { return getInt( ID ); }
|
int id( ) const { return getInt( ID ); }
|
||||||
QString name( ) const { return getString( NAME ); }
|
QString name( ) const { return getString( NAME ); }
|
||||||
QString creator( ) const { return getString( CREATOR ); }
|
QString creator( ) const { return getString( CREATOR ); }
|
||||||
|
|
Loading…
Reference in New Issue