2009-11-07 22:55:33 +03:00
/*
2018-06-06 16:48:17 +03:00
* Bittorrent Client using Qt and libtorrent .
2018-05-24 18:39:02 +03:00
* Copyright ( C ) 2006 Christophe Dumez < chris @ qbittorrent . org >
2009-11-07 22:55:33 +03:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* In addition , as a special exception , the copyright holders give permission to
* link this program with the OpenSSL project ' s " OpenSSL " library ( or with
* modified versions of it that use the same license as the " OpenSSL " library ) ,
* and distribute the linked executables . You must obey the GNU General Public
* License in all respects for all of the code used other than " OpenSSL " . If you
* modify file ( s ) , you may extend this exception to your version of the file ( s ) ,
* but you are not obligated to do so . If you do not wish to do so , delete this
* exception statement from your version .
*/
2017-03-30 05:17:39 +03:00
# include "transferlistwidget.h"
2019-06-24 18:37:31 +03:00
# include <algorithm>
2009-11-07 22:55:33 +03:00
# include <QClipboard>
2017-03-30 05:17:39 +03:00
# include <QDebug>
2010-05-21 18:26:18 +04:00
# include <QFileDialog>
2019-02-24 19:31:39 +03:00
# include <QHeaderView>
2017-03-30 05:17:39 +03:00
# include <QMenu>
2010-12-26 12:51:37 +03:00
# include <QMessageBox>
2017-03-30 05:17:39 +03:00
# include <QRegExp>
2018-05-24 18:41:03 +03:00
# include <QRegularExpression>
2019-06-24 18:37:31 +03:00
# include <QSet>
2017-03-30 05:17:39 +03:00
# include <QShortcut>
2015-11-18 19:13:25 +03:00
# include <QTableView>
2017-03-30 05:17:39 +03:00
# include <QWheelEvent>
2010-12-26 12:51:37 +03:00
2015-09-25 11:10:05 +03:00
# include "base/bittorrent/session.h"
# include "base/bittorrent/torrenthandle.h"
2019-06-24 18:37:31 +03:00
# include "base/bittorrent/trackerentry.h"
2018-11-18 21:40:37 +03:00
# include "base/global.h"
2017-03-30 05:06:09 +03:00
# include "base/logger.h"
2017-03-30 05:17:39 +03:00
# include "base/preferences.h"
2015-09-25 11:10:05 +03:00
# include "base/torrentfilter.h"
2017-03-30 05:17:39 +03:00
# include "base/utils/fs.h"
2018-10-24 20:20:33 +03:00
# include "base/utils/misc.h"
2017-03-30 05:17:39 +03:00
# include "base/utils/string.h"
2018-05-24 18:39:02 +03:00
# include "autoexpandabledialog.h"
2018-06-14 12:54:23 +03:00
# include "deletionconfirmationdialog.h"
2017-03-30 05:17:39 +03:00
# include "mainwindow.h"
2018-06-14 12:54:23 +03:00
# include "optionsdialog.h"
2017-09-11 21:32:11 +03:00
# include "previewselectdialog.h"
2018-06-14 12:54:23 +03:00
# include "speedlimitdialog.h"
2017-09-24 14:54:42 +03:00
# include "torrentcategorydialog.h"
2019-06-24 18:37:31 +03:00
# include "trackerentriesdialog.h"
2017-03-30 05:17:39 +03:00
# include "transferlistdelegate.h"
2018-06-14 12:54:23 +03:00
# include "transferlistmodel.h"
2014-09-13 17:12:07 +04:00
# include "transferlistsortmodel.h"
2019-07-07 16:02:13 +03:00
# include "tristateaction.h"
2019-07-16 07:01:33 +03:00
# include "uithememanager.h"
2018-06-14 12:54:23 +03:00
# include "updownratiodialog.h"
2019-03-02 08:22:13 +03:00
# include "utils.h"
2010-07-16 19:03:18 +04:00
2017-12-12 18:00:56 +03:00
# ifdef Q_OS_MAC
# include "macutilities.h"
# endif
2017-07-10 02:15:08 +03:00
namespace
{
2019-06-27 18:36:54 +03:00
QStringList extractHashes ( const QVector < BitTorrent : : TorrentHandle * > & torrents )
2017-07-10 02:15:08 +03:00
{
QStringList hashes ;
2018-11-18 21:40:37 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : torrents )
2017-07-10 02:15:08 +03:00
hashes < < torrent - > hash ( ) ;
return hashes ;
}
2018-10-24 20:20:33 +03:00
bool torrentContainsPreviewableFiles ( const BitTorrent : : TorrentHandle * const torrent )
{
if ( ! torrent - > hasMetadata ( ) )
return false ;
for ( int i = 0 ; i < torrent - > filesCount ( ) ; + + i ) {
if ( Utils : : Misc : : isPreviewable ( Utils : : Fs : : fileExtension ( torrent - > fileName ( i ) ) ) )
return true ;
}
return false ;
}
2017-07-10 02:15:08 +03:00
}
2015-06-07 15:03:30 +03:00
2017-09-25 20:03:24 +03:00
TransferListWidget : : TransferListWidget ( QWidget * parent , MainWindow * mainWindow )
2015-04-19 18:17:47 +03:00
: QTreeView ( parent )
2017-09-25 20:03:24 +03:00
, m_mainWindow ( mainWindow )
2014-12-08 04:40:58 +03:00
{
setUniformRowHeights ( true ) ;
// Load settings
2018-06-06 16:48:17 +03:00
bool columnLoaded = loadSettings ( ) ;
2014-12-08 04:40:58 +03:00
// Create and apply delegate
2017-09-25 20:03:24 +03:00
m_listDelegate = new TransferListDelegate ( this ) ;
setItemDelegate ( m_listDelegate ) ;
2014-12-08 04:40:58 +03:00
// Create transfer list model
2018-06-14 12:54:23 +03:00
m_listModel = new TransferListModel ( this ) ;
2014-12-08 04:40:58 +03:00
2019-07-14 06:46:10 +03:00
m_sortFilterModel = new TransferListSortModel ( this ) ;
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setDynamicSortFilter ( true ) ;
m_sortFilterModel - > setSourceModel ( m_listModel ) ;
2018-06-14 12:54:23 +03:00
m_sortFilterModel - > setFilterKeyColumn ( TransferListModel : : TR_NAME ) ;
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setFilterRole ( Qt : : DisplayRole ) ;
m_sortFilterModel - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
2014-12-08 04:40:58 +03:00
2017-09-25 20:03:24 +03:00
setModel ( m_sortFilterModel ) ;
2014-12-08 04:40:58 +03:00
// Visual settings
setRootIsDecorated ( false ) ;
setAllColumnsShowFocus ( true ) ;
setSortingEnabled ( true ) ;
setSelectionMode ( QAbstractItemView : : ExtendedSelection ) ;
setItemsExpandable ( false ) ;
setAutoScroll ( true ) ;
setDragDropMode ( QAbstractItemView : : DragOnly ) ;
2013-09-21 11:59:58 +04:00
# if defined(Q_OS_MAC)
2014-12-08 04:40:58 +03:00
setAttribute ( Qt : : WA_MacShowFocusRect , false ) ;
2012-06-30 19:25:09 +04:00
# endif
2014-12-08 04:40:58 +03:00
header ( ) - > setStretchLastSection ( false ) ;
// Default hidden columns
2018-06-06 16:48:17 +03:00
if ( ! columnLoaded ) {
2018-06-14 12:54:23 +03:00
setColumnHidden ( TransferListModel : : TR_ADD_DATE , true ) ;
setColumnHidden ( TransferListModel : : TR_SEED_DATE , true ) ;
setColumnHidden ( TransferListModel : : TR_UPLIMIT , true ) ;
setColumnHidden ( TransferListModel : : TR_DLLIMIT , true ) ;
setColumnHidden ( TransferListModel : : TR_TRACKER , true ) ;
setColumnHidden ( TransferListModel : : TR_AMOUNT_DOWNLOADED , true ) ;
setColumnHidden ( TransferListModel : : TR_AMOUNT_UPLOADED , true ) ;
setColumnHidden ( TransferListModel : : TR_AMOUNT_DOWNLOADED_SESSION , true ) ;
setColumnHidden ( TransferListModel : : TR_AMOUNT_UPLOADED_SESSION , true ) ;
setColumnHidden ( TransferListModel : : TR_AMOUNT_LEFT , true ) ;
setColumnHidden ( TransferListModel : : TR_TIME_ELAPSED , true ) ;
setColumnHidden ( TransferListModel : : TR_SAVE_PATH , true ) ;
setColumnHidden ( TransferListModel : : TR_COMPLETED , true ) ;
setColumnHidden ( TransferListModel : : TR_RATIO_LIMIT , true ) ;
setColumnHidden ( TransferListModel : : TR_SEEN_COMPLETE_DATE , true ) ;
setColumnHidden ( TransferListModel : : TR_LAST_ACTIVITY , true ) ;
setColumnHidden ( TransferListModel : : TR_TOTAL_SIZE , true ) ;
2014-12-08 04:40:58 +03:00
}
2009-11-08 22:54:22 +03:00
2014-12-08 04:40:58 +03:00
//Ensure that at least one column is visible at all times
bool atLeastOne = false ;
2018-09-07 14:12:38 +03:00
for ( int i = 0 ; i < TransferListModel : : NB_COLUMNS ; + + i ) {
2014-12-08 04:40:58 +03:00
if ( ! isColumnHidden ( i ) ) {
atLeastOne = true ;
break ;
}
2010-08-14 19:53:05 +04:00
}
2014-12-08 04:40:58 +03:00
if ( ! atLeastOne )
2018-06-14 12:54:23 +03:00
setColumnHidden ( TransferListModel : : TR_NAME , false ) ;
2014-12-08 04:40:58 +03:00
//When adding/removing columns between versions some may
//end up being size 0 when the new version is launched with
//a conf file from the previous version.
2018-09-07 14:12:38 +03:00
for ( int i = 0 ; i < TransferListModel : : NB_COLUMNS ; + + i )
2016-06-22 20:01:02 +03:00
if ( ( columnWidth ( i ) < = 0 ) & & ( ! isColumnHidden ( i ) ) )
2014-12-08 04:40:58 +03:00
resizeColumnToContents ( i ) ;
setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
// Listen for list events
2018-04-18 16:59:41 +03:00
connect ( this , & QAbstractItemView : : doubleClicked , this , & TransferListWidget : : torrentDoubleClicked ) ;
connect ( this , & QWidget : : customContextMenuRequested , this , & TransferListWidget : : displayListMenu ) ;
2014-12-08 04:40:58 +03:00
header ( ) - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
2018-04-18 16:59:41 +03:00
connect ( header ( ) , & QWidget : : customContextMenuRequested , this , & TransferListWidget : : displayDLHoSMenu ) ;
connect ( header ( ) , & QHeaderView : : sectionMoved , this , & TransferListWidget : : saveSettings ) ;
connect ( header ( ) , & QHeaderView : : sectionResized , this , & TransferListWidget : : saveSettings ) ;
connect ( header ( ) , & QHeaderView : : sortIndicatorChanged , this , & TransferListWidget : : saveSettings ) ;
2019-07-13 07:55:21 +03:00
const auto * editHotkey = new QShortcut ( Qt : : Key_F2 , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( editHotkey , & QShortcut : : activated , this , & TransferListWidget : : renameSelectedTorrent ) ;
const auto * deleteHotkey = new QShortcut ( QKeySequence : : Delete , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( deleteHotkey , & QShortcut : : activated , this , & TransferListWidget : : softDeleteSelectedTorrents ) ;
const auto * permDeleteHotkey = new QShortcut ( Qt : : SHIFT + Qt : : Key_Delete , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( permDeleteHotkey , & QShortcut : : activated , this , & TransferListWidget : : permDeleteSelectedTorrents ) ;
const auto * doubleClickHotkey = new QShortcut ( Qt : : Key_Return , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( doubleClickHotkey , & QShortcut : : activated , this , & TransferListWidget : : torrentDoubleClicked ) ;
const auto * recheckHotkey = new QShortcut ( Qt : : CTRL + Qt : : Key_R , this , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( recheckHotkey , & QShortcut : : activated , this , & TransferListWidget : : recheckSelectedTorrents ) ;
2015-11-18 19:13:25 +03:00
// This hack fixes reordering of first column with Qt5.
// https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
QTableView unused ;
unused . setVerticalHeader ( header ( ) ) ;
header ( ) - > setParent ( this ) ;
unused . setVerticalHeader ( new QHeaderView ( Qt : : Horizontal ) ) ;
2014-12-08 04:40:58 +03:00
}
TransferListWidget : : ~ TransferListWidget ( )
{
// Save settings
saveSettings ( ) ;
}
2018-06-14 12:54:23 +03:00
TransferListModel * TransferListWidget : : getSourceModel ( ) const
2014-12-08 04:40:58 +03:00
{
2017-09-25 20:03:24 +03:00
return m_listModel ;
2014-12-08 04:40:58 +03:00
}
2019-02-12 03:45:30 +03:00
void TransferListWidget : : previewFile ( const QString & filePath )
2014-12-08 04:40:58 +03:00
{
2019-03-02 08:22:13 +03:00
Utils : : Gui : : openPath ( filePath ) ;
2014-12-08 04:40:58 +03:00
}
2019-07-14 06:46:10 +03:00
QModelIndex TransferListWidget : : mapToSource ( const QModelIndex & index ) const
2014-12-08 04:40:58 +03:00
{
Q_ASSERT ( index . isValid ( ) ) ;
2017-09-25 20:03:24 +03:00
if ( index . model ( ) = = m_sortFilterModel )
return m_sortFilterModel - > mapToSource ( index ) ;
2014-12-08 04:40:58 +03:00
return index ;
}
2019-07-14 06:46:10 +03:00
QModelIndex TransferListWidget : : mapFromSource ( const QModelIndex & index ) const
2014-12-08 04:40:58 +03:00
{
Q_ASSERT ( index . isValid ( ) ) ;
2017-09-25 20:03:24 +03:00
Q_ASSERT ( index . model ( ) = = m_sortFilterModel ) ;
return m_sortFilterModel - > mapFromSource ( index ) ;
2014-12-08 04:40:58 +03:00
}
2017-01-24 14:10:08 +03:00
void TransferListWidget : : torrentDoubleClicked ( )
2014-12-08 04:40:58 +03:00
{
2017-01-24 14:10:08 +03:00
const QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
2017-02-06 18:51:25 +03:00
if ( ( selectedIndexes . size ( ) ! = 1 ) | | ! selectedIndexes . first ( ) . isValid ( ) ) return ;
2017-01-24 14:10:08 +03:00
2017-09-25 20:03:24 +03:00
const QModelIndex index = m_listModel - > index ( mapToSource ( selectedIndexes . first ( ) ) . row ( ) ) ;
BitTorrent : : TorrentHandle * const torrent = m_listModel - > torrentHandle ( index ) ;
2015-04-19 18:17:47 +03:00
if ( ! torrent ) return ;
2014-12-08 04:40:58 +03:00
int action ;
2015-04-19 18:17:47 +03:00
if ( torrent - > isSeed ( ) )
2014-12-08 04:40:58 +03:00
action = Preferences : : instance ( ) - > getActionOnDblClOnTorrentFn ( ) ;
else
action = Preferences : : instance ( ) - > getActionOnDblClOnTorrentDl ( ) ;
2018-06-06 16:48:17 +03:00
switch ( action ) {
2014-12-08 04:40:58 +03:00
case TOGGLE_PAUSE :
2015-04-19 18:17:47 +03:00
if ( torrent - > isPaused ( ) )
torrent - > resume ( ) ;
2014-12-08 04:40:58 +03:00
else
2015-04-19 18:17:47 +03:00
torrent - > pause ( ) ;
2014-12-08 04:40:58 +03:00
break ;
case OPEN_DEST :
2017-12-17 02:16:36 +03:00
# ifdef Q_OS_MAC
MacUtils : : openFiles ( QSet < QString > { torrent - > contentPath ( true ) } ) ;
# else
2015-06-28 21:58:39 +03:00
if ( torrent - > filesCount ( ) = = 1 )
2019-03-02 08:22:13 +03:00
Utils : : Gui : : openFolderSelect ( torrent - > contentPath ( true ) ) ;
2015-06-28 21:58:39 +03:00
else
2019-03-02 08:22:13 +03:00
Utils : : Gui : : openPath ( torrent - > contentPath ( true ) ) ;
2017-12-17 02:16:36 +03:00
# endif
2015-06-28 21:58:39 +03:00
break ;
2010-08-14 19:53:05 +04:00
}
2009-11-07 22:55:33 +03:00
}
2019-06-27 18:36:54 +03:00
QVector < BitTorrent : : TorrentHandle * > TransferListWidget : : getSelectedTorrents ( ) const
2014-12-08 04:40:58 +03:00
{
2019-06-27 18:36:54 +03:00
QVector < BitTorrent : : TorrentHandle * > torrents ;
2018-11-27 23:15:04 +03:00
for ( const QModelIndex & index : asConst ( selectionModel ( ) - > selectedRows ( ) ) )
2017-09-25 20:03:24 +03:00
torrents < < m_listModel - > torrentHandle ( mapToSource ( index ) ) ;
2015-06-07 15:03:30 +03:00
return torrents ;
2009-11-07 22:55:33 +03:00
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : setSelectedTorrentsLocation ( )
{
2019-06-27 18:36:54 +03:00
const QVector < BitTorrent : : TorrentHandle * > torrents = getSelectedTorrents ( ) ;
2015-06-07 15:03:30 +03:00
if ( torrents . isEmpty ( ) ) return ;
2015-04-19 18:17:47 +03:00
2016-12-27 17:14:49 +03:00
const QString oldLocation = torrents [ 0 ] - > savePath ( ) ;
2017-08-13 13:56:03 +03:00
qDebug ( " Old location is %s " , qUtf8Printable ( oldLocation ) ) ;
2016-12-27 17:14:49 +03:00
const QString newLocation = QFileDialog : : getExistingDirectory ( this , tr ( " Choose save path " ) , oldLocation ,
2014-12-08 04:40:58 +03:00
QFileDialog : : DontConfirmOverwrite | QFileDialog : : ShowDirsOnly | QFileDialog : : HideNameFilterDetails ) ;
2017-03-30 05:14:33 +03:00
if ( newLocation . isEmpty ( ) | | ! QDir ( newLocation ) . exists ( ) ) return ;
2017-08-13 13:56:03 +03:00
qDebug ( " New location is %s " , qUtf8Printable ( newLocation ) ) ;
2016-12-27 17:14:49 +03:00
// Actually move storage
2018-11-18 21:40:37 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : torrents ) {
2018-03-06 18:49:12 +03:00
Logger : : instance ( ) - > addMessage ( tr ( " Set location: moving \" %1 \" , from \" %2 \" to \" %3 \" "
, " Set location: moving \" ubuntu_16_04.iso \" , from \" /home/dir1 \" to \" /home/dir2 \" " )
2018-04-23 12:42:42 +03:00
. arg ( torrent - > name ( ) , Utils : : Fs : : toNativePath ( torrent - > savePath ( ) )
, Utils : : Fs : : toNativePath ( newLocation ) ) ) ;
2016-12-27 17:14:49 +03:00
torrent - > move ( Utils : : Fs : : expandPathAbs ( newLocation ) ) ;
2017-03-30 05:06:09 +03:00
}
2009-11-07 22:55:33 +03:00
}
2015-04-19 18:17:47 +03:00
void TransferListWidget : : pauseAllTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( BitTorrent : : Session : : instance ( ) - > torrents ( ) ) )
2015-04-19 18:17:47 +03:00
torrent - > pause ( ) ;
}
void TransferListWidget : : resumeAllTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( BitTorrent : : Session : : instance ( ) - > torrents ( ) ) )
2015-04-19 18:17:47 +03:00
torrent - > resume ( ) ;
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : startSelectedTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2015-06-07 15:03:30 +03:00
torrent - > resume ( ) ;
2014-12-08 04:40:58 +03:00
}
2015-04-14 02:22:14 +03:00
void TransferListWidget : : forceStartSelectedTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2015-06-07 15:03:30 +03:00
torrent - > resume ( true ) ;
2015-04-14 02:22:14 +03:00
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : startVisibleTorrents ( )
{
2017-09-25 20:03:24 +03:00
for ( int i = 0 ; i < m_sortFilterModel - > rowCount ( ) ; + + i ) {
BitTorrent : : TorrentHandle * const torrent = m_listModel - > torrentHandle ( mapToSource ( m_sortFilterModel - > index ( i , 0 ) ) ) ;
2015-04-19 18:17:47 +03:00
if ( torrent )
torrent - > resume ( ) ;
2009-11-07 22:55:33 +03:00
}
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : pauseSelectedTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2015-06-07 15:03:30 +03:00
torrent - > pause ( ) ;
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : pauseVisibleTorrents ( )
{
2017-09-25 20:03:24 +03:00
for ( int i = 0 ; i < m_sortFilterModel - > rowCount ( ) ; + + i ) {
BitTorrent : : TorrentHandle * const torrent = m_listModel - > torrentHandle ( mapToSource ( m_sortFilterModel - > index ( i , 0 ) ) ) ;
2015-04-19 18:17:47 +03:00
if ( torrent )
torrent - > pause ( ) ;
2009-11-07 22:55:33 +03:00
}
}
2016-08-05 21:15:13 +03:00
void TransferListWidget : : softDeleteSelectedTorrents ( )
{
deleteSelectedTorrents ( false ) ;
}
void TransferListWidget : : permDeleteSelectedTorrents ( )
{
deleteSelectedTorrents ( true ) ;
}
void TransferListWidget : : deleteSelectedTorrents ( bool deleteLocalFiles )
2014-12-08 04:40:58 +03:00
{
2017-09-25 20:03:24 +03:00
if ( m_mainWindow - > currentTabWidget ( ) ! = this ) return ;
2015-04-19 18:17:47 +03:00
2019-06-27 18:36:54 +03:00
const QVector < BitTorrent : : TorrentHandle * > torrents = getSelectedTorrents ( ) ;
2015-06-07 15:03:30 +03:00
if ( torrents . empty ( ) ) return ;
2017-02-06 18:51:25 +03:00
if ( Preferences : : instance ( ) - > confirmTorrentDeletion ( )
2018-06-14 12:54:23 +03:00
& & ! DeletionConfirmationDialog : : askForDeletionConfirmation ( this , deleteLocalFiles , torrents . size ( ) , torrents [ 0 ] - > name ( ) ) )
2014-12-08 04:40:58 +03:00
return ;
2018-11-18 21:40:37 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : torrents )
2016-08-05 21:15:13 +03:00
BitTorrent : : Session : : instance ( ) - > deleteTorrent ( torrent - > hash ( ) , deleteLocalFiles ) ;
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : deleteVisibleTorrents ( )
{
2017-09-25 20:03:24 +03:00
if ( m_sortFilterModel - > rowCount ( ) < = 0 ) return ;
2015-04-19 18:17:47 +03:00
2019-06-27 18:36:54 +03:00
QVector < BitTorrent : : TorrentHandle * > torrents ;
2017-09-25 20:03:24 +03:00
for ( int i = 0 ; i < m_sortFilterModel - > rowCount ( ) ; + + i )
torrents < < m_listModel - > torrentHandle ( mapToSource ( m_sortFilterModel - > index ( i , 0 ) ) ) ;
2015-06-07 15:03:30 +03:00
2016-08-05 21:15:13 +03:00
bool deleteLocalFiles = false ;
2017-02-06 18:51:25 +03:00
if ( Preferences : : instance ( ) - > confirmTorrentDeletion ( )
2018-06-14 12:54:23 +03:00
& & ! DeletionConfirmationDialog : : askForDeletionConfirmation ( this , deleteLocalFiles , torrents . size ( ) , torrents [ 0 ] - > name ( ) ) )
2015-03-17 00:57:03 +03:00
return ;
2015-10-26 11:43:41 +03:00
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( torrents ) )
2016-08-05 21:15:13 +03:00
BitTorrent : : Session : : instance ( ) - > deleteTorrent ( torrent - > hash ( ) , deleteLocalFiles ) ;
2014-12-08 04:40:58 +03:00
}
2018-12-08 02:01:09 +03:00
void TransferListWidget : : increaseQueuePosSelectedTorrents ( )
2014-12-08 04:40:58 +03:00
{
qDebug ( ) < < Q_FUNC_INFO ;
2017-09-25 20:03:24 +03:00
if ( m_mainWindow - > currentTabWidget ( ) = = this )
2018-12-08 02:01:09 +03:00
BitTorrent : : Session : : instance ( ) - > increaseTorrentsQueuePos ( extractHashes ( getSelectedTorrents ( ) ) ) ;
2011-03-07 22:26:44 +03:00
}
2018-12-08 02:01:09 +03:00
void TransferListWidget : : decreaseQueuePosSelectedTorrents ( )
2014-12-08 04:40:58 +03:00
{
qDebug ( ) < < Q_FUNC_INFO ;
2017-09-25 20:03:24 +03:00
if ( m_mainWindow - > currentTabWidget ( ) = = this )
2018-12-08 02:01:09 +03:00
BitTorrent : : Session : : instance ( ) - > decreaseTorrentsQueuePos ( extractHashes ( getSelectedTorrents ( ) ) ) ;
2009-11-08 00:04:56 +03:00
}
2018-12-08 02:01:09 +03:00
void TransferListWidget : : topQueuePosSelectedTorrents ( )
2014-12-08 04:40:58 +03:00
{
2017-09-25 20:03:24 +03:00
if ( m_mainWindow - > currentTabWidget ( ) = = this )
2018-12-08 02:01:09 +03:00
BitTorrent : : Session : : instance ( ) - > topTorrentsQueuePos ( extractHashes ( getSelectedTorrents ( ) ) ) ;
2011-08-10 22:44:37 +04:00
}
2009-11-18 14:04:19 +03:00
2018-12-08 02:01:09 +03:00
void TransferListWidget : : bottomQueuePosSelectedTorrents ( )
2014-12-08 04:40:58 +03:00
{
2017-09-25 20:03:24 +03:00
if ( m_mainWindow - > currentTabWidget ( ) = = this )
2018-12-08 02:01:09 +03:00
BitTorrent : : Session : : instance ( ) - > bottomTorrentsQueuePos ( extractHashes ( getSelectedTorrents ( ) ) ) ;
2009-11-19 15:45:11 +03:00
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : copySelectedMagnetURIs ( ) const
{
2018-06-14 14:46:50 +03:00
QStringList magnetUris ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2018-06-14 14:46:50 +03:00
magnetUris < < torrent - > toMagnetUri ( ) ;
2015-06-07 15:03:30 +03:00
2018-06-14 14:46:50 +03:00
qApp - > clipboard ( ) - > setText ( magnetUris . join ( ' \n ' ) ) ;
2014-12-08 04:40:58 +03:00
}
2015-02-06 21:56:24 +03:00
void TransferListWidget : : copySelectedNames ( ) const
2015-02-01 16:52:36 +03:00
{
2018-06-14 14:46:50 +03:00
QStringList torrentNames ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2018-06-14 14:46:50 +03:00
torrentNames < < torrent - > name ( ) ;
2015-06-07 15:03:30 +03:00
2018-06-14 14:46:50 +03:00
qApp - > clipboard ( ) - > setText ( torrentNames . join ( ' \n ' ) ) ;
2015-02-01 16:52:36 +03:00
}
2017-08-06 11:35:12 +03:00
void TransferListWidget : : copySelectedHashes ( ) const
{
QStringList torrentHashes ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2017-08-06 11:35:12 +03:00
torrentHashes < < torrent - > hash ( ) ;
qApp - > clipboard ( ) - > setText ( torrentHashes . join ( ' \n ' ) ) ;
}
2018-12-08 02:01:09 +03:00
void TransferListWidget : : hideQueuePosColumn ( bool hide )
2014-12-08 04:40:58 +03:00
{
2018-12-08 02:01:09 +03:00
setColumnHidden ( TransferListModel : : TR_QUEUE_POSITION , hide ) ;
if ( ! hide & & ( columnWidth ( TransferListModel : : TR_QUEUE_POSITION ) = = 0 ) )
resizeColumnToContents ( TransferListModel : : TR_QUEUE_POSITION ) ;
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : openSelectedTorrentsFolder ( ) const
{
QSet < QString > pathsList ;
2017-12-12 18:00:56 +03:00
# ifdef Q_OS_MAC
// On macOS you expect both the files and folders to be opened in their parent
// folders prehilighted for opening, so we use a custom method.
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) ) {
2017-12-12 18:00:56 +03:00
QString path = torrent - > contentPath ( true ) ;
pathsList . insert ( path ) ;
}
2017-12-12 20:20:48 +03:00
MacUtils : : openFiles ( pathsList ) ;
2017-12-12 18:00:56 +03:00
# else
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) ) {
2015-10-24 15:28:29 +03:00
QString path = torrent - > contentPath ( true ) ;
if ( ! pathsList . contains ( path ) ) {
if ( torrent - > filesCount ( ) = = 1 )
2019-03-02 08:22:13 +03:00
Utils : : Gui : : openFolderSelect ( path ) ;
2015-10-24 15:28:29 +03:00
else
2019-03-02 08:22:13 +03:00
Utils : : Gui : : openPath ( path ) ;
2015-06-28 21:58:39 +03:00
}
pathsList . insert ( path ) ;
2014-12-08 04:40:58 +03:00
}
2018-11-06 18:49:17 +03:00
# endif // Q_OS_MAC
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : previewSelectedTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) ) {
2019-06-05 08:46:29 +03:00
if ( torrentContainsPreviewableFiles ( torrent ) ) {
const auto * dialog = new PreviewSelectDialog ( this , torrent ) ;
connect ( dialog , & PreviewSelectDialog : : readyToPreviewFile , this , & TransferListWidget : : previewFile ) ;
}
else {
2018-10-24 20:20:33 +03:00
QMessageBox : : critical ( this , tr ( " Unable to preview " ) , tr ( " The selected torrent does not contain previewable files " ) ) ;
2019-06-05 08:46:29 +03:00
}
2014-12-08 04:40:58 +03:00
}
}
void TransferListWidget : : setDlLimitSelectedTorrents ( )
{
2019-06-27 18:36:54 +03:00
QVector < BitTorrent : : TorrentHandle * > torrentsList ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) ) {
2016-12-30 08:34:10 +03:00
if ( torrent - > isSeed ( ) )
continue ;
2018-11-06 18:49:17 +03:00
torrentsList + = torrent ;
2014-12-08 04:40:58 +03:00
}
2018-11-06 18:49:17 +03:00
if ( torrentsList . empty ( ) ) return ;
2015-06-07 15:03:30 +03:00
2018-11-06 18:49:17 +03:00
int oldLimit = torrentsList . first ( ) - > downloadLimit ( ) ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( torrentsList ) ) {
2016-12-30 08:34:10 +03:00
if ( torrent - > downloadLimit ( ) ! = oldLimit ) {
oldLimit = - 1 ;
break ;
}
}
2014-12-08 04:40:58 +03:00
bool ok = false ;
2016-12-30 08:34:10 +03:00
const long newLimit = SpeedLimitDialog : : askSpeedLimit (
2015-10-26 11:38:54 +03:00
this , & ok , tr ( " Torrent Download Speed Limiting " ) , oldLimit
2016-05-01 11:05:52 +03:00
, BitTorrent : : Session : : instance ( ) - > globalDownloadSpeedLimit ( ) ) ;
2016-12-30 08:34:10 +03:00
if ( ! ok ) return ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( torrentsList ) ) {
2017-08-13 13:56:03 +03:00
qDebug ( " Applying download speed limit of %ld Kb/s to torrent %s " , ( newLimit / 1024l ) , qUtf8Printable ( torrent - > hash ( ) ) ) ;
2016-12-30 08:34:10 +03:00
torrent - > setDownloadLimit ( newLimit ) ;
2014-12-08 04:40:58 +03:00
}
}
void TransferListWidget : : setUpLimitSelectedTorrents ( )
{
2019-06-27 18:36:54 +03:00
QVector < BitTorrent : : TorrentHandle * > torrentsList = getSelectedTorrents ( ) ;
2018-11-06 18:49:17 +03:00
if ( torrentsList . empty ( ) ) return ;
2015-06-07 15:03:30 +03:00
2018-11-06 18:49:17 +03:00
int oldLimit = torrentsList . first ( ) - > uploadLimit ( ) ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( torrentsList ) ) {
2016-12-30 08:34:10 +03:00
if ( torrent - > uploadLimit ( ) ! = oldLimit ) {
oldLimit = - 1 ;
break ;
}
}
2014-12-08 04:40:58 +03:00
bool ok = false ;
2016-12-30 08:34:10 +03:00
const long newLimit = SpeedLimitDialog : : askSpeedLimit (
2015-10-26 11:38:54 +03:00
this , & ok , tr ( " Torrent Upload Speed Limiting " ) , oldLimit
2016-05-01 11:05:52 +03:00
, BitTorrent : : Session : : instance ( ) - > globalUploadSpeedLimit ( ) ) ;
2016-12-30 08:34:10 +03:00
if ( ! ok ) return ;
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( torrentsList ) ) {
2017-08-13 13:56:03 +03:00
qDebug ( " Applying upload speed limit of %ld Kb/s to torrent %s " , ( newLimit / 1024l ) , qUtf8Printable ( torrent - > hash ( ) ) ) ;
2016-12-30 08:34:10 +03:00
torrent - > setUploadLimit ( newLimit ) ;
2014-12-08 04:40:58 +03:00
}
}
void TransferListWidget : : setMaxRatioSelectedTorrents ( )
{
2019-06-27 18:36:54 +03:00
const QVector < BitTorrent : : TorrentHandle * > torrents = getSelectedTorrents ( ) ;
2015-06-07 15:03:30 +03:00
if ( torrents . isEmpty ( ) ) return ;
2016-02-07 20:31:50 +03:00
qreal currentMaxRatio = BitTorrent : : Session : : instance ( ) - > globalMaxRatio ( ) ;
2015-06-07 15:03:30 +03:00
if ( torrents . count ( ) = = 1 )
2017-09-06 22:47:05 +03:00
currentMaxRatio = torrents [ 0 ] - > maxRatio ( ) ;
2015-04-19 18:17:47 +03:00
2016-02-07 20:31:50 +03:00
int currentMaxSeedingTime = BitTorrent : : Session : : instance ( ) - > globalMaxSeedingMinutes ( ) ;
if ( torrents . count ( ) = = 1 )
2017-09-06 22:47:05 +03:00
currentMaxSeedingTime = torrents [ 0 ] - > maxSeedingTime ( ) ;
bool useGlobalValue = true ;
if ( torrents . count ( ) = = 1 )
useGlobalValue = ( torrents [ 0 ] - > ratioLimit ( ) = = BitTorrent : : TorrentHandle : : USE_GLOBAL_RATIO )
& & ( torrents [ 0 ] - > seedingTimeLimit ( ) = = BitTorrent : : TorrentHandle : : USE_GLOBAL_SEEDING_TIME ) ;
2016-02-07 20:31:50 +03:00
2019-06-19 06:26:17 +03:00
auto dialog = new UpDownRatioDialog ( useGlobalValue , currentMaxRatio , BitTorrent : : TorrentHandle : : MAX_RATIO ,
2016-02-07 20:31:50 +03:00
currentMaxSeedingTime , BitTorrent : : TorrentHandle : : MAX_SEEDING_TIME , this ) ;
2019-06-19 06:26:17 +03:00
dialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2019-06-25 04:39:22 +03:00
connect ( dialog , & QDialog : : accepted , this , [ dialog , torrents ] ( )
2019-06-19 06:26:17 +03:00
{
for ( BitTorrent : : TorrentHandle * const torrent : torrents ) {
const qreal ratio = ( dialog - > useDefault ( )
? BitTorrent : : TorrentHandle : : USE_GLOBAL_RATIO : dialog - > ratio ( ) ) ;
torrent - > setRatioLimit ( ratio ) ;
const int seedingTime = ( dialog - > useDefault ( )
? BitTorrent : : TorrentHandle : : USE_GLOBAL_SEEDING_TIME : dialog - > seedingTime ( ) ) ;
torrent - > setSeedingTimeLimit ( seedingTime ) ;
}
} ) ;
dialog - > open ( ) ;
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : recheckSelectedTorrents ( )
{
2015-07-08 23:29:31 +03:00
if ( Preferences : : instance ( ) - > confirmTorrentRecheck ( ) ) {
QMessageBox : : StandardButton ret = QMessageBox : : question ( this , tr ( " Recheck confirmation " ) , tr ( " Are you sure you want to recheck the selected torrent(s)? " ) , QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) ;
if ( ret ! = QMessageBox : : Yes ) return ;
}
2015-04-19 18:17:47 +03:00
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2015-06-07 15:03:30 +03:00
torrent - > forceRecheck ( ) ;
2014-12-08 04:40:58 +03:00
}
2018-01-03 05:40:52 +03:00
void TransferListWidget : : reannounceSelectedTorrents ( )
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2018-01-03 05:40:52 +03:00
torrent - > forceReannounce ( ) ;
}
2014-12-08 04:40:58 +03:00
// hide/show columns menu
void TransferListWidget : : displayDLHoSMenu ( const QPoint & )
{
2019-06-19 06:26:17 +03:00
auto menu = new QMenu ( this ) ;
menu - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
menu - > setTitle ( tr ( " Column visibility " ) ) ;
2017-09-25 20:03:24 +03:00
for ( int i = 0 ; i < m_listModel - > columnCount ( ) ; + + i ) {
2018-12-08 02:01:09 +03:00
if ( ! BitTorrent : : Session : : instance ( ) - > isQueueingSystemEnabled ( ) & & ( i = = TransferListModel : : TR_QUEUE_POSITION ) )
2014-12-08 04:40:58 +03:00
continue ;
2019-06-19 06:26:17 +03:00
QAction * myAct = menu - > addAction ( m_listModel - > headerData ( i , Qt : : Horizontal , Qt : : DisplayRole ) . toString ( ) ) ;
2014-12-08 04:40:58 +03:00
myAct - > setCheckable ( true ) ;
myAct - > setChecked ( ! isColumnHidden ( i ) ) ;
2019-06-19 06:26:17 +03:00
myAct - > setData ( i ) ;
2014-12-08 04:40:58 +03:00
}
2019-06-19 06:26:17 +03:00
connect ( menu , & QMenu : : triggered , this , [ this ] ( const QAction * action )
{
int visibleCols = 0 ;
for ( int i = 0 ; i < TransferListModel : : NB_COLUMNS ; + + i ) {
if ( ! isColumnHidden ( i ) )
+ + visibleCols ;
if ( visibleCols > 1 )
break ;
}
const int col = action - > data ( ) . toInt ( ) ;
2014-12-08 04:40:58 +03:00
if ( ! isColumnHidden ( col ) & & visibleCols = = 1 )
return ;
2019-06-19 06:26:17 +03:00
2014-12-08 04:40:58 +03:00
setColumnHidden ( col , ! isColumnHidden ( col ) ) ;
2019-06-19 06:26:17 +03:00
2014-12-08 04:40:58 +03:00
if ( ! isColumnHidden ( col ) & & columnWidth ( col ) < = 5 )
2017-12-08 17:05:21 +03:00
resizeColumnToContents ( col ) ;
2019-06-19 06:26:17 +03:00
2014-12-15 15:05:49 +03:00
saveSettings ( ) ;
2019-06-19 06:26:17 +03:00
} ) ;
menu - > popup ( QCursor : : pos ( ) ) ;
2014-12-08 04:40:58 +03:00
}
2019-07-07 16:02:13 +03:00
void TransferListWidget : : setSelectedTorrentsSuperSeeding ( const bool enabled ) const
2014-12-08 04:40:58 +03:00
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) ) {
2015-06-07 15:03:30 +03:00
if ( torrent - > hasMetadata ( ) )
2019-07-07 16:02:13 +03:00
torrent - > setSuperSeeding ( enabled ) ;
2014-12-08 04:40:58 +03:00
}
}
2019-07-07 16:02:13 +03:00
void TransferListWidget : : setSelectedTorrentsSequentialDownload ( const bool enabled ) const
2014-12-08 04:40:58 +03:00
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2019-07-07 16:02:13 +03:00
torrent - > setSequentialDownload ( enabled ) ;
2014-12-08 04:40:58 +03:00
}
2019-07-07 16:02:13 +03:00
void TransferListWidget : : setSelectedFirstLastPiecePrio ( const bool enabled ) const
2014-12-08 04:40:58 +03:00
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2019-07-07 16:02:13 +03:00
torrent - > setFirstLastPiecePriority ( enabled ) ;
2014-12-08 04:40:58 +03:00
}
2019-07-07 16:02:13 +03:00
void TransferListWidget : : setSelectedAutoTMMEnabled ( const bool enabled ) const
2014-12-08 04:40:58 +03:00
{
2018-11-27 23:15:04 +03:00
for ( BitTorrent : : TorrentHandle * const torrent : asConst ( getSelectedTorrents ( ) ) )
2016-05-08 22:47:50 +03:00
torrent - > setAutoTMMEnabled ( enabled ) ;
2016-02-09 11:56:48 +03:00
}
void TransferListWidget : : askNewCategoryForSelection ( )
{
2017-09-24 14:54:42 +03:00
const QString newCategoryName = TorrentCategoryDialog : : createCategory ( this ) ;
if ( ! newCategoryName . isEmpty ( ) )
setSelectionCategory ( newCategoryName ) ;
2014-12-08 04:40:58 +03:00
}
2017-06-05 03:22:17 +03:00
void TransferListWidget : : askAddTagsForSelection ( )
{
const QStringList tags = askTagsForSelection ( tr ( " Add Tags " ) ) ;
2018-11-18 21:40:37 +03:00
for ( const QString & tag : tags )
2017-06-05 03:22:17 +03:00
addSelectionTag ( tag ) ;
}
2019-06-24 18:37:31 +03:00
void TransferListWidget : : editTorrentTrackers ( )
{
2019-06-27 18:36:54 +03:00
const QVector < BitTorrent : : TorrentHandle * > torrents = getSelectedTorrents ( ) ;
QVector < BitTorrent : : TrackerEntry > commonTrackers ;
2019-06-24 18:37:31 +03:00
if ( ! torrents . empty ( ) ) {
commonTrackers = torrents [ 0 ] - > trackers ( ) ;
for ( const BitTorrent : : TorrentHandle * torrent : torrents ) {
QSet < BitTorrent : : TrackerEntry > trackerSet ;
for ( const BitTorrent : : TrackerEntry & entry : asConst ( torrent - > trackers ( ) ) )
trackerSet . insert ( entry ) ;
commonTrackers . erase ( std : : remove_if ( commonTrackers . begin ( ) , commonTrackers . end ( )
, [ & trackerSet ] ( const BitTorrent : : TrackerEntry & entry ) { return ! trackerSet . contains ( entry ) ; } )
, commonTrackers . end ( ) ) ;
}
}
auto trackerDialog = new TrackerEntriesDialog ( this ) ;
trackerDialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
trackerDialog - > setTrackers ( commonTrackers ) ;
connect ( trackerDialog , & QDialog : : accepted , this , [ torrents , trackerDialog ] ( )
{
for ( BitTorrent : : TorrentHandle * torrent : torrents )
torrent - > replaceTrackers ( trackerDialog - > trackers ( ) ) ;
} ) ;
trackerDialog - > open ( ) ;
}
2017-06-05 03:22:17 +03:00
void TransferListWidget : : confirmRemoveAllTagsForSelection ( )
{
QMessageBox : : StandardButton response = QMessageBox : : question (
this , tr ( " Remove All Tags " ) , tr ( " Remove all tags from selected torrents? " ) ,
QMessageBox : : Yes | QMessageBox : : No ) ;
if ( response = = QMessageBox : : Yes )
clearSelectionTags ( ) ;
}
QStringList TransferListWidget : : askTagsForSelection ( const QString & dialogTitle )
{
QStringList tags ;
bool invalid = true ;
while ( invalid ) {
bool ok = false ;
invalid = false ;
const QString tagsInput = AutoExpandableDialog : : getText (
this , dialogTitle , tr ( " Comma-separated tags: " ) , QLineEdit : : Normal , " " , & ok ) . trimmed ( ) ;
if ( ! ok | | tagsInput . isEmpty ( ) )
2019-02-14 20:16:42 +03:00
return { } ;
2017-06-05 03:22:17 +03:00
tags = tagsInput . split ( ' , ' , QString : : SkipEmptyParts ) ;
for ( QString & tag : tags ) {
tag = tag . trimmed ( ) ;
if ( ! BitTorrent : : Session : : isValidTag ( tag ) ) {
QMessageBox : : warning ( this , tr ( " Invalid tag " )
, tr ( " Tag name: '%1' is invalid " ) . arg ( tag ) ) ;
invalid = true ;
}
}
}
return tags ;
}
void TransferListWidget : : applyToSelectedTorrents ( const std : : function < void ( BitTorrent : : TorrentHandle * const ) > & fn )
{
2018-11-27 23:15:04 +03:00
for ( const QModelIndex & index : asConst ( selectionModel ( ) - > selectedRows ( ) ) ) {
2017-09-25 20:03:24 +03:00
BitTorrent : : TorrentHandle * const torrent = m_listModel - > torrentHandle ( mapToSource ( index ) ) ;
2017-06-05 03:22:17 +03:00
Q_ASSERT ( torrent ) ;
fn ( torrent ) ;
}
}
2014-12-08 04:40:58 +03:00
void TransferListWidget : : renameSelectedTorrent ( )
{
const QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
2017-02-06 18:51:25 +03:00
if ( ( selectedIndexes . size ( ) ! = 1 ) | | ! selectedIndexes . first ( ) . isValid ( ) ) return ;
2015-06-07 15:03:30 +03:00
2018-06-14 12:54:23 +03:00
const QModelIndex mi = m_listModel - > index ( mapToSource ( selectedIndexes . first ( ) ) . row ( ) , TransferListModel : : TR_NAME ) ;
2017-09-25 20:03:24 +03:00
BitTorrent : : TorrentHandle * const torrent = m_listModel - > torrentHandle ( mi ) ;
2015-04-19 18:17:47 +03:00
if ( ! torrent ) return ;
2014-12-08 04:40:58 +03:00
// Ask for a new Name
bool ok ;
2015-04-19 18:17:47 +03:00
QString name = AutoExpandableDialog : : getText ( this , tr ( " Rename " ) , tr ( " New name: " ) , QLineEdit : : Normal , torrent - > name ( ) , & ok ) ;
2014-12-08 04:40:58 +03:00
if ( ok & & ! name . isEmpty ( ) ) {
2018-05-24 18:41:03 +03:00
name . replace ( QRegularExpression ( " \r ? \n | \r " ) , " " ) ;
2014-12-08 04:40:58 +03:00
// Rename the torrent
2017-09-25 20:03:24 +03:00
m_listModel - > setData ( mi , name , Qt : : DisplayRole ) ;
2014-12-08 04:40:58 +03:00
}
}
2019-02-12 03:45:30 +03:00
void TransferListWidget : : setSelectionCategory ( const QString & category )
2014-12-08 04:40:58 +03:00
{
2018-11-27 23:15:04 +03:00
for ( const QModelIndex & index : asConst ( selectionModel ( ) - > selectedRows ( ) ) )
2018-06-14 12:54:23 +03:00
m_listModel - > setData ( m_listModel - > index ( mapToSource ( index ) . row ( ) , TransferListModel : : TR_CATEGORY ) , category , Qt : : DisplayRole ) ;
2014-12-08 04:40:58 +03:00
}
2017-06-05 03:22:17 +03:00
void TransferListWidget : : addSelectionTag ( const QString & tag )
{
applyToSelectedTorrents ( [ & tag ] ( BitTorrent : : TorrentHandle * const torrent ) { torrent - > addTag ( tag ) ; } ) ;
}
void TransferListWidget : : removeSelectionTag ( const QString & tag )
{
applyToSelectedTorrents ( [ & tag ] ( BitTorrent : : TorrentHandle * const torrent ) { torrent - > removeTag ( tag ) ; } ) ;
}
void TransferListWidget : : clearSelectionTags ( )
{
applyToSelectedTorrents ( [ ] ( BitTorrent : : TorrentHandle * const torrent ) { torrent - > removeAllTags ( ) ; } ) ;
}
2019-06-23 18:13:58 +03:00
void TransferListWidget : : displayListMenu ( const QPoint & )
2014-12-08 04:40:58 +03:00
{
2018-11-18 21:40:37 +03:00
const QModelIndexList selectedIndexes = selectionModel ( ) - > selectedRows ( ) ;
2019-02-13 18:51:07 +03:00
if ( selectedIndexes . isEmpty ( ) ) return ;
2017-02-06 18:51:25 +03:00
2019-07-07 16:02:13 +03:00
auto * listMenu = new QMenu ( this ) ;
2019-06-23 18:45:21 +03:00
listMenu - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2014-12-08 04:40:58 +03:00
// Create actions
2019-07-16 07:01:33 +03:00
auto * actionStart = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " media-playback-start " ) , tr ( " Resume " , " Resume/start the torrent " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionStart , & QAction : : triggered , this , & TransferListWidget : : startSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionPause = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " media-playback-pause " ) , tr ( " Pause " , " Pause the torrent " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionPause , & QAction : : triggered , this , & TransferListWidget : : pauseSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionForceStart = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " media-seek-forward " ) , tr ( " Force Resume " , " Force Resume/start the torrent " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionForceStart , & QAction : : triggered , this , & TransferListWidget : : forceStartSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionDelete = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-delete " ) , tr ( " Delete " , " Delete the torrent " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionDelete , & QAction : : triggered , this , & TransferListWidget : : softDeleteSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionPreviewFile = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " view-preview " ) , tr ( " Preview file... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionPreviewFile , & QAction : : triggered , this , & TransferListWidget : : previewSelectedTorrents ) ;
2019-07-07 16:02:13 +03:00
auto * actionSetMaxRatio = new QAction ( QIcon ( QLatin1String ( " :/icons/skin/ratio.svg " ) ) , tr ( " Limit share ratio... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionSetMaxRatio , & QAction : : triggered , this , & TransferListWidget : : setMaxRatioSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionSetUploadLimit = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " kt-set-max-upload-speed " ) , tr ( " Limit upload rate... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionSetUploadLimit , & QAction : : triggered , this , & TransferListWidget : : setUpLimitSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionSetDownloadLimit = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " kt-set-max-download-speed " ) , tr ( " Limit download rate... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionSetDownloadLimit , & QAction : : triggered , this , & TransferListWidget : : setDlLimitSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionOpenDestinationFolder = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " inode-directory " ) , tr ( " Open destination folder " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionOpenDestinationFolder , & QAction : : triggered , this , & TransferListWidget : : openSelectedTorrentsFolder ) ;
2019-07-16 07:01:33 +03:00
auto * actionIncreaseQueuePos = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " go-up " ) , tr ( " Move up " , " i.e. move up in the queue " ) , listMenu ) ;
2018-12-08 02:01:09 +03:00
connect ( actionIncreaseQueuePos , & QAction : : triggered , this , & TransferListWidget : : increaseQueuePosSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionDecreaseQueuePos = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " go-down " ) , tr ( " Move down " , " i.e. Move down in the queue " ) , listMenu ) ;
2018-12-08 02:01:09 +03:00
connect ( actionDecreaseQueuePos , & QAction : : triggered , this , & TransferListWidget : : decreaseQueuePosSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionTopQueuePos = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " go-top " ) , tr ( " Move to top " , " i.e. Move to top of the queue " ) , listMenu ) ;
2018-12-08 02:01:09 +03:00
connect ( actionTopQueuePos , & QAction : : triggered , this , & TransferListWidget : : topQueuePosSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionBottomQueuePos = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " go-bottom " ) , tr ( " Move to bottom " , " i.e. Move to bottom of the queue " ) , listMenu ) ;
2018-12-08 02:01:09 +03:00
connect ( actionBottomQueuePos , & QAction : : triggered , this , & TransferListWidget : : bottomQueuePosSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionSetTorrentPath = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " inode-directory " ) , tr ( " Set location... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionSetTorrentPath , & QAction : : triggered , this , & TransferListWidget : : setSelectedTorrentsLocation ) ;
2019-07-16 07:01:33 +03:00
auto * actionForceRecheck = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " document-edit-verify " ) , tr ( " Force recheck " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionForceRecheck , & QAction : : triggered , this , & TransferListWidget : : recheckSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionForceReannounce = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " document-edit-verify " ) , tr ( " Force reannounce " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionForceReannounce , & QAction : : triggered , this , & TransferListWidget : : reannounceSelectedTorrents ) ;
2019-07-16 07:01:33 +03:00
auto * actionCopyMagnetLink = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " kt-magnet " ) , tr ( " Magnet link " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionCopyMagnetLink , & QAction : : triggered , this , & TransferListWidget : : copySelectedMagnetURIs ) ;
2019-07-16 07:01:33 +03:00
auto * actionCopyName = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-copy " ) , tr ( " Name " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionCopyName , & QAction : : triggered , this , & TransferListWidget : : copySelectedNames ) ;
2019-07-16 07:01:33 +03:00
auto * actionCopyHash = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-copy " ) , tr ( " Hash " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionCopyHash , & QAction : : triggered , this , & TransferListWidget : : copySelectedHashes ) ;
2019-07-07 16:02:13 +03:00
auto * actionSuperSeedingMode = new TriStateAction ( tr ( " Super seeding mode " ) , listMenu ) ;
connect ( actionSuperSeedingMode , & QAction : : triggered , this , & TransferListWidget : : setSelectedTorrentsSuperSeeding ) ;
2019-07-16 07:01:33 +03:00
auto * actionRename = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-rename " ) , tr ( " Rename... " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
connect ( actionRename , & QAction : : triggered , this , & TransferListWidget : : renameSelectedTorrent ) ;
2019-07-07 16:02:13 +03:00
auto * actionSequentialDownload = new TriStateAction ( tr ( " Download in sequential order " ) , listMenu ) ;
connect ( actionSequentialDownload , & QAction : : triggered , this , & TransferListWidget : : setSelectedTorrentsSequentialDownload ) ;
auto * actionFirstLastPiecePrio = new TriStateAction ( tr ( " Download first and last pieces first " ) , listMenu ) ;
connect ( actionFirstLastPiecePrio , & QAction : : triggered , this , & TransferListWidget : : setSelectedFirstLastPiecePrio ) ;
auto * actionAutoTMM = new TriStateAction ( tr ( " Automatic Torrent Management " ) , listMenu ) ;
2019-06-03 10:10:19 +03:00
actionAutoTMM - > setToolTip ( tr ( " Automatic mode means that various torrent properties(eg save path) will be decided by the associated category " ) ) ;
connect ( actionAutoTMM , & QAction : : triggered , this , & TransferListWidget : : setSelectedAutoTMMEnabled ) ;
2019-07-16 07:01:33 +03:00
QAction * actionEditTracker = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-rename " ) , tr ( " Edit trackers... " ) , listMenu ) ;
2019-06-24 18:37:31 +03:00
connect ( actionEditTracker , & QAction : : triggered , this , & TransferListWidget : : editTorrentTrackers ) ;
2014-12-08 04:40:58 +03:00
// End of actions
2015-07-19 22:59:07 +03:00
2014-12-08 04:40:58 +03:00
// Enable/disable pause/start action given the DL state
2018-06-06 16:48:17 +03:00
bool needsPause = false , needsStart = false , needsForce = false , needsPreview = false ;
bool allSameSuperSeeding = true ;
bool superSeedingMode = false ;
bool allSameSequentialDownloadMode = true , allSamePrioFirstlast = true ;
bool sequentialDownloadMode = false , prioritizeFirstLast = false ;
bool oneHasMetadata = false , oneNotSeed = false ;
2016-02-09 11:56:48 +03:00
bool allSameCategory = true ;
2016-05-08 22:47:50 +03:00
bool allSameAutoTMM = true ;
bool firstAutoTMM = false ;
2016-02-09 11:56:48 +03:00
QString firstCategory ;
2014-12-08 04:40:58 +03:00
bool first = true ;
2017-07-10 02:15:08 +03:00
QSet < QString > tagsInAny ;
QSet < QString > tagsInAll ;
2015-04-19 18:17:47 +03:00
2018-11-18 21:40:37 +03:00
for ( const QModelIndex & index : selectedIndexes ) {
2014-12-08 04:40:58 +03:00
// Get the file name
// Get handle and pause the torrent
2019-06-03 10:10:19 +03:00
const BitTorrent : : TorrentHandle * torrent = m_listModel - > torrentHandle ( mapToSource ( index ) ) ;
2015-04-19 18:17:47 +03:00
if ( ! torrent ) continue ;
2016-02-09 11:56:48 +03:00
if ( firstCategory . isEmpty ( ) & & first )
firstCategory = torrent - > category ( ) ;
if ( firstCategory ! = torrent - > category ( ) )
allSameCategory = false ;
2015-09-16 02:01:51 +03:00
2017-07-10 02:15:08 +03:00
tagsInAny . unite ( torrent - > tags ( ) ) ;
2017-06-05 03:22:17 +03:00
2017-07-10 02:15:08 +03:00
if ( first ) {
2016-05-08 22:47:50 +03:00
firstAutoTMM = torrent - > isAutoTMMEnabled ( ) ;
2017-07-10 02:15:08 +03:00
tagsInAll = torrent - > tags ( ) ;
}
else {
tagsInAll . intersect ( torrent - > tags ( ) ) ;
}
2019-07-07 16:02:13 +03:00
2016-05-08 22:47:50 +03:00
if ( firstAutoTMM ! = torrent - > isAutoTMMEnabled ( ) )
allSameAutoTMM = false ;
2015-09-16 02:01:51 +03:00
2015-04-19 18:17:47 +03:00
if ( torrent - > hasMetadata ( ) )
2018-06-06 16:48:17 +03:00
oneHasMetadata = true ;
2015-04-19 18:17:47 +03:00
if ( ! torrent - > isSeed ( ) ) {
2018-06-06 16:48:17 +03:00
oneNotSeed = true ;
2018-08-14 11:42:28 +03:00
if ( first ) {
sequentialDownloadMode = torrent - > isSequentialDownload ( ) ;
prioritizeFirstLast = torrent - > hasFirstLastPiecePriority ( ) ;
}
else {
if ( sequentialDownloadMode ! = torrent - > isSequentialDownload ( ) )
allSameSequentialDownloadMode = false ;
if ( prioritizeFirstLast ! = torrent - > hasFirstLastPiecePriority ( ) )
allSamePrioFirstlast = false ;
2014-12-08 04:40:58 +03:00
}
}
else {
2018-06-06 16:48:17 +03:00
if ( ! oneNotSeed & & allSameSuperSeeding & & torrent - > hasMetadata ( ) ) {
2018-08-14 11:42:28 +03:00
if ( first )
2018-06-06 16:48:17 +03:00
superSeedingMode = torrent - > superSeeding ( ) ;
else if ( superSeedingMode ! = torrent - > superSeeding ( ) )
allSameSuperSeeding = false ;
2014-12-08 04:40:58 +03:00
}
}
2015-07-19 22:59:07 +03:00
if ( ! torrent - > isForced ( ) )
2018-06-06 16:48:17 +03:00
needsForce = true ;
2015-07-19 22:59:07 +03:00
else
2018-06-06 16:48:17 +03:00
needsStart = true ;
2015-07-19 22:59:07 +03:00
if ( torrent - > isPaused ( ) )
2018-06-06 16:48:17 +03:00
needsStart = true ;
2015-07-19 22:59:07 +03:00
else
2018-06-06 16:48:17 +03:00
needsPause = true ;
2015-07-19 22:59:07 +03:00
if ( torrent - > hasMetadata ( ) )
2018-06-06 16:48:17 +03:00
needsPreview = true ;
2015-07-19 22:59:07 +03:00
2014-12-08 04:40:58 +03:00
first = false ;
2015-07-19 22:59:07 +03:00
2018-06-06 16:48:17 +03:00
if ( oneHasMetadata & & oneNotSeed & & ! allSameSequentialDownloadMode
& & ! allSamePrioFirstlast & & ! allSameSuperSeeding & & ! allSameCategory
& & needsStart & & needsForce & & needsPause & & needsPreview & & ! allSameAutoTMM ) {
2015-07-19 22:59:07 +03:00
break ;
}
2014-12-08 04:40:58 +03:00
}
2019-06-03 10:10:19 +03:00
2018-06-06 16:48:17 +03:00
if ( needsStart )
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionStart ) ;
2018-06-06 16:48:17 +03:00
if ( needsPause )
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionPause ) ;
2018-06-06 16:48:17 +03:00
if ( needsForce )
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionForceStart ) ;
listMenu - > addSeparator ( ) ;
listMenu - > addAction ( actionDelete ) ;
listMenu - > addSeparator ( ) ;
listMenu - > addAction ( actionSetTorrentPath ) ;
2014-12-08 04:40:58 +03:00
if ( selectedIndexes . size ( ) = = 1 )
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionRename ) ;
2019-06-24 18:37:31 +03:00
listMenu - > addAction ( actionEditTracker ) ;
2019-06-03 10:10:19 +03:00
2016-02-09 11:56:48 +03:00
// Category Menu
2017-09-24 14:54:42 +03:00
QStringList categories = BitTorrent : : Session : : instance ( ) - > categories ( ) . keys ( ) ;
2017-11-30 12:10:30 +03:00
std : : sort ( categories . begin ( ) , categories . end ( ) , Utils : : String : : naturalLessThan < Qt : : CaseInsensitive > ) ;
2019-06-03 10:10:19 +03:00
2019-07-16 07:01:33 +03:00
QMenu * categoryMenu = listMenu - > addMenu ( UIThemeManager : : instance ( ) - > getIcon ( " view-categories " ) , tr ( " Category " ) ) ;
2019-06-03 10:10:19 +03:00
2019-07-16 07:01:33 +03:00
const QAction * newCategoryAction = categoryMenu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( " list-add " ) , tr ( " New... " , " New category... " ) ) ;
2019-06-03 10:10:19 +03:00
connect ( newCategoryAction , & QAction : : triggered , this , & TransferListWidget : : askNewCategoryForSelection ) ;
2019-07-16 07:01:33 +03:00
const QAction * resetCategoryAction = categoryMenu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-clear " ) , tr ( " Reset " , " Reset category " ) ) ;
2019-06-03 10:10:19 +03:00
connect ( resetCategoryAction , & QAction : : triggered , this , [ this ] ( ) { setSelectionCategory ( " " ) ; } ) ;
2016-02-09 11:56:48 +03:00
categoryMenu - > addSeparator ( ) ;
2019-06-03 10:10:19 +03:00
for ( const QString & category : asConst ( categories ) ) {
const QString escapedCategory = QString ( category ) . replace ( ' & ' , " && " ) ; // avoid '&' becomes accelerator key
2019-07-16 07:01:33 +03:00
QAction * cat = new QAction ( UIThemeManager : : instance ( ) - > getIcon ( " inode-directory " ) , escapedCategory , categoryMenu ) ;
2016-02-09 11:56:48 +03:00
if ( allSameCategory & & ( category = = firstCategory ) ) {
cat - > setCheckable ( true ) ;
cat - > setChecked ( true ) ;
2015-09-16 02:01:51 +03:00
}
2019-06-03 10:10:19 +03:00
connect ( cat , & QAction : : triggered , this , [ this , category ] ( ) { setSelectionCategory ( category ) ; } ) ;
2019-07-07 16:02:13 +03:00
categoryMenu - > addAction ( cat ) ;
2015-07-19 08:02:41 +03:00
}
2016-02-09 11:56:48 +03:00
2017-06-05 03:22:17 +03:00
// Tag Menu
QStringList tags ( BitTorrent : : Session : : instance ( ) - > tags ( ) . toList ( ) ) ;
2017-11-30 12:10:30 +03:00
std : : sort ( tags . begin ( ) , tags . end ( ) , Utils : : String : : naturalLessThan < Qt : : CaseInsensitive > ) ;
2019-06-03 10:10:19 +03:00
2019-07-16 07:01:33 +03:00
QMenu * tagsMenu = listMenu - > addMenu ( UIThemeManager : : instance ( ) - > getIcon ( " view-categories " ) , tr ( " Tags " ) ) ;
2019-06-03 10:10:19 +03:00
2019-07-16 07:01:33 +03:00
const QAction * addTagAction = tagsMenu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( " list-add " ) , tr ( " Add... " , " Add / assign multiple tags... " ) ) ;
2019-06-03 10:10:19 +03:00
connect ( addTagAction , & QAction : : triggered , this , & TransferListWidget : : askAddTagsForSelection ) ;
2019-07-16 07:01:33 +03:00
const QAction * removeTagsAction = tagsMenu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-clear " ) , tr ( " Remove All " , " Remove all tags " ) ) ;
2019-06-03 10:10:19 +03:00
connect ( removeTagsAction , & QAction : : triggered , this , [ this ] ( )
{
if ( Preferences : : instance ( ) - > confirmRemoveAllTags ( ) )
confirmRemoveAllTagsForSelection ( ) ;
else
clearSelectionTags ( ) ;
} ) ;
2017-06-05 03:22:17 +03:00
tagsMenu - > addSeparator ( ) ;
2019-06-03 10:10:19 +03:00
2018-11-27 23:15:04 +03:00
for ( const QString & tag : asConst ( tags ) ) {
2019-07-07 16:02:13 +03:00
auto * action = new TriStateAction ( tag , tagsMenu ) ;
action - > setCloseOnTriggered ( false ) ;
2017-07-10 02:15:08 +03:00
const Qt : : CheckState initialState = tagsInAll . contains ( tag ) ? Qt : : Checked
: tagsInAny . contains ( tag ) ? Qt : : PartiallyChecked
: Qt : : Unchecked ;
2019-07-07 16:02:13 +03:00
action - > setCheckState ( initialState ) ;
2017-07-10 02:15:08 +03:00
2019-07-07 16:02:13 +03:00
connect ( action , & QAction : : triggered , this , [ this , tag ] ( const bool checked )
2017-07-10 02:15:08 +03:00
{
2019-07-07 16:02:13 +03:00
if ( checked )
2017-07-10 02:15:08 +03:00
addSelectionTag ( tag ) ;
else
removeSelectionTag ( tag ) ;
2019-07-07 16:02:13 +03:00
} ) ;
2017-07-10 02:15:08 +03:00
2019-07-07 16:02:13 +03:00
tagsMenu - > addAction ( action ) ;
2017-06-05 03:22:17 +03:00
}
2019-07-07 16:02:13 +03:00
actionAutoTMM - > setCheckState ( allSameAutoTMM
? ( firstAutoTMM ? Qt : : Checked : Qt : : Unchecked )
: Qt : : PartiallyChecked ) ;
listMenu - > addAction ( actionAutoTMM ) ;
2016-02-09 11:56:48 +03:00
2019-06-03 10:10:19 +03:00
listMenu - > addSeparator ( ) ;
2018-06-06 16:48:17 +03:00
if ( oneNotSeed )
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionSetDownloadLimit ) ;
listMenu - > addAction ( actionSetUploadLimit ) ;
listMenu - > addAction ( actionSetMaxRatio ) ;
2019-07-07 16:02:13 +03:00
if ( ! oneNotSeed & & oneHasMetadata ) {
actionSuperSeedingMode - > setCheckState ( allSameSuperSeeding
? ( superSeedingMode ? Qt : : Checked : Qt : : Unchecked )
: Qt : : PartiallyChecked ) ;
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionSuperSeedingMode ) ;
2014-12-08 04:40:58 +03:00
}
2019-06-03 10:10:19 +03:00
listMenu - > addSeparator ( ) ;
2018-06-06 16:48:17 +03:00
bool addedPreviewAction = false ;
if ( needsPreview ) {
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionPreviewFile ) ;
2018-06-06 16:48:17 +03:00
addedPreviewAction = true ;
2014-12-08 04:40:58 +03:00
}
2018-08-14 11:42:28 +03:00
if ( oneNotSeed ) {
2019-07-07 16:02:13 +03:00
actionSequentialDownload - > setCheckState ( allSameSequentialDownloadMode
? ( sequentialDownloadMode ? Qt : : Checked : Qt : : Unchecked )
: Qt : : PartiallyChecked ) ;
listMenu - > addAction ( actionSequentialDownload ) ;
actionFirstLastPiecePrio - > setCheckState ( allSamePrioFirstlast
? ( prioritizeFirstLast ? Qt : : Checked : Qt : : Unchecked )
: Qt : : PartiallyChecked ) ;
listMenu - > addAction ( actionFirstLastPiecePrio ) ;
addedPreviewAction = true ;
2014-12-08 04:40:58 +03:00
}
2016-02-09 11:56:48 +03:00
2018-06-06 16:48:17 +03:00
if ( addedPreviewAction )
2019-06-03 10:10:19 +03:00
listMenu - > addSeparator ( ) ;
2018-06-06 16:48:17 +03:00
if ( oneHasMetadata ) {
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionForceRecheck ) ;
listMenu - > addAction ( actionForceReannounce ) ;
listMenu - > addSeparator ( ) ;
2014-12-08 04:40:58 +03:00
}
2019-06-03 10:10:19 +03:00
listMenu - > addAction ( actionOpenDestinationFolder ) ;
2018-06-06 16:48:17 +03:00
if ( BitTorrent : : Session : : instance ( ) - > isQueueingSystemEnabled ( ) & & oneNotSeed ) {
2019-06-03 10:10:19 +03:00
listMenu - > addSeparator ( ) ;
2018-12-08 02:01:09 +03:00
QMenu * queueMenu = listMenu - > addMenu ( tr ( " Queue " ) ) ;
queueMenu - > addAction ( actionTopQueuePos ) ;
queueMenu - > addAction ( actionIncreaseQueuePos ) ;
queueMenu - > addAction ( actionDecreaseQueuePos ) ;
queueMenu - > addAction ( actionBottomQueuePos ) ;
2014-12-08 04:40:58 +03:00
}
2019-06-23 18:13:58 +03:00
QMenu * copySubMenu = listMenu - > addMenu (
2019-07-16 07:01:33 +03:00
UIThemeManager : : instance ( ) - > getIcon ( " edit-copy " ) , tr ( " Copy " ) ) ;
2019-06-23 18:13:58 +03:00
copySubMenu - > addAction ( actionCopyName ) ;
copySubMenu - > addAction ( actionCopyHash ) ;
copySubMenu - > addAction ( actionCopyMagnetLink ) ;
2019-06-03 10:10:19 +03:00
listMenu - > popup ( QCursor : : pos ( ) ) ;
2014-12-08 04:40:58 +03:00
}
2018-11-06 18:49:17 +03:00
void TransferListWidget : : currentChanged ( const QModelIndex & current , const QModelIndex & )
2014-12-08 04:40:58 +03:00
{
qDebug ( " CURRENT CHANGED " ) ;
2018-04-15 13:06:31 +03:00
BitTorrent : : TorrentHandle * torrent = nullptr ;
2014-12-08 04:40:58 +03:00
if ( current . isValid ( ) ) {
2017-09-25 20:03:24 +03:00
torrent = m_listModel - > torrentHandle ( mapToSource ( current ) ) ;
2014-12-08 04:40:58 +03:00
// Scroll Fix
scrollTo ( current ) ;
}
2015-04-19 18:17:47 +03:00
emit currentTorrentChanged ( torrent ) ;
2014-12-08 04:40:58 +03:00
}
2019-02-12 03:45:30 +03:00
void TransferListWidget : : applyCategoryFilter ( const QString & category )
2014-12-08 04:40:58 +03:00
{
2016-02-09 11:56:48 +03:00
if ( category . isNull ( ) )
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > disableCategoryFilter ( ) ;
2015-07-14 16:03:51 +03:00
else
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setCategoryFilter ( category ) ;
2014-12-08 04:40:58 +03:00
}
2017-06-05 03:22:17 +03:00
void TransferListWidget : : applyTagFilter ( const QString & tag )
{
if ( tag . isNull ( ) )
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > disableTagFilter ( ) ;
2017-06-05 03:22:17 +03:00
else
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setTagFilter ( tag ) ;
2017-06-05 03:22:17 +03:00
}
2015-03-22 02:18:21 +03:00
void TransferListWidget : : applyTrackerFilterAll ( )
{
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > disableTrackerFilter ( ) ;
2015-03-22 02:18:21 +03:00
}
void TransferListWidget : : applyTrackerFilter ( const QStringList & hashes )
{
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setTrackerFilter ( hashes ) ;
2015-03-22 02:18:21 +03:00
}
2018-06-06 16:48:17 +03:00
void TransferListWidget : : applyNameFilter ( const QString & name )
2014-12-08 04:40:58 +03:00
{
2018-08-12 17:46:16 +03:00
const QRegExp : : PatternSyntax patternSyntax = Preferences : : instance ( ) - > getRegexAsFilteringPatternForTransferList ( )
2018-07-29 15:46:19 +03:00
? QRegExp : : RegExp : QRegExp : : WildcardUnix ;
m_sortFilterModel - > setFilterRegExp ( QRegExp ( name , Qt : : CaseInsensitive , patternSyntax ) ) ;
2014-12-08 04:40:58 +03:00
}
void TransferListWidget : : applyStatusFilter ( int f )
{
2017-09-25 20:03:24 +03:00
m_sortFilterModel - > setStatusFilter ( static_cast < TorrentFilter : : Type > ( f ) ) ;
2014-12-08 04:40:58 +03:00
// Select first item if nothing is selected
2018-06-06 16:48:17 +03:00
if ( selectionModel ( ) - > selectedRows ( 0 ) . empty ( ) & & ( m_sortFilterModel - > rowCount ( ) > 0 ) ) {
2018-06-14 12:54:23 +03:00
qDebug ( " Nothing is selected, selecting first row: %s " , qUtf8Printable ( m_sortFilterModel - > index ( 0 , TransferListModel : : TR_NAME ) . data ( ) . toString ( ) ) ) ;
selectionModel ( ) - > setCurrentIndex ( m_sortFilterModel - > index ( 0 , TransferListModel : : TR_NAME ) , QItemSelectionModel : : SelectCurrent | QItemSelectionModel : : Rows ) ;
2014-12-08 04:40:58 +03:00
}
2009-11-08 16:19:00 +03:00
}
2009-11-09 11:56:21 +03:00
2010-12-04 12:51:43 +03:00
void TransferListWidget : : saveSettings ( )
{
2014-12-08 04:40:58 +03:00
Preferences : : instance ( ) - > setTransHeaderState ( header ( ) - > saveState ( ) ) ;
2010-12-04 12:51:43 +03:00
}
2011-03-13 20:49:56 +03:00
bool TransferListWidget : : loadSettings ( )
2010-12-04 12:51:43 +03:00
{
2017-12-08 17:05:21 +03:00
return header ( ) - > restoreState ( Preferences : : instance ( ) - > getTransHeaderState ( ) ) ;
2010-12-04 12:51:43 +03:00
}
2016-11-27 10:14:41 +03:00
void TransferListWidget : : wheelEvent ( QWheelEvent * event )
{
2017-02-06 18:51:25 +03:00
if ( event - > modifiers ( ) & Qt : : ShiftModifier ) {
2016-11-27 10:14:41 +03:00
// Shift + scroll = horizontal scroll
2019-06-11 15:32:34 +03:00
event - > accept ( ) ;
2016-11-27 10:14:41 +03:00
QWheelEvent scrollHEvent ( event - > pos ( ) , event - > globalPos ( ) , event - > delta ( ) , event - > buttons ( ) , event - > modifiers ( ) , Qt : : Horizontal ) ;
QTreeView : : wheelEvent ( & scrollHEvent ) ;
return ;
}
QTreeView : : wheelEvent ( event ) ; // event delegated to base class
}