From bc25b7591e9a154640a159f8866051fb91e3a485 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 3 Dec 2009 17:23:53 +0000 Subject: [PATCH] (trunk Qt) #2096 "magnet links" -- fix crashes when displaying magnet links in Qt client --- qt/details.cc | 16 +++++++++------- qt/mainwin.cc | 26 ++++++++++++++++++++++---- qt/mainwin.h | 1 + qt/mainwin.ui | 16 +++++++++++----- qt/session.cc | 31 +++++++++++++++++++------------ qt/torrent.cc | 5 ++++- qt/torrent.h | 3 +++ 7 files changed, 69 insertions(+), 29 deletions(-) diff --git a/qt/details.cc b/qt/details.cc index 4cf7b07c4..792d56a2e 100644 --- a/qt/details.cc +++ b/qt/details.cc @@ -254,13 +254,15 @@ Details :: refresh( ) int64_t haveUnverified = 0; int64_t verifiedPieces = 0; foreach( const Torrent * t, torrents ) { - haveTotal += t->haveTotal( ); - haveUnverified += t->haveUnverified( ); - const uint64_t v = t->haveVerified( ); - haveVerified += v; - verifiedPieces += v / t->pieceSize( ); - sizeWhenDone += t->sizeWhenDone( ); - leftUntilDone += t->leftUntilDone( ); + if( t->hasMetadata( ) ) { + haveTotal += t->haveTotal( ); + haveUnverified += t->haveUnverified( ); + const uint64_t v = t->haveVerified( ); + haveVerified += v; + verifiedPieces += v / t->pieceSize( ); + sizeWhenDone += t->sizeWhenDone( ); + leftUntilDone += t->leftUntilDone( ); + } } if( !haveVerified && !haveUnverified ) string = none; diff --git a/qt/mainwin.cc b/qt/mainwin.cc index 2b67d3d97..1fb6a62eb 100644 --- a/qt/mainwin.cc +++ b/qt/mainwin.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode const QSize smallIconSize( i, i ); // icons - ui.action_Add->setIcon( getStockIcon( "list-add", QStyle::SP_DialogOpenButton ) ); + ui.action_AddFile->setIcon( getStockIcon( "list-add", QStyle::SP_DialogOpenButton ) ); ui.action_New->setIcon( getStockIcon( "document-new", QStyle::SP_DesktopIcon ) ); ui.action_Properties->setIcon( getStockIcon( "document-properties", QStyle::SP_DesktopIcon ) ); ui.action_OpenFolder->setIcon( getStockIcon( "folder-open", QStyle::SP_DirOpenIcon ) ); @@ -152,7 +153,8 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode connect( ui.action_Announce, SIGNAL(triggered()), this, SLOT(reannounceSelected()) ); connect( ui.action_StartAll, SIGNAL(triggered()), this, SLOT(startAll())); connect( ui.action_PauseAll, SIGNAL(triggered()), this, SLOT(pauseAll())); - connect( ui.action_Add, SIGNAL(triggered()), this, SLOT(openTorrent())); + connect( ui.action_AddFile, SIGNAL(triggered()), this, SLOT(openTorrent())); + connect( ui.action_AddURL, SIGNAL(triggered()), this, SLOT(openURL())); connect( ui.action_New, SIGNAL(triggered()), this, SLOT(newTorrent())); connect( ui.action_Preferences, SIGNAL(triggered()), myPrefsDialog, SLOT(show())); connect( ui.action_Statistics, SIGNAL(triggered()), myStatsDialog, SLOT(show())); @@ -219,7 +221,8 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode actionGroup->addAction( ui.action_SortByTracker ); QMenu * menu = new QMenu( ); - menu->addAction( ui.action_Add ); + menu->addAction( ui.action_AddFile ); + menu->addAction( ui.action_AddURL ); menu->addSeparator( ); menu->addAction( ui.action_ShowMainWindow ); menu->addAction( ui.action_ShowMessageLog ); @@ -1099,12 +1102,27 @@ TrMainWindow :: openTorrent( ) layout->addWidget( button, layout->rowCount( ), 0, 1, -1, Qt::AlignLeft ); myFileDialogOptionsCheck = button; - connect( myFileDialog, SIGNAL(filesSelected(const QStringList&)), this, SLOT(addTorrents(const QStringList&))); + connect( myFileDialog, SIGNAL(filesSelected(const QStringList&)), + this, SLOT(addTorrents(const QStringList&))); } myFileDialog->show( ); } +void +TrMainWindow :: openURL( ) +{ + bool ok; + const QString key = QInputDialog::getText( this, + tr( "Add URL or Magnet Link" ), + tr( "Add URL or Magnet Link" ), + QLineEdit::Normal, + QString( ), + &ok ); + if( ok && !key.isEmpty( ) ) + mySession.addTorrent( key ); +} + void TrMainWindow :: addTorrents( const QStringList& filenames ) { diff --git a/qt/mainwin.h b/qt/mainwin.h index b5437d0e3..133eb8b98 100644 --- a/qt/mainwin.h +++ b/qt/mainwin.h @@ -110,6 +110,7 @@ class TrMainWindow: public QMainWindow void refreshTitle( ); void refreshStatusBar( ); void openTorrent( ); + void openURL( ); void newTorrent( ); void trayActivated( QSystemTrayIcon::ActivationReason ); void refreshPref( int key ); diff --git a/qt/mainwin.ui b/qt/mainwin.ui index 4300b3812..23092e782 100644 --- a/qt/mainwin.ui +++ b/qt/mainwin.ui @@ -51,7 +51,7 @@ 0 0 792 - 23 + 25 @@ -126,7 +126,8 @@ &File - + + @@ -168,16 +169,16 @@ false - + - + - &Add... + &Add File... Add a torrent @@ -549,6 +550,11 @@ &Copy Magnet Link to Clipboard + + + Add &URL... + + diff --git a/qt/session.cc b/qt/session.cc index d130c5221..7e789549e 100644 --- a/qt/session.cc +++ b/qt/session.cc @@ -857,30 +857,37 @@ Session :: addTorrent( QString filename ) } void -Session :: addTorrent( QString filename, QString localPath ) +Session :: addTorrent( QString key, QString localPath ) { - QFile file( filename ); + tr_benc top, *args; + tr_bencInitDict( &top, 2 ); + tr_bencDictAddStr( &top, "method", "torrent-add" ); + args = tr_bencDictAddDict( &top, "arguments", 3 ); + tr_bencDictAddStr( args, "download-dir", qPrintable(localPath) ); + tr_bencDictAddInt( 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_benc top, *args; - tr_bencInitDict( &top, 2 ); - tr_bencDictAddStr( &top, "method", "torrent-add" ); - args = tr_bencDictAddDict( &top, "arguments", 3 ); - tr_bencDictAddStr( args, "download-dir", qPrintable(localPath) ); tr_bencDictAddRaw( args, "metainfo", b64, b64len ); - tr_bencDictAddInt( args, "paused", !myPrefs.getBool( Prefs::START ) ); - exec( &top ); - tr_free( b64 ); tr_bencFree( &top ); } + else + { + tr_bencDictAddStr( args, "filename", key.toUtf8().constData() ); + } + + exec( &top ); + tr_bencFree( &top ); } void diff --git a/qt/torrent.cc b/qt/torrent.cc index 888db7ab5..b779fd7ce 100644 --- a/qt/torrent.cc +++ b/qt/torrent.cc @@ -71,6 +71,7 @@ Torrent :: myProperties[] = { PEERS_SENDING_TO_US, "peersSendingToUs", QVariant::Int, STAT }, { WEBSEEDS_SENDING_TO_US, "webseedsSendingToUs", QVariant::Int, STAT_EXTRA }, { PERCENT_DONE, "percentDone", QVariant::Double, STAT }, + { METADATA_PERCENT_DONE, "metadataPercentComplete", QVariant::Double, STAT }, { PERCENT_VERIFIED, "recheckProgress", QVariant::Double, STAT }, { DATE_ACTIVITY, "activityDate", QVariant::DateTime, STAT_EXTRA }, { DATE_ADDED, "addedDate", QVariant::DateTime, INFO }, @@ -413,8 +414,10 @@ Torrent :: updateMimeIcon( ) if( files.size( ) > 1 ) icon = QFileIconProvider().icon( QFileIconProvider::Folder ); - else + else if( files.size( ) == 1 ) icon = Utils :: guessMimeIcon( files.at(0).filename ); + else + icon = QIcon( ); setIcon( MIME_ICON, icon ); } diff --git a/qt/torrent.h b/qt/torrent.h index 9fc12a3bf..590463e4b 100644 --- a/qt/torrent.h +++ b/qt/torrent.h @@ -101,6 +101,7 @@ class Torrent: public QObject PEERS_SENDING_TO_US, WEBSEEDS_SENDING_TO_US, PERCENT_DONE, + METADATA_PERCENT_DONE, PERCENT_VERIFIED, DATE_ACTIVITY, DATE_ADDED, @@ -222,9 +223,11 @@ class Torrent: public QObject uint64_t sizeWhenDone( ) const { return getSize( SIZE_WHEN_DONE ); } uint64_t leftUntilDone( ) const { return getSize( LEFT_UNTIL_DONE ); } uint64_t pieceSize( ) const { return getSize( PIECE_SIZE ); } + bool hasMetadata( ) const { return getDouble( METADATA_PERCENT_DONE ) >= 1.0; } int pieceCount( ) const { return getInt( PIECE_COUNT ); } double ratio( ) const { return getDouble( RATIO ); } double percentDone( ) const { return getDouble( PERCENT_DONE ); } + double metadataPercentDone( ) const { return getDouble( METADATA_PERCENT_DONE ); } uint64_t downloadedEver( ) const { return getSize( DOWNLOADED_EVER ); } uint64_t uploadedEver( ) const { return getSize( UPLOADED_EVER ); } uint64_t failedEver( ) const { return getSize( FAILED_EVER ); }