2012-05-15 20:57:31 +04:00
/*
2015-04-19 18:17:47 +03:00
* Bittorrent Client using Qt and libtorrent .
2018-04-14 22:53:45 +03:00
* Copyright ( C ) 2012 Christophe Dumez < chris @ qbittorrent . org >
2012-05-15 20:57:31 +04: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-12-03 10:32:58 +03:00
# include "addnewtorrentdialog.h"
2021-12-27 15:31:57 +03:00
# include <algorithm>
2022-01-18 10:45:31 +03:00
# include <QAction>
2015-06-02 12:09:15 +03:00
# include <QDebug>
2019-03-02 08:22:13 +03:00
# include <QDir>
2020-02-19 13:19:51 +03:00
# include <QFileDialog>
2017-12-03 10:32:58 +03:00
# include <QMenu>
2016-04-23 02:55:59 +03:00
# include <QPushButton>
2018-10-21 14:51:58 +03:00
# include <QShortcut>
2017-12-03 10:32:58 +03:00
# include <QString>
# include <QUrl>
2018-05-18 19:22:42 +03:00
# include <QVector>
2015-06-02 12:09:15 +03:00
2019-03-06 08:58:07 +03:00
# include "base/bittorrent/downloadpriority.h"
2020-09-07 18:05:55 +03:00
# include "base/bittorrent/infohash.h"
2017-12-03 10:32:58 +03:00
# include "base/bittorrent/magneturi.h"
# include "base/bittorrent/session.h"
2021-01-06 15:12:40 +03:00
# include "base/bittorrent/torrent.h"
2021-12-16 12:50:16 +03:00
# include "base/bittorrent/torrentcontentlayout.h"
2018-05-18 19:22:42 +03:00
# include "base/global.h"
2017-12-03 10:32:58 +03:00
# include "base/net/downloadmanager.h"
2016-02-09 11:56:48 +03:00
# include "base/settingsstorage.h"
2017-12-03 10:32:58 +03:00
# include "base/torrentfileguard.h"
2021-04-05 08:02:28 +03:00
# include "base/utils/compare.h"
2015-09-25 11:10:05 +03:00
# include "base/utils/fs.h"
# include "base/utils/misc.h"
2018-04-14 22:53:45 +03:00
# include "autoexpandabledialog.h"
2020-04-30 10:53:43 +03:00
# include "properties/proplistdelegate.h"
2018-06-14 12:54:23 +03:00
# include "raisedmessagebox.h"
2015-06-02 12:09:15 +03:00
# include "torrentcontentfiltermodel.h"
2017-12-03 10:32:58 +03:00
# include "torrentcontentmodel.h"
2016-02-09 11:56:48 +03:00
# include "ui_addnewtorrentdialog.h"
2019-07-16 07:01:33 +03:00
# include "uithememanager.h"
2017-12-03 10:32:58 +03:00
# include "utils.h"
2012-05-15 20:57:31 +04:00
2016-02-09 11:56:48 +03:00
namespace
{
2018-10-21 14:51:58 +03:00
# define SETTINGS_KEY(name) "AddNewTorrentDialog / " name
const QString KEY_ENABLED = QStringLiteral ( SETTINGS_KEY ( " Enabled " ) ) ;
const QString KEY_TOPLEVEL = QStringLiteral ( SETTINGS_KEY ( " TopLevel " ) ) ;
const QString KEY_SAVEPATHHISTORY = QStringLiteral ( SETTINGS_KEY ( " SavePathHistory " ) ) ;
2021-05-20 10:36:44 +03:00
const QString KEY_DOWNLOADPATHHISTORY = QStringLiteral ( SETTINGS_KEY ( " DownloadPathHistory " ) ) ;
2018-10-21 14:51:58 +03:00
const QString KEY_SAVEPATHHISTORYLENGTH = QStringLiteral ( SETTINGS_KEY ( " SavePathHistoryLength " ) ) ;
2017-10-16 16:10:25 +03:00
2017-04-05 10:21:12 +03:00
// just a shortcut
inline SettingsStorage * settings ( )
{
return SettingsStorage : : instance ( ) ;
}
2021-12-09 13:05:49 +03:00
class FileStorageAdaptor final : public BitTorrent : : AbstractFileStorage
{
public :
2022-02-08 06:03:48 +03:00
FileStorageAdaptor ( const BitTorrent : : TorrentInfo & torrentInfo , PathList & filePaths )
2021-12-09 13:05:49 +03:00
: m_torrentInfo { torrentInfo }
, m_filePaths { filePaths }
{
Q_ASSERT ( filePaths . isEmpty ( ) | | ( filePaths . size ( ) = = torrentInfo . filesCount ( ) ) ) ;
}
int filesCount ( ) const override
{
return m_torrentInfo . filesCount ( ) ;
}
qlonglong fileSize ( const int index ) const override
{
Q_ASSERT ( ( index > = 0 ) & & ( index < filesCount ( ) ) ) ;
return m_torrentInfo . fileSize ( index ) ;
}
2022-02-08 06:03:48 +03:00
Path filePath ( const int index ) const override
2021-12-09 13:05:49 +03:00
{
Q_ASSERT ( ( index > = 0 ) & & ( index < filesCount ( ) ) ) ;
return ( m_filePaths . isEmpty ( ) ? m_torrentInfo . filePath ( index ) : m_filePaths . at ( index ) ) ;
}
2022-02-08 06:03:48 +03:00
void renameFile ( const int index , const Path & newFilePath ) override
2021-12-09 13:05:49 +03:00
{
Q_ASSERT ( ( index > = 0 ) & & ( index < filesCount ( ) ) ) ;
2022-02-08 06:03:48 +03:00
const Path currentFilePath = filePath ( index ) ;
2021-12-09 13:05:49 +03:00
if ( currentFilePath = = newFilePath )
return ;
if ( m_filePaths . isEmpty ( ) )
m_filePaths = m_torrentInfo . filePaths ( ) ;
m_filePaths [ index ] = newFilePath ;
}
private :
const BitTorrent : : TorrentInfo & m_torrentInfo ;
2022-02-08 06:03:48 +03:00
PathList & m_filePaths ;
2021-12-09 13:05:49 +03:00
} ;
2021-05-20 10:36:44 +03:00
// savePath is a folder, not an absolute file path
2022-02-08 06:03:48 +03:00
int indexOfPath ( const FileSystemPathComboEdit * fsPathEdit , const Path & savePath )
2021-05-20 10:36:44 +03:00
{
for ( int i = 0 ; i < fsPathEdit - > count ( ) ; + + i )
{
2022-02-08 06:03:48 +03:00
if ( fsPathEdit - > item ( i ) = = savePath )
2021-05-20 10:36:44 +03:00
return i ;
}
return - 1 ;
}
2022-02-08 06:03:48 +03:00
void setPath ( FileSystemPathComboEdit * fsPathEdit , const Path & newPath )
2021-05-20 10:36:44 +03:00
{
int existingIndex = indexOfPath ( fsPathEdit , newPath ) ;
if ( existingIndex < 0 )
{
// New path, prepend to combo box
fsPathEdit - > insertItem ( 0 , newPath ) ;
existingIndex = 0 ;
}
fsPathEdit - > setCurrentIndex ( existingIndex ) ;
}
2022-02-08 06:03:48 +03:00
void updatePathHistory ( const QString & settingsKey , const Path & path , const int maxLength )
2021-05-20 10:36:44 +03:00
{
// Add last used save path to the front of history
auto pathList = settings ( ) - > loadValue < QStringList > ( settingsKey ) ;
2022-02-08 06:03:48 +03:00
const int selectedSavePathIndex = pathList . indexOf ( path . toString ( ) ) ;
2022-01-03 07:12:23 +03:00
if ( selectedSavePathIndex > - 1 )
pathList . move ( selectedSavePathIndex , 0 ) ;
else
2022-02-08 06:03:48 +03:00
pathList . prepend ( path . toString ( ) ) ;
2021-05-20 10:36:44 +03:00
settings ( ) - > storeValue ( settingsKey , QStringList ( pathList . mid ( 0 , maxLength ) ) ) ;
}
2016-02-09 11:56:48 +03:00
}
2018-05-18 09:24:54 +03:00
const int AddNewTorrentDialog : : minPathHistoryLength ;
const int AddNewTorrentDialog : : maxPathHistoryLength ;
2017-10-16 16:10:25 +03:00
2016-07-15 05:15:10 +03:00
AddNewTorrentDialog : : AddNewTorrentDialog ( const BitTorrent : : AddTorrentParams & inParams , QWidget * parent )
2015-02-01 02:27:51 +03:00
: QDialog ( parent )
2018-04-14 22:53:45 +03:00
, m_ui ( new Ui : : AddNewTorrentDialog )
2016-07-15 05:15:10 +03:00
, m_torrentParams ( inParams )
2018-10-21 14:51:58 +03:00
, m_storeDialogSize ( SETTINGS_KEY ( " DialogSize " ) )
2021-11-08 08:23:33 +03:00
, m_storeDefaultCategory ( SETTINGS_KEY ( " DefaultCategory " ) )
, m_storeRememberLastSavePath ( SETTINGS_KEY ( " RememberLastSavePath " ) )
2021-11-04 06:34:00 +03:00
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
2021-11-23 06:02:07 +03:00
, m_storeTreeHeaderState ( " GUI/Qt6/ " SETTINGS_KEY ( " TreeHeaderState " ) )
2021-11-04 06:34:00 +03:00
, m_storeSplitterState ( " GUI/Qt6/ " SETTINGS_KEY ( " SplitterState " ) )
# else
2021-11-23 06:02:07 +03:00
, m_storeTreeHeaderState ( SETTINGS_KEY ( " TreeHeaderState " ) )
2021-11-04 06:34:00 +03:00
, m_storeSplitterState ( SETTINGS_KEY ( " SplitterState " ) )
# endif
2012-05-15 20:57:31 +04:00
{
2015-10-26 10:45:14 +03:00
// TODO: set dialog file properties using m_torrentParams.filePriorities
2018-04-14 22:53:45 +03:00
m_ui - > setupUi ( this ) ;
2015-02-01 02:27:51 +03:00
setAttribute ( Qt : : WA_DeleteOnClose ) ;
2019-06-05 07:25:45 +03:00
2018-04-14 22:53:45 +03:00
m_ui - > lblMetaLoading - > setVisible ( false ) ;
m_ui - > progMetaLoading - > setVisible ( false ) ;
2020-02-19 13:19:51 +03:00
m_ui - > buttonSave - > setVisible ( false ) ;
connect ( m_ui - > buttonSave , & QPushButton : : clicked , this , & AddNewTorrentDialog : : saveTorrentFile ) ;
2015-02-01 02:27:51 +03:00
2018-04-14 22:53:45 +03:00
m_ui - > savePath - > setMode ( FileSystemPathEdit : : Mode : : DirectorySave ) ;
m_ui - > savePath - > setDialogCaption ( tr ( " Choose save path " ) ) ;
m_ui - > savePath - > setMaxVisibleItems ( 20 ) ;
2016-04-23 02:55:59 +03:00
2019-02-22 00:31:43 +03:00
const auto * session = BitTorrent : : Session : : instance ( ) ;
2016-02-09 11:56:48 +03:00
2021-05-20 10:36:44 +03:00
m_ui - > downloadPath - > setMode ( FileSystemPathEdit : : Mode : : DirectorySave ) ;
m_ui - > downloadPath - > setDialogCaption ( tr ( " Choose save path " ) ) ;
m_ui - > downloadPath - > setMaxVisibleItems ( 20 ) ;
2021-01-02 16:55:17 +03:00
m_ui - > startTorrentCheckBox - > setChecked ( ! m_torrentParams . addPaused . value_or ( session - > isAddTorrentPaused ( ) ) ) ;
2015-10-26 10:45:14 +03:00
2022-01-28 23:18:09 +03:00
m_ui - > comboTTM - > blockSignals ( true ) ; // the TreeView size isn't correct if the slot does its job at this point
2021-05-20 10:36:44 +03:00
m_ui - > comboTTM - > setCurrentIndex ( session - > isAutoTMMDisabledByDefault ( ) ? 0 : 1 ) ;
2018-04-14 22:53:45 +03:00
m_ui - > comboTTM - > blockSignals ( false ) ;
2021-05-20 10:36:44 +03:00
2018-04-14 22:53:45 +03:00
connect ( m_ui - > savePath , & FileSystemPathEdit : : selectedPathChanged , this , & AddNewTorrentDialog : : onSavePathChanged ) ;
2021-05-20 10:36:44 +03:00
connect ( m_ui - > downloadPath , & FileSystemPathEdit : : selectedPathChanged , this , & AddNewTorrentDialog : : onDownloadPathChanged ) ;
connect ( m_ui - > groupBoxDownloadPath , & QGroupBox : : toggled , this , & AddNewTorrentDialog : : onUseDownloadPathChanged ) ;
2018-05-13 21:23:27 +03:00
2021-11-08 08:23:33 +03:00
m_ui - > checkBoxRememberLastSavePath - > setChecked ( m_storeRememberLastSavePath ) ;
2015-02-01 02:27:51 +03:00
2020-12-10 09:54:27 +03:00
m_ui - > contentLayoutComboBox - > setCurrentIndex (
2021-01-02 15:45:36 +03:00
static_cast < int > ( m_torrentParams . contentLayout . value_or ( session - > torrentContentLayout ( ) ) ) ) ;
2021-12-16 12:50:16 +03:00
connect ( m_ui - > contentLayoutComboBox , & QComboBox : : currentIndexChanged , this , & AddNewTorrentDialog : : contentLayoutChanged ) ;
2015-10-26 10:45:14 +03:00
2018-07-18 19:35:54 +03:00
m_ui - > sequentialCheckBox - > setChecked ( m_torrentParams . sequential ) ;
m_ui - > firstLastCheckBox - > setChecked ( m_torrentParams . firstLastPiecePriority ) ;
2018-04-14 22:53:45 +03:00
m_ui - > skipCheckingCheckBox - > setChecked ( m_torrentParams . skipChecking ) ;
m_ui - > doNotDeleteTorrentCheckBox - > setVisible ( TorrentFileGuard : : autoDeleteMode ( ) ! = TorrentFileGuard : : Never ) ;
2016-04-07 17:58:30 +03:00
2016-02-09 11:56:48 +03:00
// Load categories
2021-05-20 10:36:44 +03:00
QStringList categories = session - > categories ( ) ;
2021-04-05 08:02:28 +03:00
std : : sort ( categories . begin ( ) , categories . end ( ) , Utils : : Compare : : NaturalLessThan < Qt : : CaseInsensitive > ( ) ) ;
2021-11-08 08:23:33 +03:00
const QString defaultCategory = m_storeDefaultCategory ;
2015-11-03 18:05:15 +03:00
2016-07-15 05:15:10 +03:00
if ( ! m_torrentParams . category . isEmpty ( ) )
2018-04-14 22:53:45 +03:00
m_ui - > categoryComboBox - > addItem ( m_torrentParams . category ) ;
2016-02-09 11:56:48 +03:00
if ( ! defaultCategory . isEmpty ( ) )
2018-04-14 22:53:45 +03:00
m_ui - > categoryComboBox - > addItem ( defaultCategory ) ;
m_ui - > categoryComboBox - > addItem ( " " ) ;
2015-11-03 18:05:15 +03:00
2018-11-27 23:15:04 +03:00
for ( const QString & category : asConst ( categories ) )
2016-07-15 05:15:10 +03:00
if ( category ! = defaultCategory & & category ! = m_torrentParams . category )
2018-04-14 22:53:45 +03:00
m_ui - > categoryComboBox - > addItem ( category ) ;
2015-11-03 18:05:15 +03:00
2022-01-18 10:45:31 +03:00
m_ui - > contentTreeView - > header ( ) - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
2018-04-14 22:53:45 +03:00
m_ui - > contentTreeView - > header ( ) - > setSortIndicator ( 0 , Qt : : AscendingOrder ) ;
2022-01-18 10:45:31 +03:00
connect ( m_ui - > contentTreeView - > header ( ) , & QWidget : : customContextMenuRequested , this , & AddNewTorrentDialog : : displayColumnHeaderMenu ) ;
2015-02-01 02:27:51 +03:00
loadState ( ) ;
// Signal / slots
2018-04-14 22:53:45 +03:00
connect ( m_ui - > doNotDeleteTorrentCheckBox , & QCheckBox : : clicked , this , & AddNewTorrentDialog : : doNotDeleteTorrentClicked ) ;
QShortcut * editHotkey = new QShortcut ( Qt : : Key_F2 , m_ui - > contentTreeView , nullptr , nullptr , Qt : : WidgetShortcut ) ;
2021-12-09 13:05:49 +03:00
connect ( editHotkey , & QShortcut : : activated , this , & AddNewTorrentDialog : : renameSelectedFile ) ;
connect ( m_ui - > contentTreeView , & QAbstractItemView : : doubleClicked , this , & AddNewTorrentDialog : : renameSelectedFile ) ;
2015-05-24 10:12:07 +03:00
2018-04-14 22:53:45 +03:00
m_ui - > buttonBox - > button ( QDialogButtonBox : : Ok ) - > setFocus ( ) ;
2012-05-15 20:57:31 +04:00
}
AddNewTorrentDialog : : ~ AddNewTorrentDialog ( )
{
2015-02-01 02:27:51 +03:00
saveState ( ) ;
2017-05-09 08:15:01 +03:00
delete m_contentDelegate ;
2018-04-14 22:53:45 +03:00
delete m_ui ;
2012-05-15 20:57:31 +04:00
}
2016-02-09 11:56:48 +03:00
bool AddNewTorrentDialog : : isEnabled ( )
{
2021-11-08 08:23:33 +03:00
return settings ( ) - > loadValue ( KEY_ENABLED , true ) ;
2016-02-09 11:56:48 +03:00
}
2021-11-08 08:23:33 +03:00
void AddNewTorrentDialog : : setEnabled ( const bool value )
2016-02-09 11:56:48 +03:00
{
2021-11-08 08:23:33 +03:00
settings ( ) - > storeValue ( KEY_ENABLED , value ) ;
2016-02-09 11:56:48 +03:00
}
bool AddNewTorrentDialog : : isTopLevel ( )
{
2021-11-08 08:23:33 +03:00
return settings ( ) - > loadValue ( KEY_TOPLEVEL , true ) ;
2016-02-09 11:56:48 +03:00
}
2021-11-08 08:23:33 +03:00
void AddNewTorrentDialog : : setTopLevel ( const bool value )
2016-02-09 11:56:48 +03:00
{
2021-11-08 08:23:33 +03:00
settings ( ) - > storeValue ( KEY_TOPLEVEL , value ) ;
2016-02-09 11:56:48 +03:00
}
2017-10-16 16:10:25 +03:00
int AddNewTorrentDialog : : savePathHistoryLength ( )
{
2018-05-18 09:24:54 +03:00
const int defaultHistoryLength = 8 ;
2021-01-01 17:57:21 +03:00
const int value = settings ( ) - > loadValue ( KEY_SAVEPATHHISTORYLENGTH , defaultHistoryLength ) ;
2021-12-27 15:31:57 +03:00
return std : : clamp ( value , minPathHistoryLength , maxPathHistoryLength ) ;
2017-10-16 16:10:25 +03:00
}
2021-11-08 08:23:33 +03:00
void AddNewTorrentDialog : : setSavePathHistoryLength ( const int value )
2017-10-16 16:10:25 +03:00
{
2018-05-18 09:24:54 +03:00
const int clampedValue = qBound ( minPathHistoryLength , value , maxPathHistoryLength ) ;
2017-10-16 16:10:25 +03:00
const int oldValue = savePathHistoryLength ( ) ;
2018-05-18 09:24:54 +03:00
if ( clampedValue = = oldValue )
return ;
2017-10-16 16:10:25 +03:00
2018-05-18 09:24:54 +03:00
settings ( ) - > storeValue ( KEY_SAVEPATHHISTORYLENGTH , clampedValue ) ;
settings ( ) - > storeValue ( KEY_SAVEPATHHISTORY
2021-01-01 17:57:21 +03:00
, QStringList ( settings ( ) - > loadValue < QStringList > ( KEY_SAVEPATHHISTORY ) . mid ( 0 , clampedValue ) ) ) ;
2017-10-16 16:10:25 +03:00
}
2012-07-03 19:37:24 +04:00
void AddNewTorrentDialog : : loadState ( )
{
2018-10-21 14:51:58 +03:00
Utils : : Gui : : resize ( this , m_storeDialogSize ) ;
2021-11-08 08:23:33 +03:00
m_ui - > splitter - > restoreState ( m_storeSplitterState ) ; ;
2012-07-03 19:37:24 +04:00
}
void AddNewTorrentDialog : : saveState ( )
{
2018-10-21 14:51:58 +03:00
m_storeDialogSize = size ( ) ;
m_storeSplitterState = m_ui - > splitter - > saveState ( ) ;
2015-02-01 02:27:51 +03:00
if ( m_contentModel )
2021-11-08 08:23:33 +03:00
m_storeTreeHeaderState = m_ui - > contentTreeView - > header ( ) - > saveState ( ) ;
2012-07-03 19:37:24 +04:00
}
2018-12-28 08:38:08 +03:00
void AddNewTorrentDialog : : show ( const QString & source , const BitTorrent : : AddTorrentParams & inParams , QWidget * parent )
2012-05-15 20:57:31 +04:00
{
2019-02-22 04:59:31 +03:00
auto * dlg = new AddNewTorrentDialog ( inParams , parent ) ;
2013-09-17 16:18:01 +04:00
2020-11-16 10:02:11 +03:00
if ( Net : : DownloadManager : : hasSupportedScheme ( source ) )
{
2015-04-19 18:17:47 +03:00
// Launch downloader
2019-03-03 12:43:42 +03:00
Net : : DownloadManager : : instance ( ) - > download (
2019-04-08 20:09:16 +03:00
Net : : DownloadRequest ( source ) . limit ( MAX_TORRENT_SIZE )
2019-03-03 12:43:42 +03:00
, dlg , & AddNewTorrentDialog : : handleDownloadFinished ) ;
2018-12-28 08:38:08 +03:00
return ;
2015-02-01 02:27:51 +03:00
}
2018-12-28 08:38:08 +03:00
2022-02-08 06:03:48 +03:00
const BitTorrent : : MagnetUri magnetUri { source } ;
2018-12-28 08:38:08 +03:00
const bool isLoaded = magnetUri . isValid ( )
? dlg - > loadMagnet ( magnetUri )
2019-02-13 17:41:38 +03:00
: dlg - > loadTorrentFile ( source ) ;
2018-12-28 08:38:08 +03:00
2019-02-13 17:41:38 +03:00
if ( isLoaded )
2019-06-05 07:25:45 +03:00
dlg - > QDialog : : show ( ) ;
2019-02-13 17:41:38 +03:00
else
2018-12-28 08:38:08 +03:00
delete dlg ;
2012-05-15 20:57:31 +04:00
}
2018-12-28 08:38:08 +03:00
void AddNewTorrentDialog : : show ( const QString & source , QWidget * parent )
2016-07-15 05:15:10 +03:00
{
show ( source , BitTorrent : : AddTorrentParams ( ) , parent ) ;
}
2022-02-08 06:03:48 +03:00
bool AddNewTorrentDialog : : loadTorrentFile ( const QString & source )
2012-05-15 20:57:31 +04:00
{
2022-02-08 06:03:48 +03:00
const Path decodedPath { source . startsWith ( " file:// " , Qt : : CaseInsensitive )
? QUrl : : fromEncoded ( source . toLocal8Bit ( ) ) . toLocalFile ( )
: source } ;
2015-02-01 02:27:51 +03:00
2021-10-06 21:45:37 +03:00
const nonstd : : expected < BitTorrent : : TorrentInfo , QString > result = BitTorrent : : TorrentInfo : : loadFromFile ( decodedPath ) ;
if ( ! result )
2020-11-16 10:02:11 +03:00
{
2019-02-13 17:41:38 +03:00
RaisedMessageBox : : critical ( this , tr ( " Invalid torrent " )
, tr ( " Failed to load the torrent: %1. \n Error: %2 " , " Don't remove the ' \n ' characters. They insert a newline. " )
2022-02-08 06:03:48 +03:00
. arg ( decodedPath . toString ( ) , result . error ( ) ) ) ;
2015-02-01 02:27:51 +03:00
return false ;
}
2021-12-09 13:05:49 +03:00
m_torrentInfo = result . value ( ) ;
2020-03-04 19:39:41 +03:00
m_torrentGuard = std : : make_unique < TorrentFileGuard > ( decodedPath ) ;
2019-02-13 17:41:38 +03:00
return loadTorrentImpl ( ) ;
}
bool AddNewTorrentDialog : : loadTorrentImpl ( )
{
2021-03-05 12:43:58 +03:00
const auto torrentID = BitTorrent : : TorrentID : : fromInfoHash ( m_torrentInfo . infoHash ( ) ) ;
2015-04-19 18:17:47 +03:00
2015-02-01 02:27:51 +03:00
// Prevent showing the dialog if download is already present
2021-03-05 12:43:58 +03:00
if ( BitTorrent : : Session : : instance ( ) - > isKnownTorrent ( torrentID ) )
2020-11-16 10:02:11 +03:00
{
2021-03-05 12:43:58 +03:00
BitTorrent : : Torrent * const torrent = BitTorrent : : Session : : instance ( ) - > findTorrent ( torrentID ) ;
2020-11-16 10:02:11 +03:00
if ( torrent )
{
if ( torrent - > isPrivate ( ) | | m_torrentInfo . isPrivate ( ) )
{
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : warning ( this , tr ( " Torrent is already present " ) , tr ( " Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent. " ) . arg ( torrent - > name ( ) ) , QMessageBox : : Ok ) ;
2016-02-15 04:24:22 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2016-02-15 04:24:22 +03:00
torrent - > addTrackers ( m_torrentInfo . trackers ( ) ) ;
torrent - > addUrlSeeds ( m_torrentInfo . urlSeeds ( ) ) ;
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : information ( this , tr ( " Torrent is already present " ) , tr ( " Torrent '%1' is already in the transfer list. Trackers have been merged. " ) . arg ( torrent - > name ( ) ) , QMessageBox : : Ok ) ;
2016-02-15 04:24:22 +03:00
}
2015-04-19 18:17:47 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : information ( this , tr ( " Torrent is already present " ) , tr ( " Torrent is already queued for processing. " ) , QMessageBox : : Ok ) ;
2015-04-19 18:17:47 +03:00
}
2015-02-01 02:27:51 +03:00
return false ;
}
2021-06-25 20:44:23 +03:00
m_ui - > labelInfohash1Data - > setText ( m_torrentInfo . infoHash ( ) . v1 ( ) . isValid ( ) ? m_torrentInfo . infoHash ( ) . v1 ( ) . toString ( ) : tr ( " N/A " ) ) ;
m_ui - > labelInfohash2Data - > setText ( m_torrentInfo . infoHash ( ) . v2 ( ) . isValid ( ) ? m_torrentInfo . infoHash ( ) . v2 ( ) . toString ( ) : tr ( " N/A " ) ) ;
2015-02-01 02:27:51 +03:00
setupTreeview ( ) ;
2018-04-14 22:53:45 +03:00
TMMChanged ( m_ui - > comboTTM - > currentIndex ( ) ) ;
2021-05-20 10:36:44 +03:00
2015-02-01 02:27:51 +03:00
return true ;
2012-05-15 20:57:31 +04:00
}
2016-01-07 14:22:35 +03:00
bool AddNewTorrentDialog : : loadMagnet ( const BitTorrent : : MagnetUri & magnetUri )
2012-05-15 20:57:31 +04:00
{
2020-11-16 10:02:11 +03:00
if ( ! magnetUri . isValid ( ) )
{
2018-06-14 12:54:23 +03:00
RaisedMessageBox : : critical ( this , tr ( " Invalid magnet link " ) , tr ( " This magnet link was not recognized " ) ) ;
2015-02-01 02:27:51 +03:00
return false ;
}
2013-07-27 23:05:19 +04:00
2020-03-04 19:39:41 +03:00
m_torrentGuard = std : : make_unique < TorrentFileGuard > ( ) ;
2020-09-07 18:05:55 +03:00
2021-03-05 12:43:58 +03:00
const auto torrentID = BitTorrent : : TorrentID : : fromInfoHash ( magnetUri . infoHash ( ) ) ;
2015-02-01 02:27:51 +03:00
// Prevent showing the dialog if download is already present
2021-03-05 12:43:58 +03:00
if ( BitTorrent : : Session : : instance ( ) - > isKnownTorrent ( torrentID ) )
2020-11-16 10:02:11 +03:00
{
2021-03-05 12:43:58 +03:00
BitTorrent : : Torrent * const torrent = BitTorrent : : Session : : instance ( ) - > findTorrent ( torrentID ) ;
2020-11-16 10:02:11 +03:00
if ( torrent )
{
if ( torrent - > isPrivate ( ) )
{
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : warning ( this , tr ( " Torrent is already present " ) , tr ( " Torrent '%1' is already in the transfer list. Trackers haven't been merged because it is a private torrent. " ) . arg ( torrent - > name ( ) ) , QMessageBox : : Ok ) ;
2016-02-15 04:24:22 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2016-02-15 04:24:22 +03:00
torrent - > addTrackers ( magnetUri . trackers ( ) ) ;
torrent - > addUrlSeeds ( magnetUri . urlSeeds ( ) ) ;
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : information ( this , tr ( " Torrent is already present " ) , tr ( " Magnet link '%1' is already in the transfer list. Trackers have been merged. " ) . arg ( torrent - > name ( ) ) , QMessageBox : : Ok ) ;
2016-02-15 04:24:22 +03:00
}
2015-04-19 18:17:47 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2018-07-15 05:31:21 +03:00
RaisedMessageBox : : information ( this , tr ( " Torrent is already present " ) , tr ( " Magnet link is already queued for processing. " ) , QMessageBox : : Ok ) ;
2015-04-19 18:17:47 +03:00
}
2015-02-01 02:27:51 +03:00
return false ;
}
2020-11-21 15:16:21 +03:00
connect ( BitTorrent : : Session : : instance ( ) , & BitTorrent : : Session : : metadataDownloaded , this , & AddNewTorrentDialog : : updateMetadata ) ;
2015-04-19 18:17:47 +03:00
2015-02-01 02:27:51 +03:00
// Set dialog title
2020-09-07 18:05:55 +03:00
const QString torrentName = magnetUri . name ( ) ;
2018-04-14 22:53:45 +03:00
setWindowTitle ( torrentName . isEmpty ( ) ? tr ( " Magnet link " ) : torrentName ) ;
2012-05-15 20:57:31 +04:00
2015-02-01 02:27:51 +03:00
setupTreeview ( ) ;
2018-04-14 22:53:45 +03:00
TMMChanged ( m_ui - > comboTTM - > currentIndex ( ) ) ;
2012-05-20 19:14:02 +04:00
2020-11-21 15:16:21 +03:00
BitTorrent : : Session : : instance ( ) - > downloadMetadata ( magnetUri ) ;
2015-02-01 02:27:51 +03:00
setMetadataProgressIndicator ( true , tr ( " Retrieving metadata... " ) ) ;
2021-06-25 20:44:23 +03:00
m_ui - > labelInfohash1Data - > setText ( magnetUri . infoHash ( ) . v1 ( ) . isValid ( ) ? magnetUri . infoHash ( ) . v1 ( ) . toString ( ) : tr ( " N/A " ) ) ;
m_ui - > labelInfohash2Data - > setText ( magnetUri . infoHash ( ) . v2 ( ) . isValid ( ) ? magnetUri . infoHash ( ) . v2 ( ) . toString ( ) : tr ( " N/A " ) ) ;
2013-07-27 23:04:16 +04:00
2020-09-07 18:05:55 +03:00
m_magnetURI = magnetUri ;
2015-02-01 02:27:51 +03:00
return true ;
2012-05-15 20:57:31 +04:00
}
2015-04-19 18:17:47 +03:00
void AddNewTorrentDialog : : showEvent ( QShowEvent * event )
{
QDialog : : showEvent ( event ) ;
2016-02-09 11:56:48 +03:00
if ( ! isTopLevel ( ) ) return ;
2015-04-19 18:17:47 +03:00
activateWindow ( ) ;
raise ( ) ;
}
2015-02-01 02:27:51 +03:00
void AddNewTorrentDialog : : updateDiskSpaceLabel ( )
{
// Determine torrent size
2018-09-07 14:12:38 +03:00
qlonglong torrentSize = 0 ;
2015-02-01 02:27:51 +03:00
2021-12-09 13:05:49 +03:00
if ( hasMetadata ( ) )
2020-11-16 10:02:11 +03:00
{
if ( m_contentModel )
{
2019-03-06 08:58:07 +03:00
const QVector < BitTorrent : : DownloadPriority > priorities = m_contentModel - > model ( ) - > getFilePriorities ( ) ;
2015-04-19 18:17:47 +03:00
Q_ASSERT ( priorities . size ( ) = = m_torrentInfo . filesCount ( ) ) ;
for ( int i = 0 ; i < priorities . size ( ) ; + + i )
2021-10-02 21:42:58 +03:00
{
2019-03-06 08:58:07 +03:00
if ( priorities [ i ] > BitTorrent : : DownloadPriority : : Ignored )
2018-04-14 22:53:45 +03:00
torrentSize + = m_torrentInfo . fileSize ( i ) ;
2021-10-02 21:42:58 +03:00
}
2015-02-01 02:27:51 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2018-04-14 22:53:45 +03:00
torrentSize = m_torrentInfo . totalSize ( ) ;
2015-02-01 02:27:51 +03:00
}
2012-05-15 20:57:31 +04:00
}
2015-02-01 02:27:51 +03:00
2019-05-27 11:19:24 +03:00
const QString sizeString = tr ( " %1 (Free space on disk: %2) " ) . arg (
( ( torrentSize > 0 ) ? Utils : : Misc : : friendlyUnit ( torrentSize ) : tr ( " Not available " , " This size is unavailable. " ) )
, Utils : : Misc : : friendlyUnit ( Utils : : Fs : : freeDiskSpaceOnPath ( m_ui - > savePath - > selectedPath ( ) ) ) ) ;
2018-10-21 14:51:58 +03:00
m_ui - > labelSizeData - > setText ( sizeString ) ;
2012-05-15 20:57:31 +04:00
}
2022-02-08 06:03:48 +03:00
void AddNewTorrentDialog : : onSavePathChanged ( const Path & newPath )
2012-05-15 20:57:31 +04:00
{
2018-05-13 21:23:27 +03:00
Q_UNUSED ( newPath ) ;
2015-02-01 02:27:51 +03:00
// Remember index
2021-05-20 10:36:44 +03:00
m_savePathIndex = m_ui - > savePath - > currentIndex ( ) ;
2015-06-28 10:57:40 +03:00
updateDiskSpaceLabel ( ) ;
2012-12-01 04:06:47 +04:00
}
2022-02-08 06:03:48 +03:00
void AddNewTorrentDialog : : onDownloadPathChanged ( const Path & newPath )
2021-05-20 10:36:44 +03:00
{
Q_UNUSED ( newPath ) ;
// Remember index
const int currentPathIndex = m_ui - > downloadPath - > currentIndex ( ) ;
if ( currentPathIndex > = 0 )
m_downloadPathIndex = m_ui - > downloadPath - > currentIndex ( ) ;
}
void AddNewTorrentDialog : : onUseDownloadPathChanged ( const bool checked )
{
m_useDownloadPath = checked ;
m_ui - > downloadPath - > setCurrentIndex ( checked ? m_downloadPathIndex : - 1 ) ;
}
2016-02-09 11:56:48 +03:00
void AddNewTorrentDialog : : categoryChanged ( int index )
{
Q_UNUSED ( index ) ;
2020-11-16 10:02:11 +03:00
if ( m_ui - > comboTTM - > currentIndex ( ) = = 1 )
{
2021-05-20 10:36:44 +03:00
const auto * btSession = BitTorrent : : Session : : instance ( ) ;
const QString categoryName = m_ui - > categoryComboBox - > currentText ( ) ;
2022-02-08 06:03:48 +03:00
const Path savePath = btSession - > categorySavePath ( categoryName ) ;
m_ui - > savePath - > setSelectedPath ( savePath ) ;
2021-05-20 10:36:44 +03:00
2022-02-08 06:03:48 +03:00
const Path downloadPath = btSession - > categoryDownloadPath ( categoryName ) ;
m_ui - > downloadPath - > setSelectedPath ( downloadPath ) ;
2021-05-20 10:36:44 +03:00
m_ui - > groupBoxDownloadPath - > setChecked ( ! m_ui - > downloadPath - > selectedPath ( ) . isEmpty ( ) ) ;
2019-12-18 13:49:43 +03:00
updateDiskSpaceLabel ( ) ;
2016-02-09 11:56:48 +03:00
}
}
2021-12-16 12:50:16 +03:00
void AddNewTorrentDialog : : contentLayoutChanged ( const int index )
{
if ( ! hasMetadata ( ) )
return ;
const auto filePriorities = m_contentModel - > model ( ) - > getFilePriorities ( ) ;
m_contentModel - > model ( ) - > clear ( ) ;
Q_ASSERT ( ! m_torrentParams . filePaths . isEmpty ( ) ) ;
const auto contentLayout = ( ( index = = 0 )
? BitTorrent : : detectContentLayout ( m_torrentInfo . filePaths ( ) )
: static_cast < BitTorrent : : TorrentContentLayout > ( index ) ) ;
2022-02-08 06:03:48 +03:00
BitTorrent : : applyContentLayout ( m_torrentParams . filePaths , contentLayout , Path : : findRootFolder ( m_torrentInfo . filePaths ( ) ) ) ;
2021-12-16 12:50:16 +03:00
m_contentModel - > model ( ) - > setupModelData ( FileStorageAdaptor ( m_torrentInfo , m_torrentParams . filePaths ) ) ;
m_contentModel - > model ( ) - > updateFilesPriorities ( filePriorities ) ;
// Expand single-item folders recursively
QModelIndex currentIndex ;
while ( m_contentModel - > rowCount ( currentIndex ) = = 1 )
{
currentIndex = m_contentModel - > index ( 0 , 0 , currentIndex ) ;
m_ui - > contentTreeView - > setExpanded ( currentIndex , true ) ;
}
}
2020-02-19 13:19:51 +03:00
void AddNewTorrentDialog : : saveTorrentFile ( )
{
2021-12-09 13:05:49 +03:00
Q_ASSERT ( hasMetadata ( ) ) ;
2020-02-19 13:19:51 +03:00
const QString torrentFileExtension { C_TORRENT_FILE_EXTENSION } ;
2021-07-04 09:29:34 +03:00
const QString filter { tr ( " Torrent file (*%1) " ) . arg ( torrentFileExtension ) } ;
2020-02-19 13:19:51 +03:00
QString path = QFileDialog : : getSaveFileName (
this , tr ( " Save as torrent file " )
, QDir : : home ( ) . absoluteFilePath ( m_torrentInfo . name ( ) + torrentFileExtension )
, filter ) ;
if ( path . isEmpty ( ) ) return ;
if ( ! path . endsWith ( torrentFileExtension , Qt : : CaseInsensitive ) )
path + = torrentFileExtension ;
2022-02-08 06:03:48 +03:00
const nonstd : : expected < void , QString > result = m_torrentInfo . saveToFile ( Path ( path ) ) ;
2021-10-06 21:53:56 +03:00
if ( ! result )
2020-11-16 10:02:11 +03:00
{
2021-06-17 20:28:07 +03:00
QMessageBox : : critical ( this , tr ( " I/O Error " )
2021-10-06 21:53:56 +03:00
, tr ( " Couldn't export torrent metadata file '%1'. Reason: %2. " ) . arg ( path , result . error ( ) ) ) ;
2020-02-19 13:19:51 +03:00
}
}
2021-12-09 13:05:49 +03:00
bool AddNewTorrentDialog : : hasMetadata ( ) const
{
return m_torrentInfo . isValid ( ) ;
}
2021-05-20 10:36:44 +03:00
void AddNewTorrentDialog : : populateSavePaths ( )
2012-05-15 20:57:31 +04:00
{
2021-05-20 10:36:44 +03:00
const auto * btSession = BitTorrent : : Session : : instance ( ) ;
m_ui - > savePath - > blockSignals ( true ) ;
2018-04-14 22:53:45 +03:00
m_ui - > savePath - > clear ( ) ;
2021-05-20 10:36:44 +03:00
const auto savePathHistory = settings ( ) - > loadValue < QStringList > ( KEY_SAVEPATHHISTORY ) ;
if ( savePathHistory . size ( ) > 0 )
{
for ( const QString & path : savePathHistory )
2022-02-08 06:03:48 +03:00
m_ui - > savePath - > addItem ( Path ( path ) ) ;
2021-05-20 10:36:44 +03:00
}
else
{
m_ui - > savePath - > addItem ( btSession - > savePath ( ) ) ;
}
2018-05-13 21:23:27 +03:00
2021-05-20 10:36:44 +03:00
if ( m_savePathIndex > = 0 )
{
m_ui - > savePath - > setCurrentIndex ( std : : min ( m_savePathIndex , ( m_ui - > savePath - > count ( ) - 1 ) ) ) ;
}
else
{
if ( ! m_torrentParams . savePath . isEmpty ( ) )
setPath ( m_ui - > savePath , m_torrentParams . savePath ) ;
else if ( ! m_storeRememberLastSavePath )
setPath ( m_ui - > savePath , btSession - > savePath ( ) ) ;
else
m_ui - > savePath - > setCurrentIndex ( 0 ) ;
m_savePathIndex = m_ui - > savePath - > currentIndex ( ) ;
}
m_ui - > savePath - > blockSignals ( false ) ;
m_ui - > downloadPath - > blockSignals ( true ) ;
m_ui - > downloadPath - > clear ( ) ;
const auto downloadPathHistory = settings ( ) - > loadValue < QStringList > ( KEY_DOWNLOADPATHHISTORY ) ;
if ( downloadPathHistory . size ( ) > 0 )
{
for ( const QString & path : downloadPathHistory )
2022-02-08 06:03:48 +03:00
m_ui - > downloadPath - > addItem ( Path ( path ) ) ;
2021-05-20 10:36:44 +03:00
}
else
{
m_ui - > downloadPath - > addItem ( btSession - > downloadPath ( ) ) ;
}
2018-05-13 21:23:27 +03:00
2021-05-20 10:36:44 +03:00
if ( m_downloadPathIndex > = 0 )
{
m_ui - > downloadPath - > setCurrentIndex ( m_useDownloadPath ? std : : min ( m_downloadPathIndex , ( m_ui - > downloadPath - > count ( ) - 1 ) ) : - 1 ) ;
m_ui - > groupBoxDownloadPath - > setChecked ( m_useDownloadPath ) ;
}
else
{
const bool useDownloadPath = m_torrentParams . useDownloadPath . value_or ( btSession - > isDownloadPathEnabled ( ) ) ;
m_ui - > groupBoxDownloadPath - > setChecked ( useDownloadPath ) ;
2017-09-25 20:30:44 +03:00
2021-05-20 10:36:44 +03:00
if ( ! m_torrentParams . downloadPath . isEmpty ( ) )
setPath ( m_ui - > downloadPath , m_torrentParams . downloadPath ) ;
else if ( ! m_storeRememberLastSavePath )
setPath ( m_ui - > downloadPath , btSession - > downloadPath ( ) ) ;
else
m_ui - > downloadPath - > setCurrentIndex ( 0 ) ;
m_downloadPathIndex = m_ui - > downloadPath - > currentIndex ( ) ;
if ( ! useDownloadPath )
m_ui - > downloadPath - > setCurrentIndex ( - 1 ) ;
}
m_ui - > downloadPath - > blockSignals ( false ) ;
m_ui - > groupBoxDownloadPath - > blockSignals ( false ) ;
2012-05-15 20:57:31 +04:00
}
2022-01-21 12:31:31 +03:00
void AddNewTorrentDialog : : displayContentTreeMenu ( )
2015-02-01 02:27:51 +03:00
{
2018-04-14 22:53:45 +03:00
const QModelIndexList selectedRows = m_ui - > contentTreeView - > selectionModel ( ) - > selectedRows ( 0 ) ;
2019-06-03 10:10:19 +03:00
2021-01-17 09:47:12 +03:00
const auto applyPriorities = [ this ] ( const BitTorrent : : DownloadPriority prio )
2019-06-03 10:10:19 +03:00
{
2021-01-17 09:47:12 +03:00
const QModelIndexList selectedRows = m_ui - > contentTreeView - > selectionModel ( ) - > selectedRows ( 0 ) ;
2020-11-16 10:02:11 +03:00
for ( const QModelIndex & index : selectedRows )
{
2021-01-17 09:47:12 +03:00
m_contentModel - > setData ( index . sibling ( index . row ( ) , PRIORITY )
2019-06-03 10:10:19 +03:00
, static_cast < int > ( prio ) ) ;
2012-05-15 20:57:31 +04:00
}
2019-06-03 10:10:19 +03:00
} ;
2021-04-04 02:33:51 +03:00
const auto applyPrioritiesByOrder = [ this ] ( )
2021-01-17 09:47:12 +03:00
{
// Equally distribute the selected items into groups and for each group assign
// a download priority that will apply to each item. The number of groups depends on how
// many "download priority" are available to be assigned
const QModelIndexList selectedRows = m_ui - > contentTreeView - > selectionModel ( ) - > selectedRows ( 0 ) ;
2021-03-18 10:40:05 +03:00
const qsizetype priorityGroups = 3 ;
const auto priorityGroupSize = std : : max < qsizetype > ( ( selectedRows . length ( ) / priorityGroups ) , 1 ) ;
2021-01-17 09:47:12 +03:00
2021-03-18 10:40:05 +03:00
for ( qsizetype i = 0 ; i < selectedRows . length ( ) ; + + i )
2021-01-17 09:47:12 +03:00
{
auto priority = BitTorrent : : DownloadPriority : : Ignored ;
switch ( i / priorityGroupSize )
{
case 0 :
priority = BitTorrent : : DownloadPriority : : Maximum ;
break ;
case 1 :
priority = BitTorrent : : DownloadPriority : : High ;
break ;
default :
case 2 :
priority = BitTorrent : : DownloadPriority : : Normal ;
break ;
}
const QModelIndex & index = selectedRows [ i ] ;
m_contentModel - > setData ( index . sibling ( index . row ( ) , PRIORITY )
, static_cast < int > ( priority ) ) ;
}
2021-04-04 02:33:51 +03:00
} ;
QMenu * menu = new QMenu ( this ) ;
menu - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2022-01-18 10:45:31 +03:00
2021-04-04 02:33:51 +03:00
if ( selectedRows . size ( ) = = 1 )
{
2021-12-09 13:05:49 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( " edit-rename " ) , tr ( " Rename... " ) , this , & AddNewTorrentDialog : : renameSelectedFile ) ;
2021-04-04 02:33:51 +03:00
menu - > addSeparator ( ) ;
QMenu * priorityMenu = menu - > addMenu ( tr ( " Priority " ) ) ;
priorityMenu - > addAction ( tr ( " Do not download " ) , priorityMenu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Ignored ) ;
} ) ;
priorityMenu - > addAction ( tr ( " Normal " ) , priorityMenu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Normal ) ;
} ) ;
priorityMenu - > addAction ( tr ( " High " ) , priorityMenu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : High ) ;
} ) ;
priorityMenu - > addAction ( tr ( " Maximum " ) , priorityMenu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Maximum ) ;
} ) ;
priorityMenu - > addSeparator ( ) ;
priorityMenu - > addAction ( tr ( " By shown file order " ) , priorityMenu , applyPrioritiesByOrder ) ;
}
else
{
menu - > addAction ( tr ( " Do not download " ) , menu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Ignored ) ;
} ) ;
menu - > addAction ( tr ( " Normal priority " ) , menu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Normal ) ;
} ) ;
menu - > addAction ( tr ( " High priority " ) , menu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : High ) ;
} ) ;
menu - > addAction ( tr ( " Maximum priority " ) , menu , [ applyPriorities ] ( )
{
applyPriorities ( BitTorrent : : DownloadPriority : : Maximum ) ;
} ) ;
menu - > addSeparator ( ) ;
menu - > addAction ( tr ( " Priority by shown file order " ) , menu , applyPrioritiesByOrder ) ;
}
2019-06-03 10:10:19 +03:00
menu - > popup ( QCursor : : pos ( ) ) ;
2012-05-15 20:57:31 +04:00
}
2022-01-18 10:45:31 +03:00
void AddNewTorrentDialog : : displayColumnHeaderMenu ( )
{
QMenu * menu = new QMenu ( this ) ;
menu - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
menu - > setToolTipsVisible ( true ) ;
QAction * resizeAction = menu - > addAction ( tr ( " Resize columns " ) , this , [ this ] ( )
{
for ( int i = 0 , count = m_ui - > contentTreeView - > header ( ) - > count ( ) ; i < count ; + + i )
{
if ( ! m_ui - > contentTreeView - > isColumnHidden ( i ) )
m_ui - > contentTreeView - > resizeColumnToContents ( i ) ;
}
} ) ;
resizeAction - > setToolTip ( tr ( " Resize all non-hidden columns to the size of their contents " ) ) ;
menu - > popup ( QCursor : : pos ( ) ) ;
}
2013-07-27 23:04:16 +04:00
void AddNewTorrentDialog : : accept ( )
2012-05-15 20:57:31 +04:00
{
2015-11-07 21:44:53 +03:00
// TODO: Check if destination actually exists
2018-04-14 22:53:45 +03:00
m_torrentParams . skipChecking = m_ui - > skipCheckingCheckBox - > isChecked ( ) ;
2015-02-01 02:27:51 +03:00
2016-02-09 11:56:48 +03:00
// Category
2018-04-14 22:53:45 +03:00
m_torrentParams . category = m_ui - > categoryComboBox - > currentText ( ) ;
if ( m_ui - > defaultCategoryCheckbox - > isChecked ( ) )
2021-11-08 08:23:33 +03:00
m_storeDefaultCategory = m_torrentParams . category ;
2015-11-03 18:05:15 +03:00
2021-11-08 08:23:33 +03:00
m_storeRememberLastSavePath = m_ui - > checkBoxRememberLastSavePath - > isChecked ( ) ;
2018-05-13 21:23:27 +03:00
2015-02-01 02:27:51 +03:00
// Save file priorities
if ( m_contentModel )
2016-07-15 05:15:10 +03:00
m_torrentParams . filePriorities = m_contentModel - > model ( ) - > getFilePriorities ( ) ;
2015-02-01 02:27:51 +03:00
2021-01-02 16:55:17 +03:00
m_torrentParams . addPaused = ! m_ui - > startTorrentCheckBox - > isChecked ( ) ;
2020-12-10 09:54:27 +03:00
m_torrentParams . contentLayout = static_cast < BitTorrent : : TorrentContentLayout > ( m_ui - > contentLayoutComboBox - > currentIndex ( ) ) ;
2015-04-19 18:17:47 +03:00
2018-07-18 19:35:54 +03:00
m_torrentParams . sequential = m_ui - > sequentialCheckBox - > isChecked ( ) ;
m_torrentParams . firstLastPiecePriority = m_ui - > firstLastCheckBox - > isChecked ( ) ;
2021-05-20 10:36:44 +03:00
const bool useAutoTMM = ( m_ui - > comboTTM - > currentIndex ( ) = = 1 ) ; // 1 is Automatic mode. Handle all non 1 values as manual mode.
m_torrentParams . useAutoTMM = useAutoTMM ;
if ( ! useAutoTMM )
2020-11-16 10:02:11 +03:00
{
2022-02-08 06:03:48 +03:00
const Path savePath = m_ui - > savePath - > selectedPath ( ) ;
2021-05-20 10:36:44 +03:00
m_torrentParams . savePath = savePath ;
updatePathHistory ( KEY_SAVEPATHHISTORY , savePath , savePathHistoryLength ( ) ) ;
m_torrentParams . useDownloadPath = m_ui - > groupBoxDownloadPath - > isChecked ( ) ;
if ( m_torrentParams . useDownloadPath )
{
2022-02-08 06:03:48 +03:00
const Path downloadPath = m_ui - > downloadPath - > selectedPath ( ) ;
2021-05-20 10:36:44 +03:00
m_torrentParams . downloadPath = downloadPath ;
updatePathHistory ( KEY_DOWNLOADPATHHISTORY , downloadPath , savePathHistoryLength ( ) ) ;
}
2017-08-05 23:11:40 +03:00
}
2015-04-19 18:17:47 +03:00
2018-06-14 12:38:18 +03:00
setEnabled ( ! m_ui - > checkBoxNeverShow - > isChecked ( ) ) ;
2016-02-09 11:56:48 +03:00
2015-04-19 18:17:47 +03:00
// Add torrent
2021-12-09 13:05:49 +03:00
if ( ! hasMetadata ( ) )
2020-09-07 18:05:55 +03:00
BitTorrent : : Session : : instance ( ) - > addTorrent ( m_magnetURI , m_torrentParams ) ;
2015-04-19 18:17:47 +03:00
else
2016-07-15 05:15:10 +03:00
BitTorrent : : Session : : instance ( ) - > addTorrent ( m_torrentInfo , m_torrentParams ) ;
2015-04-19 18:17:47 +03:00
2016-04-07 17:58:30 +03:00
m_torrentGuard - > markAsAddedToSession ( ) ;
2015-02-01 02:27:51 +03:00
QDialog : : accept ( ) ;
2013-07-27 23:04:16 +04:00
}
2015-02-01 02:27:51 +03:00
void AddNewTorrentDialog : : reject ( )
{
2021-12-09 13:05:49 +03:00
if ( ! hasMetadata ( ) )
2020-11-16 10:02:11 +03:00
{
2015-02-01 02:27:51 +03:00
setMetadataProgressIndicator ( false ) ;
2021-03-05 12:43:58 +03:00
BitTorrent : : Session : : instance ( ) - > cancelDownloadMetadata ( m_magnetURI . infoHash ( ) . toTorrentID ( ) ) ;
2015-02-01 02:27:51 +03:00
}
2015-04-19 18:17:47 +03:00
2015-02-01 02:27:51 +03:00
QDialog : : reject ( ) ;
2013-07-27 23:04:16 +04:00
}
2020-08-14 16:32:09 +03:00
void AddNewTorrentDialog : : updateMetadata ( const BitTorrent : : TorrentInfo & metadata )
2015-02-01 02:27:51 +03:00
{
2021-12-16 12:50:16 +03:00
Q_ASSERT ( metadata . isValid ( ) ) ;
2021-03-05 12:43:58 +03:00
if ( metadata . infoHash ( ) ! = m_magnetURI . infoHash ( ) ) return ;
2013-07-27 23:04:16 +04:00
2020-11-21 15:16:21 +03:00
disconnect ( BitTorrent : : Session : : instance ( ) , & BitTorrent : : Session : : metadataDownloaded , this , & AddNewTorrentDialog : : updateMetadata ) ;
2019-06-03 19:14:57 +03:00
2015-04-19 18:17:47 +03:00
// Good to go
2020-08-14 16:32:09 +03:00
m_torrentInfo = metadata ;
2015-04-19 18:17:47 +03:00
setMetadataProgressIndicator ( true , tr ( " Parsing metadata... " ) ) ;
// Update UI
setupTreeview ( ) ;
setMetadataProgressIndicator ( false , tr ( " Metadata retrieval complete " ) ) ;
2021-07-04 09:29:34 +03:00
m_ui - > buttonSave - > setVisible ( true ) ;
if ( m_torrentInfo . infoHash ( ) . v2 ( ) . isValid ( ) )
{
m_ui - > buttonSave - > setEnabled ( false ) ;
m_ui - > buttonSave - > setToolTip ( tr ( " Cannot create v2 torrent until its data is fully downloaded. " ) ) ;
}
2012-05-15 20:57:31 +04:00
}
2013-07-27 23:05:19 +04:00
2015-02-01 02:27:51 +03:00
void AddNewTorrentDialog : : setMetadataProgressIndicator ( bool visibleIndicator , const QString & labelText )
{
// Always show info label when waiting for metadata
2018-04-14 22:53:45 +03:00
m_ui - > lblMetaLoading - > setVisible ( true ) ;
m_ui - > lblMetaLoading - > setText ( labelText ) ;
m_ui - > progMetaLoading - > setVisible ( visibleIndicator ) ;
2013-07-27 23:05:19 +04:00
}
2014-02-02 21:54:19 +04:00
2015-02-01 02:27:51 +03:00
void AddNewTorrentDialog : : setupTreeview ( )
{
2021-12-09 13:05:49 +03:00
if ( ! hasMetadata ( ) )
2020-11-16 10:02:11 +03:00
{
2018-10-21 14:51:58 +03:00
m_ui - > labelCommentData - > setText ( tr ( " Not Available " , " This comment is unavailable " ) ) ;
m_ui - > labelDateData - > setText ( tr ( " Not Available " , " This date is unavailable " ) ) ;
2014-08-10 00:10:20 +04:00
}
2020-11-16 10:02:11 +03:00
else
{
2015-02-01 02:27:51 +03:00
// Set dialog title
2015-04-19 18:17:47 +03:00
setWindowTitle ( m_torrentInfo . name ( ) ) ;
2015-02-01 02:27:51 +03:00
// Set torrent information
2019-09-15 09:35:02 +03:00
m_ui - > labelCommentData - > setText ( Utils : : Misc : : parseHtmlLinks ( m_torrentInfo . comment ( ) . toHtmlEscaped ( ) ) ) ;
2021-01-06 07:47:18 +03:00
m_ui - > labelDateData - > setText ( ! m_torrentInfo . creationDate ( ) . isNull ( ) ? QLocale ( ) . toString ( m_torrentInfo . creationDate ( ) , QLocale : : ShortFormat ) : tr ( " Not available " ) ) ;
2015-02-01 02:27:51 +03:00
// Prepare content tree
2016-02-06 11:38:00 +03:00
m_contentModel = new TorrentContentFilterModel ( this ) ;
2018-04-18 16:59:41 +03:00
connect ( m_contentModel - > model ( ) , & TorrentContentModel : : filteredFilesChanged , this , & AddNewTorrentDialog : : updateDiskSpaceLabel ) ;
2018-04-14 22:53:45 +03:00
m_ui - > contentTreeView - > setModel ( m_contentModel ) ;
2017-03-08 08:01:59 +03:00
m_contentDelegate = new PropListDelegate ( nullptr ) ;
2018-04-14 22:53:45 +03:00
m_ui - > contentTreeView - > setItemDelegate ( m_contentDelegate ) ;
connect ( m_ui - > contentTreeView , & QAbstractItemView : : clicked , m_ui - > contentTreeView
2019-07-24 20:41:09 +03:00
, qOverload < const QModelIndex & > ( & QAbstractItemView : : edit ) ) ;
2018-04-14 22:53:45 +03:00
connect ( m_ui - > contentTreeView , & QWidget : : customContextMenuRequested , this , & AddNewTorrentDialog : : displayContentTreeMenu ) ;
2022-01-28 23:18:09 +03:00
connect ( m_ui - > buttonSelectAll , & QPushButton : : clicked , m_contentModel , & TorrentContentFilterModel : : selectAll ) ;
connect ( m_ui - > buttonSelectNone , & QPushButton : : clicked , m_contentModel , & TorrentContentFilterModel : : selectNone ) ;
2016-02-06 11:38:00 +03:00
2021-12-16 12:50:16 +03:00
const auto contentLayout = ( ( m_ui - > contentLayoutComboBox - > currentIndex ( ) = = 0 )
? BitTorrent : : detectContentLayout ( m_torrentInfo . filePaths ( ) )
: static_cast < BitTorrent : : TorrentContentLayout > ( m_ui - > contentLayoutComboBox - > currentIndex ( ) ) ) ;
if ( m_torrentParams . filePaths . isEmpty ( ) )
m_torrentParams . filePaths = m_torrentInfo . filePaths ( ) ;
2022-02-08 06:03:48 +03:00
BitTorrent : : applyContentLayout ( m_torrentParams . filePaths , contentLayout , Path : : findRootFolder ( m_torrentInfo . filePaths ( ) ) ) ;
2016-02-06 11:38:00 +03:00
// List files in torrent
2021-12-09 13:05:49 +03:00
m_contentModel - > model ( ) - > setupModelData ( FileStorageAdaptor ( m_torrentInfo , m_torrentParams . filePaths ) ) ;
2021-11-04 06:34:00 +03:00
if ( const QByteArray state = m_storeTreeHeaderState ; ! state . isEmpty ( ) )
m_ui - > contentTreeView - > header ( ) - > restoreState ( state ) ;
2016-02-06 11:38:00 +03:00
2016-03-18 01:23:11 +03:00
// Hide useless columns after loading the header state
2018-04-14 22:53:45 +03:00
m_ui - > contentTreeView - > hideColumn ( PROGRESS ) ;
m_ui - > contentTreeView - > hideColumn ( REMAINING ) ;
m_ui - > contentTreeView - > hideColumn ( AVAILABILITY ) ;
2016-03-18 01:23:11 +03:00
2019-12-02 19:56:44 +03:00
// Expand single-item folders recursively
QModelIndex currentIndex ;
2020-11-16 10:02:11 +03:00
while ( m_contentModel - > rowCount ( currentIndex ) = = 1 )
{
2019-12-02 19:56:44 +03:00
currentIndex = m_contentModel - > index ( 0 , 0 , currentIndex ) ;
m_ui - > contentTreeView - > setExpanded ( currentIndex , true ) ;
}
2014-02-02 21:54:19 +04:00
}
2015-02-01 02:27:51 +03:00
updateDiskSpaceLabel ( ) ;
2014-02-02 21:54:19 +04:00
}
2015-04-19 18:17:47 +03:00
2021-10-06 21:45:37 +03:00
void AddNewTorrentDialog : : handleDownloadFinished ( const Net : : DownloadResult & downloadResult )
2015-04-19 18:17:47 +03:00
{
2021-10-06 21:45:37 +03:00
switch ( downloadResult . status )
2020-11-16 10:02:11 +03:00
{
2019-03-01 10:38:16 +03:00
case Net : : DownloadStatus : : Success :
2020-11-16 10:02:11 +03:00
{
2021-10-06 21:45:37 +03:00
const nonstd : : expected < BitTorrent : : TorrentInfo , QString > result = BitTorrent : : TorrentInfo : : load ( downloadResult . data ) ;
if ( ! result )
{
RaisedMessageBox : : critical ( this , tr ( " Invalid torrent " ) , tr ( " Failed to load from URL: %1. \n Error: %2 " )
. arg ( downloadResult . url , result . error ( ) ) ) ;
return ;
}
2019-02-13 17:41:38 +03:00
2021-12-09 13:05:49 +03:00
m_torrentInfo = result . value ( ) ;
2021-10-06 21:45:37 +03:00
m_torrentGuard = std : : make_unique < TorrentFileGuard > ( ) ;
2019-03-01 10:38:16 +03:00
2021-10-06 21:45:37 +03:00
if ( loadTorrentImpl ( ) )
open ( ) ;
else
deleteLater ( ) ;
}
2019-03-01 10:38:16 +03:00
break ;
case Net : : DownloadStatus : : RedirectedToMagnet :
2021-10-06 21:45:37 +03:00
if ( loadMagnet ( BitTorrent : : MagnetUri ( downloadResult . magnet ) ) )
2019-03-01 10:38:16 +03:00
open ( ) ;
else
deleteLater ( ) ;
break ;
default :
RaisedMessageBox : : critical ( this , tr ( " Download Error " ) ,
2021-10-06 21:45:37 +03:00
tr ( " Cannot download '%1': %2 " ) . arg ( downloadResult . url , downloadResult . errorString ) ) ;
2019-03-01 10:38:16 +03:00
deleteLater ( ) ;
}
2015-04-19 18:17:47 +03:00
}
2016-02-09 11:56:48 +03:00
2016-05-08 22:47:50 +03:00
void AddNewTorrentDialog : : TMMChanged ( int index )
2016-02-09 11:56:48 +03:00
{
2020-11-16 10:02:11 +03:00
if ( index ! = 1 )
{ // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode.
2021-05-20 10:36:44 +03:00
populateSavePaths ( ) ;
2018-04-14 22:53:45 +03:00
m_ui - > groupBoxSavePath - > setEnabled ( true ) ;
2016-02-09 11:56:48 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2021-05-20 10:36:44 +03:00
const auto * session = BitTorrent : : Session : : instance ( ) ;
2018-04-14 22:53:45 +03:00
m_ui - > groupBoxSavePath - > setEnabled ( false ) ;
2021-05-20 10:36:44 +03:00
2018-04-14 22:53:45 +03:00
m_ui - > savePath - > blockSignals ( true ) ;
m_ui - > savePath - > clear ( ) ;
2022-02-08 06:03:48 +03:00
const Path savePath = session - > categorySavePath ( m_ui - > categoryComboBox - > currentText ( ) ) ;
2018-04-14 22:53:45 +03:00
m_ui - > savePath - > addItem ( savePath ) ;
2021-05-20 10:36:44 +03:00
m_ui - > downloadPath - > blockSignals ( true ) ;
m_ui - > downloadPath - > clear ( ) ;
2022-02-08 06:03:48 +03:00
const Path downloadPath = session - > categoryDownloadPath ( m_ui - > categoryComboBox - > currentText ( ) ) ;
2021-05-20 10:36:44 +03:00
m_ui - > downloadPath - > addItem ( downloadPath ) ;
m_ui - > groupBoxDownloadPath - > blockSignals ( true ) ;
m_ui - > groupBoxDownloadPath - > setChecked ( ! downloadPath . isEmpty ( ) ) ;
2016-02-09 11:56:48 +03:00
}
2022-01-30 19:39:56 +03:00
updateDiskSpaceLabel ( ) ;
2016-02-09 11:56:48 +03:00
}
2016-03-07 07:22:18 +03:00
2016-04-07 17:58:30 +03:00
void AddNewTorrentDialog : : doNotDeleteTorrentClicked ( bool checked )
{
m_torrentGuard - > setAutoRemove ( ! checked ) ;
}
2021-12-09 13:05:49 +03:00
void AddNewTorrentDialog : : renameSelectedFile ( )
{
if ( hasMetadata ( ) )
{
FileStorageAdaptor fileStorageAdaptor { m_torrentInfo , m_torrentParams . filePaths } ;
m_ui - > contentTreeView - > renameSelectedFile ( fileStorageAdaptor ) ;
}
}