diff --git a/src/Icons/oxygen/feed-subscribe.png b/src/Icons/oxygen/feed-subscribe.png
new file mode 100644
index 000000000..6acc38b31
Binary files /dev/null and b/src/Icons/oxygen/feed-subscribe.png differ
diff --git a/src/bittorrent.cpp b/src/bittorrent.cpp
index b50f2ba84..e4d93b715 100644
--- a/src/bittorrent.cpp
+++ b/src/bittorrent.cpp
@@ -198,7 +198,7 @@ void Bittorrent::setUploadLimit(QString hash, long val) {
void Bittorrent::handleDownloadFailure(QString url, QString reason) {
emit downloadFromUrlFailure(url, reason);
// Clean up
- QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
+ QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
int index = url_skippingDlg.indexOf(qurl);
if(index >= 0)
url_skippingDlg.removeAt(index);
@@ -910,6 +910,10 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
}
// Save persistent data for new torrent
TorrentPersistentData::saveTorrentPersistentData(h);
+ // Save Label
+ if(TorrentTempData::hasTempData(hash)) {
+ TorrentPersistentData::saveLabel(hash, TorrentTempData::getLabel(hash));
+ }
// Save save_path
if(!defaultTempPath.isEmpty()) {
qDebug("addTorrent: Saving save_path in persistent data: %s", savePath.toLocal8Bit().data());
diff --git a/src/icons.qrc b/src/icons.qrc
index 6cadc6a6f..98a761a33 100644
--- a/src/icons.qrc
+++ b/src/icons.qrc
@@ -168,6 +168,7 @@
Icons/oxygen/urlseed.png
Icons/oxygen/edit-cut.png
Icons/oxygen/unsubscribe.png
+ Icons/oxygen/feed-subscribe.png
Icons/oxygen/subscribe16.png
\ No newline at end of file
diff --git a/src/torrentadditiondlg.h b/src/torrentadditiondlg.h
index 067482918..6fb1b4af3 100644
--- a/src/torrentadditiondlg.h
+++ b/src/torrentadditiondlg.h
@@ -126,21 +126,21 @@ public:
}
}
-// Screen center point
-QPoint screenCenter() const{
- int scrn = 0;
- QWidget *w = this->topLevelWidget();
+ // Screen center point
+ QPoint screenCenter() const{
+ int scrn = 0;
+ QWidget *w = this->topLevelWidget();
- if(w)
- scrn = QApplication::desktop()->screenNumber(w);
- else if(QApplication::desktop()->isVirtualDesktop())
- scrn = QApplication::desktop()->screenNumber(QCursor::pos());
- else
- scrn = QApplication::desktop()->screenNumber(this);
+ if(w)
+ scrn = QApplication::desktop()->screenNumber(w);
+ else if(QApplication::desktop()->isVirtualDesktop())
+ scrn = QApplication::desktop()->screenNumber(QCursor::pos());
+ else
+ scrn = QApplication::desktop()->screenNumber(this);
- QRect desk(QApplication::desktop()->availableGeometry(scrn));
- return QPoint((desk.width() - this->frameGeometry().width()) / 2, (desk.height() - this->frameGeometry().height()) / 2);
-}
+ QRect desk(QApplication::desktop()->availableGeometry(scrn));
+ return QPoint((desk.width() - this->frameGeometry().width()) / 2, (desk.height() - this->frameGeometry().height()) / 2);
+ }
void saveSettings() {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
@@ -195,6 +195,14 @@ QPoint screenCenter() const{
//torrentContentList->expandAll();
connect(savePathTxt, SIGNAL(textChanged(QString)), this, SLOT(updateDiskSpaceLabels()));
updateDiskSpaceLabels();
+ // Load custom labels
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
+ settings.beginGroup(QString::fromUtf8("TransferListFilters"));
+ QStringList customLabels = settings.value("customLabels", QStringList()).toStringList();
+ foreach(const QString& label, customLabels) {
+ comboLabel->addItem(label);
+ }
+ // Show the dialog
show();
}
@@ -319,6 +327,7 @@ public slots:
}
// Save savepath
TorrentTempData::setSavePath(hash, savePath.path());
+ TorrentTempData::setLabel(hash, comboLabel->currentText().trimmed());
// Save last dir to remember it
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("LastDirTorrentAdd"), savePathTxt->text());
diff --git a/src/torrentpersistentdata.h b/src/torrentpersistentdata.h
index 97401a531..48ec93424 100644
--- a/src/torrentpersistentdata.h
+++ b/src/torrentpersistentdata.h
@@ -87,6 +87,15 @@ public:
settings.setValue("torrents-tmp", all_data);
}
+ static void setLabel(QString hash, QString label) {
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
+ QHash all_data = settings.value("torrents-tmp", QHash()).toHash();
+ QHash data = all_data[hash].toHash();
+ data["label"] = label;
+ all_data[hash] = data;
+ settings.setValue("torrents-tmp", all_data);
+ }
+
static void setSequential(QString hash, bool sequential) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash all_data = settings.value("torrents-tmp", QHash()).toHash();
@@ -136,6 +145,15 @@ public:
return QString::null;
}
+ static QString getLabel(QString hash) {
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
+ QHash all_data = settings.value("torrents-tmp", QHash()).toHash();
+ QHash data = all_data[hash].toHash();
+ if(data.contains("label"))
+ return data["label"].toString();
+ return "";
+ }
+
static std::vector getFilesPriority(QString hash) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash all_data = settings.value("torrents-tmp", QHash()).toHash();
@@ -211,6 +229,16 @@ public:
qDebug("TorrentPersistentData: Saving save_path: %s, hash: %s", save_path.toLocal8Bit().data(), hash.toLocal8Bit().data());
}
+ static void saveLabel(QString hash, QString label) {
+ Q_ASSERT(!hash.isEmpty());
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
+ QHash all_data = settings.value("torrents", QHash()).toHash();
+ QHash data = all_data[hash].toHash();
+ data["label"] = label;
+ all_data[hash] = data;
+ settings.setValue("torrents", all_data);
+ }
+
static void savePriority(QTorrentHandle h) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash all_data = settings.value("torrents", QHash()).toHash();
@@ -238,6 +266,13 @@ public:
return data["save_path"].toString();
}
+ static QString getLabel(QString hash) {
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
+ QHash all_data = settings.value("torrents", QHash()).toHash();
+ QHash data = all_data[hash].toHash();
+ return data.value("label", "").toString();
+ }
+
static int getPriority(QString hash) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash all_data = settings.value("torrents", QHash()).toHash();
diff --git a/src/transferlistdelegate.h b/src/transferlistdelegate.h
index f89a6707a..84eb9be8c 100644
--- a/src/transferlistdelegate.h
+++ b/src/transferlistdelegate.h
@@ -42,7 +42,7 @@
// Defines for download list list columns
enum TorrentState {STATE_DOWNLOADING, STATE_STALLED_DL, STATE_STALLED_UP, STATE_SEEDING, STATE_PAUSED_DL, STATE_PAUSED_UP, STATE_QUEUED_DL, STATE_QUEUED_UP, STATE_CHECKING_UP, STATE_CHECKING_DL, STATE_INVALID};
-enum Column {TR_NAME, TR_PRIORITY, TR_SIZE, TR_PROGRESS, TR_STATUS, TR_SEEDS, TR_PEERS, TR_DLSPEED, TR_UPSPEED, TR_ETA, TR_RATIO, TR_HASH};
+enum Column {TR_NAME, TR_PRIORITY, TR_SIZE, TR_PROGRESS, TR_STATUS, TR_SEEDS, TR_PEERS, TR_DLSPEED, TR_UPSPEED, TR_ETA, TR_RATIO, TR_LABEL, TR_HASH};
class TransferListDelegate: public QItemDelegate {
Q_OBJECT
diff --git a/src/transferlistfilterswidget.h b/src/transferlistfilterswidget.h
index 026c6100a..c2bcf8f89 100644
--- a/src/transferlistfilterswidget.h
+++ b/src/transferlistfilterswidget.h
@@ -33,67 +33,170 @@
#include
#include
+#include
#include
#include
+#include
+#include
+#include
#include "transferlistwidget.h"
-class TransferListFiltersWidget: public QListWidget {
+class TransferListFiltersWidget: public QFrame {
Q_OBJECT
private:
+ QStringList customLabels;
+ QListWidget* statusFilters;
+ QListWidget* labelFilters;
+ QVBoxLayout* vLayout;
TransferListWidget *transferList;
public:
- TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList): QListWidget(parent), transferList(transferList) {
- // Add filters
- QListWidgetItem *all = new QListWidgetItem(this);
+ TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList): QFrame(parent), transferList(transferList) {
+ // Construct lists
+ vLayout = new QVBoxLayout();
+ statusFilters = new QListWidget();
+ vLayout->addWidget(statusFilters);
+ labelFilters = new QListWidget();
+ vLayout->addWidget(labelFilters);
+ setLayout(vLayout);
+ // Limit status filters list height
+ statusFilters->setFixedHeight(100);
+ setContentsMargins(0,0,0,0);
+ vLayout->setSpacing(2);
+ // Add status filters
+ QListWidgetItem *all = new QListWidgetItem(statusFilters);
all->setData(Qt::DisplayRole, tr("All") + " (0)");
all->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filterall.png"));
- QListWidgetItem *downloading = new QListWidgetItem(this);
+ QListWidgetItem *downloading = new QListWidgetItem(statusFilters);
downloading->setData(Qt::DisplayRole, tr("Downloading") + " (0)");
downloading->setData(Qt::DecorationRole, QIcon(":/Icons/skin/downloading.png"));
- QListWidgetItem *completed = new QListWidgetItem(this);
+ QListWidgetItem *completed = new QListWidgetItem(statusFilters);
completed->setData(Qt::DisplayRole, tr("Completed") + " (0)");
completed->setData(Qt::DecorationRole, QIcon(":/Icons/skin/uploading.png"));
- QListWidgetItem *active = new QListWidgetItem(this);
+ QListWidgetItem *active = new QListWidgetItem(statusFilters);
active->setData(Qt::DisplayRole, tr("Active") + " (0)");
active->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filteractive.png"));
- QListWidgetItem *inactive = new QListWidgetItem(this);
+ QListWidgetItem *inactive = new QListWidgetItem(statusFilters);
inactive->setData(Qt::DisplayRole, tr("Inactive") + " (0)");
inactive->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filterinactive.png"));
// SIGNAL/SLOT
- connect(this, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyFilter(int)));
+ connect(statusFilters, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyStatusFilter(int)));
connect(transferList, SIGNAL(torrentStatusUpdate(uint,uint,uint,uint)), this, SLOT(updateTorrentNumbers(uint, uint, uint, uint)));
+ connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int)));
+ connect(transferList, SIGNAL(newLabel(QString)), this, SLOT(addLabel(QString)));
// Load settings
loadSettings();
+
+ // Add Label filters
+ QListWidgetItem *allLabels = new QListWidgetItem(labelFilters);
+ allLabels->setData(Qt::DisplayRole, tr("All labels") + " (0)");
+ QListWidgetItem *noLabel = new QListWidgetItem(labelFilters);
+ noLabel->setData(Qt::DisplayRole, tr("No label") + " (0)");
+ foreach(const QString& label, customLabels) {
+ QListWidgetItem *newLabel = new QListWidgetItem(labelFilters);
+ newLabel->setText(label + " (0)");
+ }
+ labelFilters->selectionModel()->select(labelFilters->model()->index(0,0), QItemSelectionModel::Select);
+ // Label menu
+ labelFilters->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(labelFilters, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showLabelMenu(QPoint)));
}
~TransferListFiltersWidget() {
saveSettings();
+ delete statusFilters;
+ delete labelFilters;
+ delete vLayout;
}
void saveSettings() const {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.beginGroup(QString::fromUtf8("TransferListFilters"));
- settings.setValue("selectedFilterIndex", QVariant(currentRow()));
+ settings.setValue("selectedFilterIndex", QVariant(statusFilters->currentRow()));
+ settings.setValue("customLabels", customLabels);
+ }
+
+ void saveCustomLabels() const {
+ QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
+ settings.beginGroup(QString::fromUtf8("TransferListFilters"));
+ settings.setValue("customLabels", customLabels);
}
void loadSettings() {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.beginGroup(QString::fromUtf8("TransferListFilters"));
- setCurrentRow(settings.value("selectedFilterIndex", 0).toInt());
+ statusFilters->setCurrentRow(settings.value("selectedFilterIndex", 0).toInt());
+ customLabels = settings.value("customLabels", QStringList()).toStringList();
}
protected slots:
void updateTorrentNumbers(uint nb_downloading, uint nb_seeding, uint nb_active, uint nb_inactive) {
- item(FILTER_ALL)->setData(Qt::DisplayRole, tr("All")+" ("+QString::number(nb_active+nb_inactive)+")");
- item(FILTER_DOWNLOADING)->setData(Qt::DisplayRole, tr("Downloading")+" ("+QString::number(nb_downloading)+")");
- item(FILTER_COMPLETED)->setData(Qt::DisplayRole, tr("Completed")+" ("+QString::number(nb_seeding)+")");
- item(FILTER_ACTIVE)->setData(Qt::DisplayRole, tr("Active")+" ("+QString::number(nb_active)+")");
- item(FILTER_INACTIVE)->setData(Qt::DisplayRole, tr("Inactive")+" ("+QString::number(nb_inactive)+")");
+ statusFilters->item(FILTER_ALL)->setData(Qt::DisplayRole, tr("All")+" ("+QString::number(nb_active+nb_inactive)+")");
+ statusFilters->item(FILTER_DOWNLOADING)->setData(Qt::DisplayRole, tr("Downloading")+" ("+QString::number(nb_downloading)+")");
+ statusFilters->item(FILTER_COMPLETED)->setData(Qt::DisplayRole, tr("Completed")+" ("+QString::number(nb_seeding)+")");
+ statusFilters->item(FILTER_ACTIVE)->setData(Qt::DisplayRole, tr("Active")+" ("+QString::number(nb_active)+")");
+ statusFilters->item(FILTER_INACTIVE)->setData(Qt::DisplayRole, tr("Inactive")+" ("+QString::number(nb_inactive)+")");
+ }
+
+ void addLabel(QString label) {
+ if(label.trimmed().isEmpty()) return;
+ if(customLabels.contains(label)) return;
+ QListWidgetItem *newLabel = new QListWidgetItem(labelFilters);
+ newLabel->setText(label + " (0)");
+ customLabels << label;
+ saveCustomLabels();
+ }
+
+ void showLabelMenu(QPoint) {
+ QMenu labelMenu(labelFilters);
+ QAction *removeAct = 0;
+ if(!labelFilters->selectedItems().empty() && labelFilters->row(labelFilters->selectedItems().first()) > 1)
+ removeAct = labelMenu.addAction(QIcon(":/Icons/oxygen/list-remove.png"), tr("Remove label"));
+ QAction *addAct = labelMenu.addAction(QIcon(":/Icons/oxygen/list-add.png"), tr("Add label"));
+ QAction *act = 0;
+ act = labelMenu.exec(QCursor::pos());
+ if(act) {
+ if(act == removeAct) {
+ removeSelectedLabel();
+ return;
+ }
+ if(act == addAct) {
+ bool ok;
+ QString label = QInputDialog::getText(this, tr("New Label"), tr("Label:"), QLineEdit::Normal, "", &ok);
+ if (ok && !label.isEmpty()) {
+ addLabel(label);
+ }
+ return;
+ }
+ }
+ }
+
+ void removeSelectedLabel() {
+ int row = labelFilters->row(labelFilters->selectedItems().first());
+ Q_ASSERT(row > 1);
+ QString label = customLabels.takeAt(row - 2);
+ labelFilters->removeItemWidget(labelFilters->selectedItems().first());
+ transferList->removeLabelFromRows(label);
+ // Select first label
+ labelFilters->selectionModel()->select(labelFilters->model()->index(0,0), QItemSelectionModel::Select);
+ applyLabelFilter(0);
+ }
+
+ void applyLabelFilter(int row) {
+ switch(row) {
+ case 0:
+ transferList->applyLabelFilter("all");
+ break;
+ case 1:
+ transferList->applyLabelFilter("none");
+ break;
+ default:
+ transferList->applyLabelFilter(customLabels.at(row-2));
+ }
}
};
diff --git a/src/transferlistwidget.cpp b/src/transferlistwidget.cpp
index 8fc1c521b..a4e32bffc 100644
--- a/src/transferlistwidget.cpp
+++ b/src/transferlistwidget.cpp
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -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; irowCount(); ++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 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)+"|"+
diff --git a/src/transferlistwidget.h b/src/transferlistwidget.h
index d40f685f8..132870753 100644
--- a/src/transferlistwidget.h
+++ b/src/transferlistwidget.h
@@ -50,6 +50,7 @@ private:
TransferListDelegate *listDelegate;
QStandardItemModel *listModel;
QSortFilterProxyModel *proxyModel;
+ QSortFilterProxyModel *labelFilterModel;
Bittorrent* BTSession;
QTimer *refreshTimer;
GUI *main_window;
@@ -61,6 +62,8 @@ public:
protected:
int getRowFromHash(QString hash) const;
QString getHashFromRow(int row) const;
+ QModelIndex mapToSource(QModelIndex index) const;
+ QStringList getCustomLabels() const;
void saveColWidthList();
bool loadColWidthList();
void saveLastSortedColumn();
@@ -84,6 +87,8 @@ protected slots:
#endif
void toggleSelectedTorrentsSequentialDownload();
void toggleSelectedFirstLastPiecePrio();
+ void setSelectionLabel(QString label);
+ void askNewLabelForSelection();
void setRowColor(int row, QColor color);
public slots:
@@ -107,12 +112,15 @@ public slots:
void previewSelectedTorrents();
void hidePriorityColumn(bool hide);
void displayDLHoSMenu(const QPoint&);
- void applyFilter(int f);
+ void applyStatusFilter(int f);
+ void applyLabelFilter(QString label);
void previewFile(QString filePath);
+ void removeLabelFromRows(QString label);
signals:
void currentTorrentChanged(QTorrentHandle &h);
void torrentStatusUpdate(unsigned int nb_downloading, unsigned int nb_seeding, unsigned int nb_active, unsigned int nb_inactive);
+ void newLabel(QString label);
};
diff --git a/src/ui/torrentadditiondlg.ui b/src/ui/torrentadditiondlg.ui
index 91a791ec9..245ce30e4 100644
--- a/src/ui/torrentadditiondlg.ui
+++ b/src/ui/torrentadditiondlg.ui
@@ -14,9 +14,6 @@
Torrent addition dialog
-
- 3
-
-
@@ -65,68 +62,112 @@
-
-
+
-
-
-
- Torrent size:
-
-
+
+
-
+
+
+ Torrent size:
+
+
+
+ -
+
+
+ Unknown
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
-
-
-
- Unknown
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
+
+
-
+
+
+ Free disk space:
+
+
+
+ -
+
+
+ Unknown
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
-
-
+
-
-
+
- Free disk space:
+ Label:
-
-
-
- Unknown
+
+
+
+ 16777215
+ 26
+
+
+
+ true
+
+
+ true
-
-
-
-
-
-
-
- -
-
+
Qt::Horizontal
40
- 20
+ 17