mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
- Initiated work on torrent labeling/categorization (functional but not perfect yet
This commit is contained in:
parent
21eb26a374
commit
ed803fb994
10 changed files with 390 additions and 96 deletions
|
@ -43,6 +43,7 @@
|
|||
#include <QTimer>
|
||||
#include <QSettings>
|
||||
#include <QClipboard>
|
||||
#include <QInputDialog>
|
||||
#include <QColor>
|
||||
#include <QUrl>
|
||||
#include <QMenu>
|
||||
|
@ -58,7 +59,7 @@ TransferListWidget::TransferListWidget(QWidget *parent, GUI *main_window, Bittor
|
|||
setItemDelegate(listDelegate);
|
||||
|
||||
// Create transfer list model
|
||||
listModel = new QStandardItemModel(0,12);
|
||||
listModel = new QStandardItemModel(0,13);
|
||||
listModel->setHeaderData(TR_NAME, Qt::Horizontal, tr("Name", "i.e: torrent name"));
|
||||
listModel->setHeaderData(TR_PRIORITY, Qt::Horizontal, "#");
|
||||
listModel->horizontalHeaderItem(TR_PRIORITY)->setTextAlignment(Qt::AlignRight);
|
||||
|
@ -78,15 +79,23 @@ TransferListWidget::TransferListWidget(QWidget *parent, GUI *main_window, Bittor
|
|||
listModel->setHeaderData(TR_RATIO, Qt::Horizontal, tr("Ratio", "Share ratio"));
|
||||
listModel->horizontalHeaderItem(TR_RATIO)->setTextAlignment(Qt::AlignRight);
|
||||
listModel->setHeaderData(TR_ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left"));
|
||||
listModel->setHeaderData(TR_LABEL, Qt::Horizontal, tr("Label"));
|
||||
|
||||
// Set Sort/Filter proxy
|
||||
labelFilterModel = new QSortFilterProxyModel();
|
||||
labelFilterModel->setDynamicSortFilter(true);
|
||||
labelFilterModel->setSourceModel(listModel);
|
||||
labelFilterModel->setFilterKeyColumn(TR_LABEL);
|
||||
labelFilterModel->setFilterRole(Qt::DisplayRole);
|
||||
|
||||
proxyModel = new QSortFilterProxyModel();
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
proxyModel->setSourceModel(listModel);
|
||||
proxyModel->setSourceModel(labelFilterModel);
|
||||
proxyModel->setFilterKeyColumn(TR_STATUS);
|
||||
proxyModel->setFilterRole(Qt::DisplayRole);
|
||||
setModel(proxyModel);
|
||||
|
||||
|
||||
// Visual settings
|
||||
setRootIsDecorated(false);
|
||||
setAllColumnsShowFocus(true);
|
||||
|
@ -96,6 +105,7 @@ TransferListWidget::TransferListWidget(QWidget *parent, GUI *main_window, Bittor
|
|||
setAutoScroll(true);
|
||||
|
||||
hideColumn(TR_PRIORITY);
|
||||
//hideColumn(TR_LABEL);
|
||||
hideColumn(TR_HASH);
|
||||
loadHiddenColumns();
|
||||
// Load last columns width for transfer list
|
||||
|
@ -132,6 +142,7 @@ TransferListWidget::~TransferListWidget() {
|
|||
saveHiddenColumns();
|
||||
// Clean up
|
||||
delete refreshTimer;
|
||||
delete labelFilterModel;
|
||||
delete proxyModel;
|
||||
delete listModel;
|
||||
delete listDelegate;
|
||||
|
@ -151,6 +162,9 @@ void TransferListWidget::addTorrent(QTorrentHandle& h) {
|
|||
listModel->setData(listModel->index(row, TR_ETA), QVariant((qlonglong)-1));
|
||||
listModel->setData(listModel->index(row, TR_SEEDS), QVariant((double)0.0));
|
||||
listModel->setData(listModel->index(row, TR_PEERS), QVariant((double)0.0));
|
||||
QString label = TorrentPersistentData::getLabel(h.hash());
|
||||
emit newLabel(label);
|
||||
listModel->setData(listModel->index(row, TR_LABEL), QVariant(label));
|
||||
if(BTSession->isQueueingEnabled())
|
||||
listModel->setData(listModel->index(row, TR_PRIORITY), QVariant((int)h.queue_position()));
|
||||
listModel->setData(listModel->index(row, TR_HASH), QVariant(h.hash()));
|
||||
|
@ -461,8 +475,18 @@ QString TransferListWidget::getHashFromRow(int row) const {
|
|||
return listModel->data(listModel->index(row, TR_HASH)).toString();
|
||||
}
|
||||
|
||||
QModelIndex TransferListWidget::mapToSource(QModelIndex index) const {
|
||||
return labelFilterModel->mapToSource(proxyModel->mapToSource(index));
|
||||
}
|
||||
|
||||
QStringList TransferListWidget::getCustomLabels() const {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.beginGroup(QString::fromUtf8("TransferListFilters"));
|
||||
return settings.value("customLabels", QStringList()).toStringList();
|
||||
}
|
||||
|
||||
void TransferListWidget::torrentDoubleClicked(QModelIndex index) {
|
||||
int row = proxyModel->mapToSource(index).row();
|
||||
int row = mapToSource(index).row();
|
||||
QString hash = getHashFromRow(row);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) return;
|
||||
|
@ -494,7 +518,7 @@ void TransferListWidget::startSelectedTorrents() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
int row = proxyModel->mapToSource(index).row();
|
||||
int row = mapToSource(index).row();
|
||||
QString hash = getHashFromRow(row);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.is_paused()) {
|
||||
|
@ -521,7 +545,7 @@ void TransferListWidget::pauseSelectedTorrents() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
int row = proxyModel->mapToSource(index).row();
|
||||
int row = mapToSource(index).row();
|
||||
QString hash = getHashFromRow(row);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && !h.is_paused()) {
|
||||
|
@ -553,7 +577,7 @@ void TransferListWidget::deleteSelectedTorrents() {
|
|||
QStringList hashes;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
hashes << getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
hashes << getHashFromRow(mapToSource(index).row());
|
||||
}
|
||||
foreach(const QString &hash, hashes) {
|
||||
deleteTorrent(getRowFromHash(hash), false);
|
||||
|
@ -568,7 +592,7 @@ void TransferListWidget::deleteSelectedTorrents() {
|
|||
void TransferListWidget::increasePrioSelectedTorrents() {
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid() && !h.is_seed()) {
|
||||
h.queue_position_up();
|
||||
}
|
||||
|
@ -580,7 +604,7 @@ void TransferListWidget::increasePrioSelectedTorrents() {
|
|||
void TransferListWidget::decreasePrioSelectedTorrents() {
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid() && !h.is_seed()) {
|
||||
h.queue_position_down();
|
||||
}
|
||||
|
@ -591,7 +615,7 @@ void TransferListWidget::decreasePrioSelectedTorrents() {
|
|||
void TransferListWidget::buySelectedTorrents() const {
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid())
|
||||
QDesktopServices::openUrl("http://match.sharemonkey.com/?info_hash="+h.hash()+"&n="+h.name()+"&cid=33");
|
||||
}
|
||||
|
@ -601,7 +625,7 @@ void TransferListWidget::copySelectedMagnetURIs() const {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
QStringList magnet_uris;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid() && h.has_metadata())
|
||||
magnet_uris << misc::toQString(make_magnet_uri(h.get_torrent_info()));
|
||||
}
|
||||
|
@ -616,7 +640,7 @@ void TransferListWidget::openSelectedTorrentsFolder() const {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
QStringList pathsList;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid()) {
|
||||
QString savePath = h.save_path();
|
||||
if(!pathsList.contains(savePath)) {
|
||||
|
@ -631,7 +655,7 @@ void TransferListWidget::previewSelectedTorrents() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
QStringList pathsList;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(proxyModel->mapToSource(index).row()));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(getHashFromRow(mapToSource(index).row()));
|
||||
if(h.is_valid() && h.has_metadata()) {
|
||||
new previewSelect(this, h);
|
||||
}
|
||||
|
@ -646,7 +670,7 @@ void TransferListWidget::setDlLimitSelectedTorrents() {
|
|||
bool all_same_limit = true;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && !h.is_seed()) {
|
||||
selected_torrents << h;
|
||||
|
@ -682,7 +706,7 @@ void TransferListWidget::setUpLimitSelectedTorrents() {
|
|||
bool all_same_limit = true;
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid()) {
|
||||
selected_torrents << h;
|
||||
|
@ -713,7 +737,7 @@ void TransferListWidget::setUpLimitSelectedTorrents() {
|
|||
void TransferListWidget::recheckSelectedTorrents() {
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata())
|
||||
h.force_recheck();
|
||||
|
@ -787,7 +811,7 @@ void TransferListWidget::toggleSelectedTorrentsSuperSeeding() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata()) {
|
||||
h.super_seeding(!h.super_seeding());
|
||||
|
@ -800,7 +824,7 @@ void TransferListWidget::toggleSelectedTorrentsSequentialDownload() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata()) {
|
||||
h.set_sequential_download(!h.is_sequential_download());
|
||||
|
@ -812,7 +836,7 @@ void TransferListWidget::toggleSelectedFirstLastPiecePrio() {
|
|||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file hash
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid() && h.has_metadata()) {
|
||||
h.prioritize_first_last_piece(!h.first_last_piece_first());
|
||||
|
@ -820,6 +844,33 @@ void TransferListWidget::toggleSelectedFirstLastPiecePrio() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::askNewLabelForSelection() {
|
||||
// Ask for label
|
||||
bool ok;
|
||||
QString label = QInputDialog::getText(this, tr("New Label"), tr("Label:"), QLineEdit::Normal, "", &ok);
|
||||
if (ok && !label.isEmpty()) {
|
||||
emit newLabel(label);
|
||||
// Assign label to selection
|
||||
setSelectionLabel(label);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setSelectionLabel(QString label) {
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
proxyModel->setData(proxyModel->index(index.row(), TR_LABEL), QVariant(label));
|
||||
TorrentPersistentData::saveLabel(hash, label);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::removeLabelFromRows(QString label) {
|
||||
for(int i=0; i<listModel->rowCount(); ++i) {
|
||||
if(label == listModel->data(listModel->index(i, TR_LABEL), Qt::DisplayRole))
|
||||
listModel->setData(listModel->index(i, TR_LABEL), "", Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::displayListMenu(const QPoint&) {
|
||||
// Create actions
|
||||
QAction actionStart(QIcon(QString::fromUtf8(":/Icons/skin/play.png")), tr("Start"), 0);
|
||||
|
@ -871,7 +922,7 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
qDebug("Displaying menu");
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
// Get the file name
|
||||
QString hash = getHashFromRow(proxyModel->mapToSource(index).row());
|
||||
QString hash = getHashFromRow(mapToSource(index).row());
|
||||
// Get handle and pause the torrent
|
||||
h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) continue;
|
||||
|
@ -926,6 +977,17 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
listMenu.addSeparator();
|
||||
listMenu.addAction(&actionDelete);
|
||||
listMenu.addSeparator();
|
||||
// Label Menu
|
||||
QStringList customLabels = getCustomLabels();
|
||||
QList<QAction*> labelActions;
|
||||
QMenu *labelMenu = listMenu.addMenu(QIcon(":/Icons/oxygen/feed-subscribe.png"), "Label");
|
||||
labelActions << labelMenu->addAction(tr("New..."));
|
||||
labelActions << labelMenu->addAction(tr("Reset"));
|
||||
labelMenu->addSeparator();
|
||||
foreach(const QString &label, customLabels) {
|
||||
labelActions << labelMenu->addAction(label);
|
||||
}
|
||||
listMenu.addSeparator();
|
||||
if(one_not_seed)
|
||||
listMenu.addAction(&actionSet_download_limit);
|
||||
listMenu.addAction(&actionSet_upload_limit);
|
||||
|
@ -988,7 +1050,25 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
listMenu.addAction(&actionCopy_magnet_link);
|
||||
listMenu.addAction(&actionBuy_it);
|
||||
// Call menu
|
||||
listMenu.exec(QCursor::pos());
|
||||
QAction *act = 0;
|
||||
act = listMenu.exec(QCursor::pos());
|
||||
if(act) {
|
||||
// Parse label actions only (others have slots assigned)
|
||||
int i = labelActions.indexOf(act);
|
||||
if(i >= 0) {
|
||||
// Label action
|
||||
if(i == 0) {
|
||||
// New Label
|
||||
askNewLabelForSelection();
|
||||
} else {
|
||||
QString label = "";
|
||||
if(i > 1)
|
||||
label = customLabels.at(i-2);
|
||||
// Update Label
|
||||
setSelectionLabel(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save columns width in a file to remember them
|
||||
|
@ -1092,7 +1172,7 @@ void TransferListWidget::loadLastSortedColumn() {
|
|||
void TransferListWidget::currentChanged(const QModelIndex& current, const QModelIndex&) {
|
||||
QTorrentHandle h;
|
||||
if(current.isValid()) {
|
||||
int row = proxyModel->mapToSource(current).row();
|
||||
int row = mapToSource(current).row();
|
||||
h = BTSession->getTorrentHandle(getHashFromRow(row));
|
||||
// Scroll Fix
|
||||
scrollTo(current);
|
||||
|
@ -1100,7 +1180,20 @@ void TransferListWidget::currentChanged(const QModelIndex& current, const QModel
|
|||
emit currentTorrentChanged(h);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyFilter(int f) {
|
||||
void TransferListWidget::applyLabelFilter(QString label) {
|
||||
if(label == "all") {
|
||||
labelFilterModel->setFilterRegExp(QRegExp());
|
||||
return;
|
||||
}
|
||||
if(label == "none") {
|
||||
labelFilterModel->setFilterRegExp(QRegExp("^$"));
|
||||
return;
|
||||
}
|
||||
qDebug("Applying Label filter: %s", label.toLocal8Bit().data());
|
||||
labelFilterModel->setFilterRegExp(QRegExp("^"+label+"$", Qt::CaseSensitive));
|
||||
}
|
||||
|
||||
void TransferListWidget::applyStatusFilter(int f) {
|
||||
switch(f) {
|
||||
case FILTER_DOWNLOADING:
|
||||
proxyModel->setFilterRegExp(QRegExp(QString::number(STATE_DOWNLOADING)+"|"+QString::number(STATE_STALLED_DL)+"|"+
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue