35 #include <QHeaderView>
36 #include <QListWidgetItem>
40 #include <QStackedWidget>
67 #include "ui_propertieswidget.h"
80 setAutoFillBackground(
true);
85 m_ui->filesList->header()->setContextMenuPolicy(Qt::CustomContextMenu);
92 m_ui->filesList->setSortingEnabled(
true);
110 connect(
m_ui->filesList, &QAbstractItemView::clicked
111 ,
m_ui->filesList, qOverload<const QModelIndex &>(&QAbstractItemView::edit));
123 m_ui->tempProgressBarArea->setVisible(
false);
130 m_ui->tempAvailabilityBarArea->setVisible(
false);
150 m_tabBar->setContentsMargins(0, 5, 0, 5);
157 const auto *editWebSeedsHotkey =
new QShortcut(Qt::Key_F2,
m_ui->listWebSeeds,
nullptr,
nullptr, Qt::WidgetShortcut);
159 const auto *deleteWebSeedsHotkey =
new QShortcut(QKeySequence::Delete,
m_ui->listWebSeeds,
nullptr,
nullptr, Qt::WidgetShortcut);
163 const auto *renameFileHotkey =
new QShortcut(Qt::Key_F2,
m_ui->filesList,
nullptr,
nullptr, Qt::WidgetShortcut);
164 connect(renameFileHotkey, &QShortcut::activated,
this, [
this]() {
m_ui->filesList->renameSelectedFile(*
m_torrent); });
165 const auto *openFileHotkeyReturn =
new QShortcut(Qt::Key_Return,
m_ui->filesList,
nullptr,
nullptr, Qt::WidgetShortcut);
167 const auto *openFileHotkeyEnter =
new QShortcut(Qt::Key_Enter,
m_ui->filesList,
nullptr,
nullptr, Qt::WidgetShortcut);
182 QMenu *menu =
new QMenu(
this);
183 menu->setAttribute(Qt::WA_DeleteOnClose);
185 for (
int i = 0; i < TorrentContentModelItem::TreeItemColumns::NB_COL; ++i)
187 QAction *myAct = menu->addAction(
m_propListModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
188 myAct->setCheckable(
true);
189 myAct->setChecked(!
m_ui->filesList->isColumnHidden(i));
190 if (i == TorrentContentModelItem::TreeItemColumns::COL_NAME)
191 myAct->setEnabled(
false);
193 connect(myAct, &QAction::toggled,
this, [
this, i](
const bool checked)
195 m_ui->filesList->setColumnHidden(i, !checked);
197 if (!
m_ui->filesList->isColumnHidden(i) && (
m_ui->filesList->columnWidth(i) <= 5))
198 m_ui->filesList->resizeColumnToContents(i);
204 menu->popup(QCursor::pos());
209 m_ui->labelPiecesAvailability->setVisible(show);
211 m_ui->labelAverageAvailabilityVal->setVisible(show);
213 m_ui->lineBelowBars->setVisible(show);
218 m_ui->labelDownloadedPieces->setVisible(show);
220 m_ui->labelProgressVal->setVisible(show);
222 m_ui->lineBelowBars->setVisible(show);
229 const int tabBarHeight =
m_tabBar->geometry().height();
230 auto *hSplitter =
static_cast<QSplitter *
>(parentWidget());
231 m_ui->stackedProperties->setVisible(
false);
233 hSplitter->handle(1)->setVisible(
false);
234 hSplitter->handle(1)->setDisabled(
true);
236 hSplitter->setHandleWidth(0);
237 const QList<int> sizes {(hSplitter->geometry().height() - tabBarHeight), tabBarHeight};
238 hSplitter->setSizes(sizes);
239 setMaximumSize(maximumSize().width(), tabBarHeight);
246 m_ui->stackedProperties->setVisible(
true);
247 auto *hSplitter =
static_cast<QSplitter *
>(parentWidget());
250 hSplitter->handle(1)->setDisabled(
false);
251 hSplitter->handle(1)->setVisible(
true);
254 setMaximumSize(maximumSize().width(), QWIDGETSIZE_MAX);
262 qDebug(
"Clearing torrent properties");
263 m_ui->labelSavePathVal->clear();
264 m_ui->labelCreatedOnVal->clear();
265 m_ui->labelTotalPiecesVal->clear();
266 m_ui->labelInfohash1Val->clear();
267 m_ui->labelInfohash2Val->clear();
268 m_ui->labelCommentVal->clear();
269 m_ui->labelProgressVal->clear();
270 m_ui->labelAverageAvailabilityVal->clear();
271 m_ui->labelWastedVal->clear();
272 m_ui->labelUpTotalVal->clear();
273 m_ui->labelDlTotalVal->clear();
274 m_ui->labelUpLimitVal->clear();
275 m_ui->labelDlLimitVal->clear();
276 m_ui->labelElapsedVal->clear();
277 m_ui->labelConnectionsVal->clear();
278 m_ui->labelReannounceInVal->clear();
279 m_ui->labelShareRatioVal->clear();
280 m_ui->listWebSeeds->clear();
281 m_ui->labelETAVal->clear();
282 m_ui->labelSeedsVal->clear();
283 m_ui->labelPeersVal->clear();
284 m_ui->labelDlSpeedVal->clear();
285 m_ui->labelUpSpeedVal->clear();
286 m_ui->labelTotalSizeVal->clear();
287 m_ui->labelCompletedOnVal->clear();
288 m_ui->labelLastSeenCompleteVal->clear();
289 m_ui->labelCreatedByVal->clear();
290 m_ui->labelAddedOnVal->clear();
316 return m_ui->filesList;
375 if (sizesStr.size() == 2)
379 auto *hSplitter =
static_cast<QSplitter *
>(parentWidget());
395 auto *hSplitter =
static_cast<QSplitter *
>(parentWidget());
398 sizes = hSplitter->sizes();
402 if (sizes.size() == 2)
403 pref->
setPropSplitterSizes(QString::number(sizes.first()) +
',' + QString::number(sizes.last()));
422 switch (
m_ui->stackedProperties->currentIndex())
438 QString elapsedString;
440 elapsedString = tr(
"%1 (seeded for %2)",
"e.g. 4m39s (seeded for 3m10s)")
445 m_ui->labelElapsedVal->setText(elapsedString);
447 m_ui->labelConnectionsVal->setText(tr(
"%1 (%2 max)",
"%1 and %2 are numbers, e.g. 3 (10 max)")
460 m_ui->labelSeedsVal->setText(tr(
"%1 (%2 total)",
"%1 and %2 are numbers, e.g. 3 (10 total)")
464 m_ui->labelPeersVal->setText(tr(
"%1 (%2 total)",
"%1 and %2 are numbers, e.g. 3 (10 total)")
470 m_ui->labelDlSpeedVal->setText(tr(
"%1 (%2 avg.)",
"%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
475 m_ui->labelUpSpeedVal->setText(tr(
"%1 (%2 avg.)",
"%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)")
523 qDebug(
"Updating priorities in files tab");
524 m_ui->filesList->setUpdatesEnabled(
false);
528 if (!isContentInitialized)
540 QModelIndex currentIndex;
544 m_ui->filesList->setExpanded(currentIndex,
true);
559 m_ui->filesList->setUpdatesEnabled(
true);
571 m_ui->listWebSeeds->clear();
572 qDebug(
"Loading URL seeds");
575 for (
const QUrl &hcSeed : hcSeeds)
577 qDebug(
"Loading URL seed: %s", qUtf8Printable(hcSeed.toString()));
578 new QListWidgetItem(hcSeed.toString(),
m_ui->listWebSeeds);
596 QString folderPath {nameIndex.data().toString()};
597 for (QModelIndex modelIdx =
m_propListModel->
parent(nameIndex); modelIdx.isValid(); modelIdx = modelIdx.parent())
598 folderPath.prepend(modelIdx.data().toString() +
'/');
606 if (!index.isValid())
628 const QModelIndexList selectedRows =
m_ui->filesList->selectionModel()->selectedRows(0);
629 if (selectedRows.empty())
return;
631 QMenu *menu =
new QMenu(
this);
632 menu->setAttribute(Qt::WA_DeleteOnClose);
634 if (selectedRows.size() == 1)
636 const QModelIndex index = selectedRows[0];
639 ,
this, [
this, index]() {
openItem(index); });
643 ,
this, [
this]() {
m_ui->filesList->renameSelectedFile(*
m_torrent); });
644 menu->addSeparator();
651 const QModelIndexList selectedRows =
m_ui->filesList->selectionModel()->selectedRows(0);
652 for (
const QModelIndex &index : selectedRows)
655 ,
static_cast<int>(prio));
662 QMenu *subMenu = menu->addMenu(tr(
"Priority"));
680 subMenu->addSeparator();
681 subMenu->addAction(tr(
"By shown file order"), subMenu, [
this]()
687 const QModelIndexList selectedRows =
m_ui->filesList->selectionModel()->selectedRows(0);
689 const qsizetype priorityGroups = 3;
690 const auto priorityGroupSize = std::max<qsizetype>((selectedRows.length() / priorityGroups), 1);
692 for (qsizetype i = 0; i < selectedRows.length(); ++i)
695 switch (i / priorityGroupSize)
709 const QModelIndex &index = selectedRows[i];
711 ,
static_cast<int>(priority));
721 connect(
m_ui->filesList->model(), &QAbstractItemModel::modelAboutToBeReset
724 menu->setActiveAction(nullptr);
728 menu->popup(QCursor::pos());
735 const QModelIndexList rows =
m_ui->listWebSeeds->selectionModel()->selectedRows();
737 QMenu *menu =
new QMenu(
this);
738 menu->setAttribute(Qt::WA_DeleteOnClose);
746 menu->addSeparator();
753 menu->popup(QCursor::pos());
758 const QModelIndexList selectedIndexes =
m_ui->filesList->selectionModel()->selectedRows(0);
759 if (selectedIndexes.size() != 1)
791 const auto displayText = QString::fromLatin1(
"<center><b>%1</b><p>%2</p></center>")
792 .arg(tr(
"Speed graphs are disabled"), tr(
"You can enable it in Advanced Options"));
793 auto *label =
new QLabel(displayText,
this);
794 label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
806 tr(
"New URL seed:"), QLineEdit::Normal,
807 QLatin1String(
"http://www."), &ok);
809 qDebug(
"Adding %s web seed", qUtf8Printable(urlSeed));
810 if (!
m_ui->listWebSeeds->findItems(urlSeed, Qt::MatchFixedString).empty())
812 QMessageBox::warning(
this,
"qBittorrent",
813 tr(
"This URL seed is already in the list."),
825 const QList<QListWidgetItem *> selectedItems =
m_ui->listWebSeeds->selectedItems();
826 if (selectedItems.isEmpty())
return;
828 QVector<QUrl> urlSeeds;
829 urlSeeds.reserve(selectedItems.size());
831 for (
const QListWidgetItem *item : selectedItems)
832 urlSeeds << item->text();
841 const QList<QListWidgetItem *> selectedItems =
m_ui->listWebSeeds->selectedItems();
842 if (selectedItems.isEmpty())
return;
844 QStringList urlsToCopy;
845 for (
const QListWidgetItem *item : selectedItems)
846 urlsToCopy << item->text();
848 QApplication::clipboard()->setText(urlsToCopy.join(
'\n'));
853 const QList<QListWidgetItem *> selectedItems =
m_ui->listWebSeeds->selectedItems();
854 if (selectedItems.size() != 1)
return;
856 const QListWidgetItem *selectedItem = selectedItems.last();
857 const QString oldSeed = selectedItem->text();
860 tr(
"Web seed URL:"), QLineEdit::Normal,
864 if (!
m_ui->listWebSeeds->findItems(newSeed, Qt::MatchFixedString).empty())
866 QMessageBox::warning(
this, QLatin1String(
"qBittorrent"),
867 tr(
"This URL seed is already in the list."),
891 m_propListModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption));
892 if (filter.isEmpty())
894 m_ui->filesList->collapseAll();
899 m_ui->filesList->expandAll();
static QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode=QLineEdit::Normal, const QString &text={}, bool *ok=nullptr, bool excludeExtension=false, Qt::InputMethodHints inputMethodHints=Qt::ImhNone)
virtual QString filePath(int index) const =0
static Session * instance()
void torrentSavePathChanged(Torrent *torrent)
void torrentMetadataReceived(Torrent *torrent)
virtual qlonglong totalSize() const =0
virtual qreal distributedCopies() const =0
virtual int uploadPayloadRate() const =0
virtual QVector< int > pieceAvailability() const =0
virtual int seedsCount() const =0
virtual int downloadLimit() const =0
virtual void flushCache() const =0
virtual qlonglong nextAnnounce() const =0
virtual QVector< DownloadPriority > filePriorities() const =0
virtual bool isChecking() const =0
virtual QVector< qreal > filesProgress() const =0
virtual qlonglong totalUpload() const =0
virtual int piecesHave() const =0
virtual QDateTime creationDate() const =0
virtual QString comment() const =0
virtual qlonglong pieceLength() const =0
virtual qlonglong activeTime() const =0
virtual qlonglong totalPayloadDownload() const =0
virtual InfoHash infoHash() const =0
virtual void prioritizeFiles(const QVector< DownloadPriority > &priorities)=0
virtual qlonglong finishedTime() const =0
virtual int piecesCount() const =0
virtual int uploadLimit() const =0
virtual int connectionsLimit() const =0
virtual int totalSeedsCount() const =0
virtual bool isQueued() const =0
virtual qlonglong totalDownload() const =0
virtual QString creator() const =0
virtual QString savePath() const =0
virtual qreal realRatio() const =0
virtual void addUrlSeeds(const QVector< QUrl > &urlSeeds)=0
virtual QString actualStorageLocation() const =0
virtual QBitArray downloadingPieces() const =0
virtual bool isPaused() const =0
virtual QDateTime addedTime() const =0
virtual qlonglong totalPayloadUpload() const =0
virtual QBitArray pieces() const =0
virtual QVector< qreal > availableFileFractions() const =0
fraction of file pieces that are available at least from one peer
virtual int connectionsCount() const =0
virtual QDateTime completedTime() const =0
virtual QVector< QUrl > urlSeeds() const =0
virtual qlonglong wastedSize() const =0
virtual QDateTime lastSeenComplete() const =0
virtual int leechsCount() const =0
virtual qreal progress() const =0
virtual bool isSeed() const =0
virtual qlonglong eta() const =0
static const qreal MAX_RATIO
virtual void removeUrlSeeds(const QVector< QUrl > &urlSeeds)=0
virtual int downloadPayloadRate() const =0
virtual int totalLeechersCount() const =0
virtual bool hasMetadata() const =0
void setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces)
void setAvailability(const QVector< int > &avail)
void setTorrent(const BitTorrent::Torrent *torrent)
static Preferences * instance()
void setPropCurTab(int tab)
int getPropCurTab() const
QString getPropSplitterSizes() const
bool getPropVisible() const
void setPropVisible(bool visible)
void setPropFileListState(const QByteArray &state)
void setPropSplitterSizes(const QString &sizes)
QByteArray getPropFileListState() const
void filteredFilesChanged() const
void setCurrentIndex(int index)
void tabChanged(int index)
void visibilityToggled(bool visible)
void filteredFilesChanged()
TorrentContentModelItem::ItemType itemType(const QModelIndex &index) const
TorrentContentModel * model() const
int getFileIndex(const QModelIndex &index) const
QModelIndex parent(const QModelIndex &child) const override
void updateFilesPriorities(const QVector< BitTorrent::DownloadPriority > &fprio)
QVector< BitTorrent::DownloadPriority > getFilePriorities() const
void updateFilesProgress(const QVector< qreal > &fp)
void setupModelData(const BitTorrent::AbstractFileStorage &info)
void updateFilesAvailability(const QVector< qreal > &fa)
static UIThemeManager * instance()
QIcon getIcon(const QString &iconId, const QString &fallback={}) const
void openFiles(const QSet< QString > &pathsList)
QString expandPath(const QString &path)
QString toNativePath(const QString &path)
T scaledSize(const QWidget *widget, const T &size)
QSize smallIconSize(const QWidget *widget=nullptr)
void openFolderSelect(const QString &absolutePath)
void openPath(const QString &absolutePath)
QString parseHtmlLinks(const QString &rawText)
QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap=-1)
QString friendlyUnit(qint64 bytes, bool isSpeed=false)
QString fromDouble(double n, int precision)
QString wildcardToRegexPattern(const QString &pattern)
QString toString(const lt::socket_type_t socketType)