diff --git a/src/gui/torrentfilterenum.h b/src/gui/torrentfilterenum.h index 0776db413..cfa7ff138 100644 --- a/src/gui/torrentfilterenum.h +++ b/src/gui/torrentfilterenum.h @@ -32,6 +32,6 @@ #define TORRENTFILTERENUM_H namespace TorrentFilter { -enum TorrentFilter {ALL, DOWNLOADING, COMPLETED, PAUSED, RESUMED, ACTIVE, INACTIVE}; + enum TorrentFilter {ALL, DOWNLOADING, COMPLETED, RESUMED, PAUSED, ACTIVE, INACTIVE}; } #endif // TORRENTFILTERENUM_H diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index efb51a607..f173e2a20 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -48,332 +48,353 @@ #include "autoexpandabledialog.h" #include "torrentfilterenum.h" -LabelFiltersList::LabelFiltersList(QWidget *parent): QListWidget(parent) { - itemHover = 0; - // Accept drop - setAcceptDrops(true); - setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - setStyleSheet("QListWidget { background: transparent; border: 0 }"); +LabelFiltersList::LabelFiltersList(QWidget *parent): QListWidget(parent) +{ + itemHover = 0; + // Accept drop + setAcceptDrops(true); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + setStyleSheet("QListWidget { background: transparent; border: 0 }"); #if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); + setAttribute(Qt::WA_MacShowFocusRect, false); #endif } -void LabelFiltersList::addItem(QListWidgetItem *it) { - Q_ASSERT(count() >= 2); - for (int i=2; itext().localeAwareCompare(it->text()) >= 0) { - insertItem(i, it); - return; +void LabelFiltersList::addItem(QListWidgetItem *it) +{ + Q_ASSERT(count() >= 2); + for (int i = 2; itext().localeAwareCompare(it->text()) >= 0) { + insertItem(i, it); + return; + } } - } - QListWidget::addItem(it); + QListWidget::addItem(it); } -QString LabelFiltersList::labelFromRow(int row) const { - Q_ASSERT(row > 1); - const QString &label = item(row)->text(); - QStringList parts = label.split(" "); - Q_ASSERT(parts.size() >= 2); - parts.removeLast(); // Remove trailing number - return parts.join(" "); +QString LabelFiltersList::labelFromRow(int row) const +{ + Q_ASSERT(row > 1); + const QString &label = item(row)->text(); + QStringList parts = label.split(" "); + Q_ASSERT(parts.size() >= 2); + parts.removeLast(); // Remove trailing number + return parts.join(" "); } -int LabelFiltersList::rowFromLabel(QString label) const { - Q_ASSERT(!label.isEmpty()); - for (int i=2; ipos()) && row(itemAt(event->pos())) > 0) { - if (itemHover) { - if (itemHover != itemAt(event->pos())) { - setItemHover(false); - itemHover = itemAt(event->pos()); - setItemHover(true); - } - } else { - itemHover = itemAt(event->pos()); - setItemHover(true); +void LabelFiltersList::dragMoveEvent(QDragMoveEvent *event) +{ + if (itemAt(event->pos()) && row(itemAt(event->pos())) > 0) { + if (itemHover) { + if (itemHover != itemAt(event->pos())) { + setItemHover(false); + itemHover = itemAt(event->pos()); + setItemHover(true); + } + } + else { + itemHover = itemAt(event->pos()); + setItemHover(true); + } + event->acceptProposedAction(); + } + else { + if (itemHover) + setItemHover(false); + event->ignore(); } - event->acceptProposedAction(); - } else { - if (itemHover) - setItemHover(false); - event->ignore(); - } } -void LabelFiltersList::dropEvent(QDropEvent *event) { - qDebug("Drop Event in labels list"); - if (itemAt(event->pos())) { - emit torrentDropped(row(itemAt(event->pos()))); - } - event->ignore(); - setItemHover(false); - // Select current item again - currentItem()->setSelected(true); +void LabelFiltersList::dropEvent(QDropEvent *event) +{ + qDebug("Drop Event in labels list"); + if (itemAt(event->pos())) + emit torrentDropped(row(itemAt(event->pos()))); + event->ignore(); + setItemHover(false); + // Select current item again + currentItem()->setSelected(true); } -void LabelFiltersList::dragLeaveEvent(QDragLeaveEvent*) { - if (itemHover) - setItemHover(false); - // Select current item again - currentItem()->setSelected(true); +void LabelFiltersList::dragLeaveEvent(QDragLeaveEvent*) +{ + if (itemHover) + setItemHover(false); + // Select current item again + currentItem()->setSelected(true); } -void LabelFiltersList::setItemHover(bool hover) { - Q_ASSERT(itemHover); - if (hover) { - itemHover->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("folder-documents.png")); - itemHover->setSelected(true); - //setCurrentItem(itemHover); - } else { - itemHover->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory.png")); - //itemHover->setSelected(false); - itemHover = 0; - } +void LabelFiltersList::setItemHover(bool hover) +{ + Q_ASSERT(itemHover); + if (hover) { + itemHover->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("folder-documents.png")); + itemHover->setSelected(true); + //setCurrentItem(itemHover); + } + else { + itemHover->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory.png")); + //itemHover->setSelected(false); + itemHover = 0; + } } -StatusFiltersWidget::StatusFiltersWidget(QWidget *parent) : QListWidget(parent), m_shown(false) { - setUniformItemSizes(true); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - // Height is fixed (sizeHint().height() is used) - setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - setStyleSheet("QListWidget { background: transparent; border: 0 }"); +StatusFiltersWidget::StatusFiltersWidget(QWidget *parent): QListWidget(parent), m_shown(false) +{ + setUniformItemSizes(true); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // Height is fixed (sizeHint().height() is used) + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + setStyleSheet("QListWidget { background: transparent; border: 0 }"); #if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); + setAttribute(Qt::WA_MacShowFocusRect, false); #endif } -QSize StatusFiltersWidget::sizeHint() const { - QSize size = QListWidget::sizeHint(); - // Height should be exactly the height of the content - size.setHeight(contentsSize().height() + 2 * frameWidth()+6); - return size; +QSize StatusFiltersWidget::sizeHint() const +{ + QSize size = QListWidget::sizeHint(); + // Height should be exactly the height of the content + size.setHeight(contentsSize().height() + 2 * frameWidth() + 6); + return size; } -TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList): QFrame(parent), transferList(transferList), nb_labeled(0), nb_torrents(0) { - // Construct lists - vLayout = new QVBoxLayout(); - vLayout->setContentsMargins(0, 4, 0, 0); - QFont font; - font.setBold(true); - font.setCapitalization(QFont::SmallCaps); - QLabel *torrentsLabel = new QLabel(tr("Torrents")); - torrentsLabel->setIndent(2); - torrentsLabel->setFont(font); - vLayout->addWidget(torrentsLabel); - statusFilters = new StatusFiltersWidget(this); - vLayout->addWidget(statusFilters); - QLabel *labelsLabel = new QLabel(tr("Labels")); - labelsLabel->setIndent(2); - labelsLabel->setFont(font); - vLayout->addWidget(labelsLabel); - labelFilters = new LabelFiltersList(this); - vLayout->addWidget(labelFilters); - setLayout(vLayout); - labelFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - statusFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - statusFilters->setSpacing(0); - setContentsMargins(0,0,0,0); - vLayout->setSpacing(2); - // Add status filters - QListWidgetItem *all = new QListWidgetItem(statusFilters); - all->setData(Qt::DisplayRole, QVariant(tr("All") + " (0)")); - all->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterall.png")); - QListWidgetItem *downloading = new QListWidgetItem(statusFilters); - downloading->setData(Qt::DisplayRole, QVariant(tr("Downloading") + " (0)")); - downloading->setData(Qt::DecorationRole, QIcon(":/icons/skin/downloading.png")); - QListWidgetItem *completed = new QListWidgetItem(statusFilters); - completed->setData(Qt::DisplayRole, QVariant(tr("Completed") + " (0)")); - completed->setData(Qt::DecorationRole, QIcon(":/icons/skin/uploading.png")); - QListWidgetItem *paused = new QListWidgetItem(statusFilters); - paused->setData(Qt::DisplayRole, QVariant(tr("Paused") + " (0)")); - paused->setData(Qt::DecorationRole, QIcon(":/icons/skin/paused.png")); - QListWidgetItem *resumed = new QListWidgetItem(statusFilters); - resumed->setData(Qt::DisplayRole, QVariant(tr("Resumed") + " (0)")); - resumed->setData(Qt::DecorationRole, QIcon(":/icons/skin/resumed.png")); - QListWidgetItem *active = new QListWidgetItem(statusFilters); - active->setData(Qt::DisplayRole, QVariant(tr("Active") + " (0)")); - active->setData(Qt::DecorationRole, QIcon(":/icons/skin/filteractive.png")); - QListWidgetItem *inactive = new QListWidgetItem(statusFilters); - inactive->setData(Qt::DisplayRole, QVariant(tr("Inactive") + " (0)")); - inactive->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterinactive.png")); - - // SIGNAL/SLOT - connect(statusFilters, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyStatusFilter(int))); - connect(transferList->getSourceModel(), SIGNAL(modelRefreshed()), SLOT(updateTorrentNumbers())); - connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*))); - connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int))); - connect(labelFilters, SIGNAL(torrentDropped(int)), this, SLOT(torrentDropped(int))); - connect(transferList->getSourceModel(), SIGNAL(torrentAboutToBeRemoved(TorrentModelItem*)), SLOT(torrentAboutToBeDeleted(TorrentModelItem*))); - connect(transferList->getSourceModel(), SIGNAL(torrentChangedLabel(TorrentModelItem*,QString,QString)), SLOT(torrentChangedLabel(TorrentModelItem*, QString, QString))); - - // Add Label filters - QListWidgetItem *allLabels = new QListWidgetItem(labelFilters); - allLabels->setData(Qt::DisplayRole, QVariant(tr("All labels") + " (0)")); - allLabels->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); - QListWidgetItem *noLabel = new QListWidgetItem(labelFilters); - noLabel->setData(Qt::DisplayRole, QVariant(tr("Unlabeled") + " (0)")); - noLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); - - // Load settings - loadSettings(); - - labelFilters->setCurrentRow(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::TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList): QFrame(parent), transferList(transferList), nb_labeled(0), nb_torrents(0) +{ + // Construct lists + vLayout = new QVBoxLayout(); + vLayout->setContentsMargins(0, 4, 0, 0); + QFont font; + font.setBold(true); + font.setCapitalization(QFont::SmallCaps); + QLabel *torrentsLabel = new QLabel(tr("Torrents")); + torrentsLabel->setIndent(2); + torrentsLabel->setFont(font); + vLayout->addWidget(torrentsLabel); + statusFilters = new StatusFiltersWidget(this); + vLayout->addWidget(statusFilters); + QLabel *labelsLabel = new QLabel(tr("Labels")); + labelsLabel->setIndent(2); + labelsLabel->setFont(font); + vLayout->addWidget(labelsLabel); + labelFilters = new LabelFiltersList(this); + vLayout->addWidget(labelFilters); + setLayout(vLayout); + labelFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + statusFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + statusFilters->setSpacing(0); + setContentsMargins(0,0,0,0); + vLayout->setSpacing(2); + // Add status filters + QListWidgetItem *all = new QListWidgetItem(statusFilters); + all->setData(Qt::DisplayRole, QVariant(tr("All") + " (0)")); + all->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filterall.png")); + QListWidgetItem *downloading = new QListWidgetItem(statusFilters); + downloading->setData(Qt::DisplayRole, QVariant(tr("Downloading") + " (0)")); + downloading->setData(Qt::DecorationRole, QIcon(":/Icons/skin/downloading.png")); + QListWidgetItem *completed = new QListWidgetItem(statusFilters); + completed->setData(Qt::DisplayRole, QVariant(tr("Completed") + " (0)")); + completed->setData(Qt::DecorationRole, QIcon(":/Icons/skin/uploading.png")); + QListWidgetItem *resumed = new QListWidgetItem(statusFilters); + resumed->setData(Qt::DisplayRole, QVariant(tr("Resumed") + " (0)")); + resumed->setData(Qt::DecorationRole, QIcon(":/Icons/skin/resumed.png")); + QListWidgetItem *paused = new QListWidgetItem(statusFilters); + paused->setData(Qt::DisplayRole, QVariant(tr("Paused") + " (0)")); + paused->setData(Qt::DecorationRole, QIcon(":/Icons/skin/paused.png")); + QListWidgetItem *active = new QListWidgetItem(statusFilters); + active->setData(Qt::DisplayRole, QVariant(tr("Active") + " (0)")); + active->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filteractive.png")); + QListWidgetItem *inactive = new QListWidgetItem(statusFilters); + inactive->setData(Qt::DisplayRole, QVariant(tr("Inactive") + " (0)")); + inactive->setData(Qt::DecorationRole, QIcon(":/Icons/skin/filterinactive.png")); + + // SIGNAL/SLOT + connect(statusFilters, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyStatusFilter(int))); + connect(transferList->getSourceModel(), SIGNAL(modelRefreshed()), SLOT(updateTorrentNumbers())); + connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*))); + connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int))); + connect(labelFilters, SIGNAL(torrentDropped(int)), this, SLOT(torrentDropped(int))); + connect(transferList->getSourceModel(), SIGNAL(torrentAboutToBeRemoved(TorrentModelItem*)), SLOT(torrentAboutToBeDeleted(TorrentModelItem*))); + connect(transferList->getSourceModel(), SIGNAL(torrentChangedLabel(TorrentModelItem*,QString,QString)), SLOT(torrentChangedLabel(TorrentModelItem*, QString, QString))); + + // Add Label filters + QListWidgetItem *allLabels = new QListWidgetItem(labelFilters); + allLabels->setData(Qt::DisplayRole, QVariant(tr("All labels") + " (0)")); + allLabels->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); + QListWidgetItem *noLabel = new QListWidgetItem(labelFilters); + noLabel->setData(Qt::DisplayRole, QVariant(tr("Unlabeled") + " (0)")); + noLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); + + // Load settings + loadSettings(); + + labelFilters->setCurrentRow(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::~TransferListFiltersWidget() { - saveSettings(); - delete statusFilters; - delete labelFilters; - delete vLayout; +TransferListFiltersWidget::~TransferListFiltersWidget() +{ + saveSettings(); + delete statusFilters; + delete labelFilters; + delete vLayout; } -StatusFiltersWidget* TransferListFiltersWidget::getStatusFilters() const { - return statusFilters; +StatusFiltersWidget* TransferListFiltersWidget::getStatusFilters() const +{ + return statusFilters; } -void TransferListFiltersWidget::saveSettings() const { - Preferences* const pref = Preferences::instance(); - pref->setTransSelFilter(statusFilters->currentRow()); - pref->setTorrentLabels(customLabels.keys()); +void TransferListFiltersWidget::saveSettings() const +{ + Preferences* const pref = Preferences::instance(); + pref->setTransSelFilter(statusFilters->currentRow()); + pref->setTorrentLabels(customLabels.keys()); } -void TransferListFiltersWidget::loadSettings() { - statusFilters->setCurrentRow(Preferences::instance()->getTransSelFilter()); - const QStringList label_list = Preferences::instance()->getTorrentLabels(); - foreach (const QString &label, label_list) { - customLabels.insert(label, 0); - qDebug("Creating label QListWidgetItem: %s", qPrintable(label)); - QListWidgetItem *newLabel = new QListWidgetItem(); - newLabel->setText(label + " (0)"); - newLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); - labelFilters->addItem(newLabel); - } +void TransferListFiltersWidget::loadSettings() +{ + statusFilters->setCurrentRow(Preferences::instance()->getTransSelFilter()); + const QStringList label_list = Preferences::instance()->getTorrentLabels(); + foreach (const QString &label, label_list) { + customLabels.insert(label, 0); + qDebug("Creating label QListWidgetItem: %s", qPrintable(label)); + QListWidgetItem *newLabel = new QListWidgetItem(); + newLabel->setText(label + " (0)"); + newLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); + labelFilters->addItem(newLabel); + } } -void TransferListFiltersWidget::updateTorrentNumbers() { - const TorrentStatusReport report = transferList->getSourceModel()->getTorrentStatusReport(); - statusFilters->item(TorrentFilter::ALL)->setData(Qt::DisplayRole, QVariant(tr("All")+" ("+QString::number(report.nb_active+report.nb_inactive)+")")); - statusFilters->item(TorrentFilter::DOWNLOADING)->setData(Qt::DisplayRole, QVariant(tr("Downloading")+" ("+QString::number(report.nb_downloading)+")")); - statusFilters->item(TorrentFilter::COMPLETED)->setData(Qt::DisplayRole, QVariant(tr("Completed")+" ("+QString::number(report.nb_seeding)+")")); - statusFilters->item(TorrentFilter::PAUSED)->setData(Qt::DisplayRole, QVariant(tr("Paused")+" ("+QString::number(report.nb_paused)+")")); - statusFilters->item(TorrentFilter::RESUMED)->setData(Qt::DisplayRole, QVariant(tr("Resumed")+" ("+QString::number(report.nb_active+report.nb_inactive-report.nb_paused)+")")); - statusFilters->item(TorrentFilter::ACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Active")+" ("+QString::number(report.nb_active)+")")); - statusFilters->item(TorrentFilter::INACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Inactive")+" ("+QString::number(report.nb_inactive)+")")); +void TransferListFiltersWidget::updateTorrentNumbers() +{ + const TorrentStatusReport report = transferList->getSourceModel()->getTorrentStatusReport(); + statusFilters->item(TorrentFilter::ALL)->setData(Qt::DisplayRole, QVariant(tr("All") + " (" + QString::number(report.nb_active + report.nb_inactive) + ")")); + statusFilters->item(TorrentFilter::DOWNLOADING)->setData(Qt::DisplayRole, QVariant(tr("Downloading") + " (" + QString::number(report.nb_downloading) + ")")); + statusFilters->item(TorrentFilter::COMPLETED)->setData(Qt::DisplayRole, QVariant(tr("Completed") + " (" + QString::number(report.nb_seeding) + ")")); + statusFilters->item(TorrentFilter::PAUSED)->setData(Qt::DisplayRole, QVariant(tr("Paused") + " (" + QString::number(report.nb_paused) + ")")); + statusFilters->item(TorrentFilter::RESUMED)->setData(Qt::DisplayRole, QVariant(tr("Resumed") + " (" + QString::number(report.nb_active + report.nb_inactive - report.nb_paused) + ")")); + statusFilters->item(TorrentFilter::ACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Active") + " (" + QString::number(report.nb_active) + ")")); + statusFilters->item(TorrentFilter::INACTIVE)->setData(Qt::DisplayRole, QVariant(tr("Inactive") + " (" + QString::number(report.nb_inactive) + ")")); } -void TransferListFiltersWidget::torrentDropped(int row) { - Q_ASSERT(row > 0); - if (row == 1) { - transferList->setSelectionLabel(""); - } else { - transferList->setSelectionLabel(labelFilters->labelFromRow(row)); - } +void TransferListFiltersWidget::torrentDropped(int row) +{ + Q_ASSERT(row > 0); + if (row == 1) + transferList->setSelectionLabel(""); + else + transferList->setSelectionLabel(labelFilters->labelFromRow(row)); } -void TransferListFiltersWidget::addLabel(QString& label) { - label = fsutils::toValidFileSystemName(label.trimmed()); - if (label.isEmpty() || customLabels.contains(label)) return; - QListWidgetItem *newLabel = new QListWidgetItem(); - newLabel->setText(label + " (0)"); - newLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); - labelFilters->addItem(newLabel); - customLabels.insert(label, 0); - Preferences::instance()->addTorrentLabel(label); +void TransferListFiltersWidget::addLabel(QString& label) +{ + label = fsutils::toValidFileSystemName(label.trimmed()); + if (label.isEmpty() || customLabels.contains(label)) return; + QListWidgetItem *newLabel = new QListWidgetItem(); + newLabel->setText(label + " (0)"); + newLabel->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory")); + labelFilters->addItem(newLabel); + customLabels.insert(label, 0); + Preferences::instance()->addTorrentLabel(label); } -void TransferListFiltersWidget::showLabelMenu(QPoint) { - QMenu labelMenu(labelFilters); - QAction *addAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-add"), tr("Add label...")); - QAction *removeAct = 0; - QAction *removeUnusedAct = 0; - if (!labelFilters->selectedItems().empty() && labelFilters->row(labelFilters->selectedItems().first()) > 1) - removeAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove label")); - else - removeUnusedAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove unused labels")); - labelMenu.addSeparator(); - QAction *startAct = labelMenu.addAction(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); - QAction *pauseAct = labelMenu.addAction(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents")); - QAction *deleteTorrentsAct = labelMenu.addAction(IconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents")); - QAction *act = 0; - act = labelMenu.exec(QCursor::pos()); - if (act) { - if (act == removeAct) { - removeSelectedLabel(); - return; - } - if (act == removeUnusedAct) { - removeUnusedLabels(); - return; - } - if (act == deleteTorrentsAct) { - transferList->deleteVisibleTorrents(); - return; - } - if (act == startAct) { - transferList->startVisibleTorrents(); - return; - } - if (act == pauseAct) { - transferList->pauseVisibleTorrents(); - return; - } - if (act == addAct) { - bool ok; - QString label = ""; - bool invalid; - do { - invalid = false; - label = AutoExpandableDialog::getText(this, tr("New Label"), tr("Label:"), QLineEdit::Normal, label, &ok); - if (ok && !label.isEmpty()) { - if (fsutils::isValidFileSystemName(label)) { - addLabel(label); - } else { - QMessageBox::warning(this, tr("Invalid label name"), tr("Please don't use any special characters in the label name.")); - invalid = true; - } +void TransferListFiltersWidget::showLabelMenu(QPoint) +{ + QMenu labelMenu(labelFilters); + QAction *addAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-add"), tr("Add label...")); + QAction *removeAct = 0; + QAction *removeUnusedAct = 0; + if (!labelFilters->selectedItems().empty() && labelFilters->row(labelFilters->selectedItems().first()) > 1) + removeAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove label")); + else + removeUnusedAct = labelMenu.addAction(IconProvider::instance()->getIcon("list-remove"), tr("Remove unused labels")); + labelMenu.addSeparator(); + QAction *startAct = labelMenu.addAction(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); + QAction *pauseAct = labelMenu.addAction(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents")); + QAction *deleteTorrentsAct = labelMenu.addAction(IconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents")); + QAction *act = 0; + act = labelMenu.exec(QCursor::pos()); + if (act) { + if (act == removeAct) { + removeSelectedLabel(); + return; + } + if (act == removeUnusedAct) { + removeUnusedLabels(); + return; + } + if (act == deleteTorrentsAct) { + transferList->deleteVisibleTorrents(); + return; + } + if (act == startAct) { + transferList->startVisibleTorrents(); + return; + } + if (act == pauseAct) { + transferList->pauseVisibleTorrents(); + return; + } + if (act == addAct) { + bool ok; + QString label = ""; + bool invalid; + do { + invalid = false; + label = AutoExpandableDialog::getText(this, tr("New Label"), tr("Label:"), QLineEdit::Normal, label, &ok); + if (ok && !label.isEmpty()) { + if (fsutils::isValidFileSystemName(label)) { + addLabel(label); + } + else { + QMessageBox::warning(this, tr("Invalid label name"), tr("Please don't use any special characters in the label name.")); + invalid = true; + } + } + } while (invalid); + return; } - } while(invalid); - return; } - } } -void TransferListFiltersWidget::removeSelectedLabel() { - const int row = labelFilters->row(labelFilters->selectedItems().first()); - Q_ASSERT(row > 1); - const QString &label = labelFilters->labelFromRow(row); - Q_ASSERT(customLabels.contains(label)); - customLabels.remove(label); - transferList->removeLabelFromRows(label); - // Select first label - labelFilters->setCurrentItem(labelFilters->item(0)); - labelFilters->selectionModel()->select(labelFilters->model()->index(0,0), QItemSelectionModel::Select); - applyLabelFilter(0); - // Un display filter - delete labelFilters->takeItem(row); - // Save custom labels to remember it was deleted - Preferences::instance()->removeTorrentLabel(label); +void TransferListFiltersWidget::removeSelectedLabel() +{ + const int row = labelFilters->row(labelFilters->selectedItems().first()); + Q_ASSERT(row > 1); + const QString &label = labelFilters->labelFromRow(row); + Q_ASSERT(customLabels.contains(label)); + customLabels.remove(label); + transferList->removeLabelFromRows(label); + // Select first label + labelFilters->setCurrentItem(labelFilters->item(0)); + labelFilters->selectionModel()->select(labelFilters->model()->index(0,0), QItemSelectionModel::Select); + applyLabelFilter(0); + // Un display filter + delete labelFilters->takeItem(row); + // Save custom labels to remember it was deleted + Preferences::instance()->removeTorrentLabel(label); } -void TransferListFiltersWidget::removeUnusedLabels() { +void TransferListFiltersWidget::removeUnusedLabels() +{ QStringList unusedLabels; QHash::const_iterator i; - for (i = customLabels.begin(); i != customLabels.end(); ++i) { + for (i = customLabels.begin(); i != customLabels.end(); ++i) if (i.value() == 0) unusedLabels << i.key(); - } foreach (const QString &label, unusedLabels) { customLabels.remove(label); delete labelFilters->takeItem(labelFilters->rowFromLabel(label)); @@ -381,95 +402,100 @@ void TransferListFiltersWidget::removeUnusedLabels() { } } -void TransferListFiltersWidget::applyLabelFilter(int row) { - switch(row) { - case 0: - transferList->applyLabelFilterAll(); - break; - case 1: - transferList->applyLabelFilter(QString()); - break; - default: - transferList->applyLabelFilter(labelFilters->labelFromRow(row)); - } +void TransferListFiltersWidget::applyLabelFilter(int row) +{ + switch (row) { + case 0: + transferList->applyLabelFilterAll(); + break; + case 1: + transferList->applyLabelFilter(QString()); + break; + default: + transferList->applyLabelFilter(labelFilters->labelFromRow(row)); + } } -void TransferListFiltersWidget::torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label) { - Q_UNUSED(torrentItem); - qDebug("Torrent label changed from %s to %s", qPrintable(old_label), qPrintable(new_label)); - if (!old_label.isEmpty()) { - if (customLabels.contains(old_label)) { - const int new_count = customLabels.value(old_label, 0) - 1; - Q_ASSERT(new_count >= 0); - customLabels.insert(old_label, new_count); - const int row = labelFilters->rowFromLabel(old_label); - Q_ASSERT(row >= 2); - labelFilters->item(row)->setText(old_label + " ("+ QString::number(new_count) +")"); +void TransferListFiltersWidget::torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label) +{ + Q_UNUSED(torrentItem); + qDebug("Torrent label changed from %s to %s", qPrintable(old_label), qPrintable(new_label)); + if (!old_label.isEmpty()) { + if (customLabels.contains(old_label)) { + const int new_count = customLabels.value(old_label, 0) - 1; + Q_ASSERT(new_count >= 0); + customLabels.insert(old_label, new_count); + const int row = labelFilters->rowFromLabel(old_label); + Q_ASSERT(row >= 2); + labelFilters->item(row)->setText(old_label + " (" + QString::number(new_count) + ")"); + } + --nb_labeled; } - --nb_labeled; - } - if (!new_label.isEmpty()) { - if (!customLabels.contains(new_label)) - addLabel(new_label); - const int new_count = customLabels.value(new_label, 0) + 1; - Q_ASSERT(new_count >= 1); - customLabels.insert(new_label, new_count); - const int row = labelFilters->rowFromLabel(new_label); - Q_ASSERT(row >= 2); - labelFilters->item(row)->setText(new_label + " ("+ QString::number(new_count) +")"); - ++nb_labeled; - } - updateStickyLabelCounters(); + if (!new_label.isEmpty()) { + if (!customLabels.contains(new_label)) + addLabel(new_label); + const int new_count = customLabels.value(new_label, 0) + 1; + Q_ASSERT(new_count >= 1); + customLabels.insert(new_label, new_count); + const int row = labelFilters->rowFromLabel(new_label); + Q_ASSERT(row >= 2); + labelFilters->item(row)->setText(new_label + " (" + QString::number(new_count) + ")"); + ++nb_labeled; + } + updateStickyLabelCounters(); } -void TransferListFiltersWidget::handleNewTorrent(TorrentModelItem* torrentItem) { - QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString(); - qDebug("New torrent was added with label: %s", qPrintable(label)); - if (!label.isEmpty()) { - if (!customLabels.contains(label)) { - addLabel(label); - // addLabel may have changed the label, update the model accordingly. - torrentItem->setData(TorrentModelItem::TR_LABEL, label); +void TransferListFiltersWidget::handleNewTorrent(TorrentModelItem* torrentItem) +{ + QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString(); + qDebug("New torrent was added with label: %s", qPrintable(label)); + if (!label.isEmpty()) { + if (!customLabels.contains(label)) { + addLabel(label); + // addLabel may have changed the label, update the model accordingly. + torrentItem->setData(TorrentModelItem::TR_LABEL, label); + } + // Update label counter + Q_ASSERT(customLabels.contains(label)); + const int new_count = customLabels.value(label, 0) + 1; + customLabels.insert(label, new_count); + const int row = labelFilters->rowFromLabel(label); + qDebug("torrentAdded, Row: %d", row); + Q_ASSERT(row >= 2); + Q_ASSERT(labelFilters->item(row)); + labelFilters->item(row)->setText(label + " (" + QString::number(new_count) + ")"); + ++nb_labeled; } - // Update label counter - Q_ASSERT(customLabels.contains(label)); - const int new_count = customLabels.value(label, 0) + 1; - customLabels.insert(label, new_count); - const int row = labelFilters->rowFromLabel(label); - qDebug("torrentAdded, Row: %d", row); - Q_ASSERT(row >= 2); - Q_ASSERT(labelFilters->item(row)); - labelFilters->item(row)->setText(label + " ("+ QString::number(new_count) +")"); - ++nb_labeled; - } - ++nb_torrents; - Q_ASSERT(nb_torrents >= 0); - Q_ASSERT(nb_labeled >= 0); - Q_ASSERT(nb_labeled <= nb_torrents); - updateStickyLabelCounters(); + ++nb_torrents; + Q_ASSERT(nb_torrents >= 0); + Q_ASSERT(nb_labeled >= 0); + Q_ASSERT(nb_labeled <= nb_torrents); + updateStickyLabelCounters(); } -void TransferListFiltersWidget::torrentAboutToBeDeleted(TorrentModelItem* torrentItem) { - Q_ASSERT(torrentItem); - QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString(); - if (!label.isEmpty()) { - // Update label counter - const int new_count = customLabels.value(label, 0) - 1; - customLabels.insert(label, new_count); - const int row = labelFilters->rowFromLabel(label); - Q_ASSERT(row >= 2); - labelFilters->item(row)->setText(label + " ("+ QString::number(new_count) +")"); - --nb_labeled; - } - --nb_torrents; - qDebug("nb_torrents: %d, nb_labeled: %d", nb_torrents, nb_labeled); - Q_ASSERT(nb_torrents >= 0); - Q_ASSERT(nb_labeled >= 0); - Q_ASSERT(nb_labeled <= nb_torrents); - updateStickyLabelCounters(); +void TransferListFiltersWidget::torrentAboutToBeDeleted(TorrentModelItem* torrentItem) +{ + Q_ASSERT(torrentItem); + QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString(); + if (!label.isEmpty()) { + // Update label counter + const int new_count = customLabels.value(label, 0) - 1; + customLabels.insert(label, new_count); + const int row = labelFilters->rowFromLabel(label); + Q_ASSERT(row >= 2); + labelFilters->item(row)->setText(label + " (" + QString::number(new_count) + ")"); + --nb_labeled; + } + --nb_torrents; + qDebug("nb_torrents: %d, nb_labeled: %d", nb_torrents, nb_labeled); + Q_ASSERT(nb_torrents >= 0); + Q_ASSERT(nb_labeled >= 0); + Q_ASSERT(nb_labeled <= nb_torrents); + updateStickyLabelCounters(); } -void TransferListFiltersWidget::updateStickyLabelCounters() { - labelFilters->item(0)->setText(tr("All labels") + " ("+QString::number(nb_torrents)+")"); - labelFilters->item(1)->setText(tr("Unlabeled") + " ("+QString::number(nb_torrents-nb_labeled)+")"); +void TransferListFiltersWidget::updateStickyLabelCounters() +{ + labelFilters->item(0)->setText(tr("All labels") + " (" + QString::number(nb_torrents) + ")"); + labelFilters->item(1)->setText(tr("Unlabeled") + " (" + QString::number(nb_torrents - nb_labeled) + ")"); } diff --git a/src/gui/transferlistfilterswidget.h b/src/gui/transferlistfilterswidget.h index 7bea61df7..3e78ed9f9 100644 --- a/src/gui/transferlistfilterswidget.h +++ b/src/gui/transferlistfilterswidget.h @@ -43,77 +43,80 @@ QT_END_NAMESPACE class TransferListWidget; class TorrentModelItem; -class LabelFiltersList: public QListWidget { - Q_OBJECT +class LabelFiltersList: public QListWidget +{ + Q_OBJECT private: - QListWidgetItem *itemHover; + QListWidgetItem * itemHover; public: - LabelFiltersList(QWidget *parent); + LabelFiltersList(QWidget *parent); - // Redefine addItem() to make sure the list stays sorted - void addItem(QListWidgetItem *it); + // Redefine addItem() to make sure the list stays sorted + void addItem(QListWidgetItem *it); - QString labelFromRow(int row) const; - int rowFromLabel(QString label) const; + QString labelFromRow(int row) const; + int rowFromLabel(QString label) const; signals: - void torrentDropped(int label_row); + void torrentDropped(int label_row); protected: - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); - void dragLeaveEvent(QDragLeaveEvent*); - void setItemHover(bool hover); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + void dragLeaveEvent(QDragLeaveEvent*); + void setItemHover(bool hover); }; -class StatusFiltersWidget : public QListWidget { - Q_OBJECT +class StatusFiltersWidget: public QListWidget +{ + Q_OBJECT public: - StatusFiltersWidget(QWidget *parent); + StatusFiltersWidget(QWidget *parent); protected: - QSize sizeHint() const; + QSize sizeHint() const; private: - bool m_shown; + bool m_shown; }; -class TransferListFiltersWidget: public QFrame { - Q_OBJECT +class TransferListFiltersWidget: public QFrame +{ + Q_OBJECT private: - QHash customLabels; - StatusFiltersWidget* statusFilters; - LabelFiltersList* labelFilters; - QVBoxLayout* vLayout; - TransferListWidget *transferList; - int nb_labeled; - int nb_torrents; + QHash customLabels; + StatusFiltersWidget* statusFilters; + LabelFiltersList* labelFilters; + QVBoxLayout* vLayout; + TransferListWidget *transferList; + int nb_labeled; + int nb_torrents; public: - TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList); - ~TransferListFiltersWidget(); + TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList); + ~TransferListFiltersWidget(); - StatusFiltersWidget* getStatusFilters() const; + StatusFiltersWidget* getStatusFilters() const; - void saveSettings() const; - void loadSettings(); + void saveSettings() const; + void loadSettings(); protected slots: - void updateTorrentNumbers(); - void torrentDropped(int row); - void addLabel(QString& label); - void showLabelMenu(QPoint); - void removeSelectedLabel(); - void removeUnusedLabels(); - void applyLabelFilter(int row); - void torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label); - void handleNewTorrent(TorrentModelItem* torrentItem); - void torrentAboutToBeDeleted(TorrentModelItem* torrentItem); - void updateStickyLabelCounters(); + void updateTorrentNumbers(); + void torrentDropped(int row); + void addLabel(QString& label); + void showLabelMenu(QPoint); + void removeSelectedLabel(); + void removeUnusedLabels(); + void applyLabelFilter(int row); + void torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label); + void handleNewTorrent(TorrentModelItem* torrentItem); + void torrentAboutToBeDeleted(TorrentModelItem* torrentItem); + void updateStickyLabelCounters(); }; #endif // TRANSFERLISTFILTERSWIDGET_H diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 2f5cf515d..e02423efb 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -102,6 +102,7 @@ static const char KEY_TORRENT_STATE[] = "state"; static const char KEY_TORRENT_SEQUENTIAL_DOWNLOAD[] = "seq_dl"; static const char KEY_TORRENT_FIRST_LAST_PIECE_PRIO[] = "f_l_piece_prio"; static const char KEY_TORRENT_LABEL[] = "label"; +static const char KEY_TORRENT_SUPER_SEEDING[] = "super_seeding"; // Tracker keys static const char KEY_TRACKER_URL[] = "url"; @@ -144,6 +145,11 @@ static const char KEY_TRANSFER_UPRATELIMIT[] = "up_rate_limit"; static const char KEY_TRANSFER_DHT_NODES[] = "dht_nodes"; static const char KEY_TRANSFER_CONNECTION_STATUS[] = "connection_status"; +// Sync main data keys +static const char KEY_SYNC_MAINDATA_QUEUEING[] = "queueing"; +static const char KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS[] = "use_alt_speed_limits"; +static const char KEY_SYNC_MAINDATA_REFRESH_INTERVAL[] = "refresh_interval"; + static const char KEY_FULL_UPDATE[] = "full_update"; static const char KEY_RESPONSE_ID[] = "rid"; static const char KEY_SUFFIX_REMOVED[] = "_removed"; @@ -151,7 +157,7 @@ static const char KEY_SUFFIX_REMOVED[] = "_removed"; QVariantMap getTranserInfoMap(); QVariantMap toMap(const QTorrentHandle& h); void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData); -void processHash(QVariantHash prevData, QVariantHash data, QVariantHash &syncData, QVariantList &removedItems); +void processHash(QVariantHash prevData, QVariantHash data, QVariantMap &syncData, QVariantList &removedItems); void processList(QVariantList prevData, QVariantList data, QVariantList &syncData, QVariantList &removedItems); QVariantMap generateSyncData(int acceptedResponseId, QVariantMap data, QVariantMap &lastAcceptedData, QVariantMap &lastData); @@ -274,8 +280,7 @@ QByteArray btjson::getTorrents(QString filter, QString label, * - "torrents_removed": a list of hashes of removed torrents * - "labels": list of labels * - "labels_removed": list of removed labels - * - "queueing": priority system usage flag - * - "server_state": map contains information about the status of the server + * - "server_state": map contains information about the state of the server * The keys of the 'torrents' dictionary are hashes of torrents. * Each value of the 'torrents' dictionary contains map. The map can contain following keys: * - "name": Torrent name @@ -302,6 +307,8 @@ QByteArray btjson::getTorrents(QString filter, QString label, * - "up_info_data: bytes uploaded * - "up_info_speed: upload speed * - "up_rate_limit: upload speed limit + * - "queueing": priority system usage flag + * - "refresh_interval": torrents table refresh interval */ QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData, QVariantMap &lastAcceptedData) { @@ -321,14 +328,18 @@ QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData } data["torrents"] = torrents; - data["queueing"] = QBtSession::instance()->isQueueingEnabled(); QVariantList labels; foreach (QString s, Preferences::instance()->getTorrentLabels()) labels << s; data["labels"] = labels; - data["server_state"] = getTranserInfoMap(); + + QVariantMap serverState = getTranserInfoMap(); + serverState[KEY_SYNC_MAINDATA_QUEUEING] = QBtSession::instance()->isQueueingEnabled(); + serverState[KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS] = Preferences::instance()->isAltBandwidthEnabled(); + serverState[KEY_SYNC_MAINDATA_REFRESH_INTERVAL] = Preferences::instance()->getRefreshInterval(); + data["server_state"] = serverState; return json::toJson(generateSyncData(acceptedResponseId, data, lastAcceptedData, lastData)); } @@ -528,6 +539,21 @@ QVariantMap getTranserInfoMap() return map; } +QByteArray btjson::getTorrentsRatesLimits(QStringList &hashes, bool downloadLimits) +{ + QVariantMap map; + + foreach (const QString &hash, hashes) { + int limit = -1; + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + if (h.is_valid()) + limit = downloadLimits ? h.download_limit() : h.upload_limit(); + map[hash] = limit; + } + + return json::toJson(map); +} + QVariantMap toMap(const QTorrentHandle& h) { libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters); @@ -555,6 +581,7 @@ QVariantMap toMap(const QTorrentHandle& h) if (h.has_metadata()) ret[KEY_TORRENT_FIRST_LAST_PIECE_PRIO] = h.first_last_piece_first(); ret[KEY_TORRENT_LABEL] = TorrentPersistentData::instance()->getLabel(h.hash()); + ret[KEY_TORRENT_SUPER_SEEDING] = status.super_seeding; return ret; } @@ -579,10 +606,10 @@ void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData) } break; case QVariant::Hash: { - QVariantHash hash; - processHash(prevData[key].toHash(), data[key].toHash(), hash, removedItems); - if (!hash.isEmpty()) - syncData[key] = hash; + QVariantMap map; + processHash(prevData[key].toHash(), data[key].toHash(), map, removedItems); + if (!map.isEmpty()) + syncData[key] = map; if (!removedItems.isEmpty()) syncData[key + KEY_SUFFIX_REMOVED] = removedItems; } @@ -603,6 +630,7 @@ void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData) case QVariant::Bool: case QVariant::Double: case QVariant::ULongLong: + case QVariant::UInt: if (prevData[key] != data[key]) syncData[key] = data[key]; break; @@ -615,7 +643,7 @@ void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData) // Compare two lists of structures (prevData, data) and calculate difference (syncData, removedItems). // Structures encoded as map. // Lists are encoded as hash table (indexed by structure key value) to improve ease of searching for removed items. -void processHash(QVariantHash prevData, QVariantHash data, QVariantHash &syncData, QVariantList &removedItems) +void processHash(QVariantHash prevData, QVariantHash data, QVariantMap &syncData, QVariantList &removedItems) { // initialize output variables syncData.clear(); @@ -623,7 +651,8 @@ void processHash(QVariantHash prevData, QVariantHash data, QVariantHash &syncDat if (prevData.isEmpty()) { // If list was empty before, then difference is a whole new list. - syncData = data; + foreach (QString key, data.keys()) + syncData[key] = data[key]; } else { foreach (QString key, data.keys()) { diff --git a/src/webui/btjson.h b/src/webui/btjson.h index 2d5f7e8eb..fb9faf434 100644 --- a/src/webui/btjson.h +++ b/src/webui/btjson.h @@ -52,6 +52,7 @@ public: static QByteArray getPropertiesForTorrent(const QString& hash); static QByteArray getFilesForTorrent(const QString& hash); static QByteArray getTransferInfo(); + static QByteArray getTorrentsRatesLimits(QStringList& hashes, bool downloadLimits); }; // class btjson #endif // BTJSON_H diff --git a/src/webui/jsonutils.h b/src/webui/jsonutils.h index 27d4ac7a9..b8619dc66 100644 --- a/src/webui/jsonutils.h +++ b/src/webui/jsonutils.h @@ -42,23 +42,25 @@ namespace json { -inline QByteArray toJson(const QVariant& var) -{ + inline QByteArray toJson(const QVariant& var) + { #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - return QJsonDocument::fromVariant(var).toJson(); + return QJsonDocument::fromVariant(var).toJson(QJsonDocument::Compact); #else - return QJson::Serializer().serialize(var); + QJson::Serializer serializer; + serializer.setIndentMode(QJson::IndentCompact); + return serializer.serialize(var); #endif -} + } -inline QVariant fromJson(const QString& json) -{ + inline QVariant fromJson(const QString& json) + { #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - return QJsonDocument::fromJson(json.toUtf8()).toVariant(); + return QJsonDocument::fromJson(json.toUtf8()).toVariant(); #else - return QJson::Parser().parse(json.toUtf8()); + return QJson::Parser().parse(json.toUtf8()); #endif -} + } } diff --git a/src/webui/qtorrentfilter.cpp b/src/webui/qtorrentfilter.cpp index 46504fab5..2c4ac2f6c 100644 --- a/src/webui/qtorrentfilter.cpp +++ b/src/webui/qtorrentfilter.cpp @@ -39,6 +39,8 @@ QTorrentFilter::QTorrentFilter(QString filter, QString label) type_ = Completed; else if (filter == "paused") type_ = Paused; + else if (filter == "resumed") + type_ = Resumed; else if (filter == "active") type_ = Active; else if (filter == "inactive") @@ -57,6 +59,8 @@ bool QTorrentFilter::apply(const QTorrentHandle& h) const return isTorrentCompleted(h); case Paused: return isTorrentPaused(h); + case Resumed: + return isTorrentResumed(h); case Active: return isTorrentActive(h); case Inactive: @@ -98,6 +102,14 @@ bool QTorrentFilter::isTorrentPaused(const QTorrentHandle &h) const || state == QTorrentState::Error; } +bool QTorrentFilter::isTorrentResumed(const QTorrentHandle &h) const +{ + const QTorrentState state = h.torrentState(); + + return state != QTorrentState::PausedUploading + && state != QTorrentState::PausedDownloading; +} + bool QTorrentFilter::isTorrentActive(const QTorrentHandle &h) const { const QTorrentState state = h.torrentState(); diff --git a/src/webui/qtorrentfilter.h b/src/webui/qtorrentfilter.h index 052c9ac6a..10e2bf2c0 100644 --- a/src/webui/qtorrentfilter.h +++ b/src/webui/qtorrentfilter.h @@ -40,6 +40,7 @@ public: Downloading, Completed, Paused, + Resumed, Active, Inactive }; @@ -55,6 +56,7 @@ private: bool isTorrentDownloading(const QTorrentHandle &h) const; bool isTorrentCompleted(const QTorrentHandle &h) const; bool isTorrentPaused(const QTorrentHandle &h) const; + bool isTorrentResumed(const QTorrentHandle &h) const; bool isTorrentActive(const QTorrentHandle &h) const; bool isTorrentInactive(const QTorrentHandle &h) const; bool torrentHasLabel(const QTorrentHandle &h) const; diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index f7140e96c..ed2d5b36c 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -94,14 +94,15 @@ QMap > WebApplication::initialize ADD_ACTION(command, getGlobalDlLimit); ADD_ACTION(command, setGlobalUpLimit); ADD_ACTION(command, setGlobalDlLimit); - ADD_ACTION(command, getTorrentUpLimit); - ADD_ACTION(command, getTorrentDlLimit); - ADD_ACTION(command, setTorrentUpLimit); - ADD_ACTION(command, setTorrentDlLimit); + ADD_ACTION(command, getTorrentsUpLimit); + ADD_ACTION(command, getTorrentsDlLimit); + ADD_ACTION(command, setTorrentsUpLimit); + ADD_ACTION(command, setTorrentsDlLimit); ADD_ACTION(command, alternativeSpeedLimitsEnabled); ADD_ACTION(command, toggleAlternativeSpeedLimits); ADD_ACTION(command, toggleSequentialDownload); ADD_ACTION(command, toggleFirstLastPiecePrio); + ADD_ACTION(command, setSuperSeeding); ADD_ACTION(command, delete); ADD_ACTION(command, deletePerm); ADD_ACTION(command, increasePrio); @@ -212,7 +213,7 @@ void WebApplication::action_public_images() } // GET params: -// - filter (string): all, downloading, completed, paused, active, inactive +// - filter (string): all, downloading, completed, paused, resumed, active, inactive // - label (string): torrent label for filtering by it (empty string means "unlabeled"; no "label" param presented means "any label") // - sort (string): name of column for sorting by its value // - reverse (bool): enable reverse sorting @@ -453,52 +454,54 @@ void WebApplication::action_command_setGlobalDlLimit() Preferences::instance()->setGlobalDownloadLimit(limit / 1024.); } -void WebApplication::action_command_getTorrentUpLimit() +void WebApplication::action_command_getTorrentsUpLimit() { CHECK_URI(0); - CHECK_PARAMETERS("hash"); - QString hash = request().posts["hash"]; - QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); - - if (h.is_valid()) - print(QByteArray::number(h.upload_limit())); + CHECK_PARAMETERS("hashes"); + QStringList hashes = request().posts["hashes"].split("|"); + print(btjson::getTorrentsRatesLimits(hashes, false), Http::CONTENT_TYPE_JS); } -void WebApplication::action_command_getTorrentDlLimit() +void WebApplication::action_command_getTorrentsDlLimit() { CHECK_URI(0); - CHECK_PARAMETERS("hash"); - QString hash = request().posts["hash"]; - QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); - - if (h.is_valid()) - print(QByteArray::number(h.download_limit())); + CHECK_PARAMETERS("hashes"); + QStringList hashes = request().posts["hashes"].split("|"); + print(btjson::getTorrentsRatesLimits(hashes, true), Http::CONTENT_TYPE_JS); } -void WebApplication::action_command_setTorrentUpLimit() +void WebApplication::action_command_setTorrentsUpLimit() { CHECK_URI(0); - CHECK_PARAMETERS("hash" << "limit"); - QString hash = request().posts["hash"]; + CHECK_PARAMETERS("hashes" << "limit"); + qlonglong limit = request().posts["limit"].toLongLong(); - if (limit == 0) limit = -1; - QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + if (limit == 0) + limit = -1; - if (h.is_valid()) + QStringList hashes = request().posts["hashes"].split("|"); + foreach (const QString &hash, hashes) { + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + if (h.is_valid()) h.set_upload_limit(limit); + } } -void WebApplication::action_command_setTorrentDlLimit() +void WebApplication::action_command_setTorrentsDlLimit() { CHECK_URI(0); - CHECK_PARAMETERS("hash" << "limit"); - QString hash = request().posts["hash"]; + CHECK_PARAMETERS("hashes" << "limit"); + qlonglong limit = request().posts["limit"].toLongLong(); - if (limit == 0) limit = -1; - QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + if (limit == 0) + limit = -1; - if (h.is_valid()) + QStringList hashes = request().posts["hashes"].split("|"); + foreach (const QString &hash, hashes) { + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + if (h.is_valid()) h.set_download_limit(limit); + } } void WebApplication::action_command_toggleAlternativeSpeedLimits() @@ -541,6 +544,21 @@ void WebApplication::action_command_toggleFirstLastPiecePrio() } } +void WebApplication::action_command_setSuperSeeding() +{ + CHECK_URI(0); + CHECK_PARAMETERS("hashes" << "value"); + bool value = request().posts["value"] == "true"; + QStringList hashes = request().posts["hashes"].split("|"); + foreach (const QString &hash, hashes) { + try { + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + h.super_seeding(value); + } + catch(invalid_handle&) {} + } +} + void WebApplication::action_command_delete() { CHECK_URI(0); diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index b4b6b9b3f..3100cb454 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -68,14 +68,15 @@ private: void action_command_getGlobalDlLimit(); void action_command_setGlobalUpLimit(); void action_command_setGlobalDlLimit(); - void action_command_getTorrentUpLimit(); - void action_command_getTorrentDlLimit(); - void action_command_setTorrentUpLimit(); - void action_command_setTorrentDlLimit(); + void action_command_getTorrentsUpLimit(); + void action_command_getTorrentsDlLimit(); + void action_command_setTorrentsUpLimit(); + void action_command_setTorrentsDlLimit(); void action_command_alternativeSpeedLimitsEnabled(); void action_command_toggleAlternativeSpeedLimits(); void action_command_toggleSequentialDownload(); void action_command_toggleFirstLastPiecePrio(); + void action_command_setSuperSeeding(); void action_command_delete(); void action_command_deletePerm(); void action_command_increasePrio(); diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index e60fa79e5..2f0edbf0f 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -111,6 +111,7 @@
  • QBT_TR(Limit upload rate...)QBT_TR QBT_TR(Limit upload rate...)QBT_TR
  • QBT_TR(Download in sequential order)QBT_TR QBT_TR(Download in sequential order)QBT_TR
  • QBT_TR(Download first and last piece first)QBT_TR QBT_TR(Download first and last piece first)QBT_TR
  • +
  • QBT_TR(Super seeding mode)QBT_TR QBT_TR(Super seeding mode)QBT_TR
  • QBT_TR(Force recheck)QBT_TR QBT_TR(Force recheck)QBT_TR
  • diff --git a/src/webui/www/public/downloadlimit.html b/src/webui/www/public/downloadlimit.html index ca1e521ab..43a54d97c 100644 --- a/src/webui/www/public/downloadlimit.html +++ b/src/webui/www/public/downloadlimit.html @@ -20,10 +20,10 @@
    diff --git a/src/webui/www/public/filters.html b/src/webui/www/public/filters.html index ecc3461c3..1270f4fef 100644 --- a/src/webui/www/public/filters.html +++ b/src/webui/www/public/filters.html @@ -2,6 +2,7 @@
  • QBT_TR(All)QBT_TR
  • QBT_TR(Downloading)QBT_TR
  • QBT_TR(Completed)QBT_TR
  • +
  • QBT_TR(Resumed)QBT_TR
  • QBT_TR(Paused)QBT_TR
  • QBT_TR(Active)QBT_TR
  • QBT_TR(Inactive)QBT_TR
  • diff --git a/src/webui/www/public/scripts/client.js b/src/webui/www/public/scripts/client.js index 9f3d07cc7..7ad60e2a6 100644 --- a/src/webui/www/public/scripts/client.js +++ b/src/webui/www/public/scripts/client.js @@ -27,6 +27,8 @@ myTable = new dynamicTable(); var updatePropertiesPanel = function(){}; var updateMainData = function(){}; var alternativeSpeedLimits = false; +var queueing_enabled = true; +var syncMainDataTimerPeriod = 1500; selected_filter = getLocalStorageItem('selected_filter', 'all'); selected_label = null; @@ -95,6 +97,7 @@ window.addEvent('load', function () { $("downloading_filter").removeClass("selectedFilter"); $("completed_filter").removeClass("selectedFilter"); $("paused_filter").removeClass("selectedFilter"); + $("resumed_filter").removeClass("selectedFilter"); $("active_filter").removeClass("selectedFilter"); $("inactive_filter").removeClass("selectedFilter"); $(f + "_filter").addClass("selectedFilter"); @@ -153,19 +156,6 @@ window.addEvent('load', function () { myTable.rows.erase(); if (response['rid']) syncMainDataLastResponseId = response['rid']; - if ('queueing' in response) { - var queueing_enabled = response['queueing']; - myTable.columns['priority'].force_hide = !queueing_enabled; - myTable.updateColumn('priority'); - if (queueing_enabled) { - $('queueingButtons').removeClass('invisible'); - $('queueingMenuItems').removeClass('invisible'); - } - else { - $('queueingButtons').addClass('invisible'); - $('queueingMenuItems').addClass('invisible'); - } - } if (response['torrents']) for (var key in response['torrents']) { response['torrents'][key]['hash'] = key; @@ -185,7 +175,7 @@ window.addEvent('load', function () { } } clearTimeout(syncMainDataTimer); - syncMainDataTimer = syncMainData.delay(1500); + syncMainDataTimer = syncMainData.delay(syncMainDataTimerPeriod); } }).send(); }; @@ -220,6 +210,29 @@ window.addEvent('load', function () { $('connectionStatus').src = 'images/skin/firewalled.png'; else $('connectionStatus').src = 'images/skin/disconnected.png'; + + if (queueing_enabled != serverState.queueing) { + queueing_enabled = serverState.queueing; + myTable.columns['priority'].force_hide = !queueing_enabled; + myTable.updateColumn('priority'); + if (queueing_enabled) { + $('queueingButtons').removeClass('invisible'); + $('queueingMenuItems').removeClass('invisible'); + } + else { + $('queueingButtons').addClass('invisible'); + $('queueingMenuItems').addClass('invisible'); + } + } + + if (alternativeSpeedLimits != serverState.use_alt_speed_limits) { + alternativeSpeedLimits = serverState.use_alt_speed_limits; + updateAltSpeedIcon(alternativeSpeedLimits); + } + + syncMainDataTimerPeriod = serverState.refresh_interval; + if (syncMainDataTimerPeriod < 500) + syncMainDataTimerPeriod = 500; }; var updateAltSpeedIcon = function(enabled) { @@ -229,16 +242,6 @@ window.addEvent('load', function () { $('alternativeSpeedLimits').src = "images/slow_off.png" } - // Determine whether the alternative speed limits are enabled or not - new Request({url: 'command/alternativeSpeedLimitsEnabled', - method: 'get', - onSuccess : function (isEnabled) { - alternativeSpeedLimits = !!parseInt(isEnabled); - if (alternativeSpeedLimits) - $('alternativeSpeedLimits').src = "images/slow.png" - } - }).send(); - $('alternativeSpeedLimits').addEvent('click', function() { // Change icon immediately to give some feedback updateAltSpeedIcon(!alternativeSpeedLimits); @@ -354,11 +357,20 @@ window.addEvent('load', function () { function closeWindows() { MochaUI.closeAll(); -} +}; -window.addEvent('keydown', function (event) { - if (event.key == 'a' && event.control) { - event.stop(); - myTable.selectAll(); +var keyboardEvents = new Keyboard({ + defaultEventType: 'keydown', + events: { + 'ctrl+a': function(event) { + myTable.selectAll(); + event.preventDefault(); + }, + 'delete': function(event) { + deleteFN(); + event.preventDefault(); + } } }); + +keyboardEvents.activate(); diff --git a/src/webui/www/public/scripts/contextmenu.js b/src/webui/www/public/scripts/contextmenu.js index 2aaff877d..72e60f5e7 100644 --- a/src/webui/www/public/scripts/contextmenu.js +++ b/src/webui/www/public/scripts/contextmenu.js @@ -136,6 +136,7 @@ var ContextMenu = new Class({ all_are_downloaded = true; all_are_paused = true; there_are_paused = false; + all_are_super_seeding = true; var h = myTable.selectedIds(); h.each(function(item, index){ @@ -153,6 +154,8 @@ var ContextMenu = new Class({ if (data['progress'] != 1.0) // not downloaded all_are_downloaded = false; + else if (data['super_seeding'] != true) + all_are_super_seeding = false; state = data['state']; if ((state != 'pausedUP') && (state != 'pausedDL')) @@ -174,6 +177,8 @@ var ContextMenu = new Class({ if (all_are_downloaded) { this.hideItem('SequentialDownload'); this.hideItem('FirstLastPiecePrio'); + this.showItem('SuperSeeding'); + this.setItemChecked('SuperSeeding', all_are_super_seeding); } else { if (!show_seq_dl && show_f_l_piece_prio) this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.addClass('separator'); @@ -192,6 +197,8 @@ var ContextMenu = new Class({ this.setItemChecked('SequentialDownload', all_are_seq_dl); this.setItemChecked('FirstLastPiecePrio', all_are_f_l_piece_prio); + + this.hideItem('SuperSeeding'); } if (all_are_paused) { @@ -234,6 +241,10 @@ var ContextMenu = new Class({ return this; }, + getItemChecked: function(item) { + return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity; + }, + //hide an item hideItem: function(item) { this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible'); diff --git a/src/webui/www/public/scripts/dynamicTable.js b/src/webui/www/public/scripts/dynamicTable.js index 9667ac371..c54152bdb 100644 --- a/src/webui/www/public/scripts/dynamicTable.js +++ b/src/webui/www/public/scripts/dynamicTable.js @@ -261,6 +261,10 @@ var dynamicTable = new Class({ if (!~state.indexOf('paused')) return false; break; + case 'resumed': + if (~state.indexOf('paused')) + return false; + break; case 'active': if ((state != 'uploading') && (state != 'downloading')) return false; @@ -352,6 +356,17 @@ var dynamicTable = new Class({ myTable.selectRow(this.hash); return true; }); + tr.addEvent('dblclick', function (e) { + e.stop(); + myTable.selectRow(this.hash); + var row = myTable.rows.get(this.hash); + var state = row['full_data'].state; + if (~state.indexOf('paused')) + startFN(); + else + pauseFN(); + return true; + }); tr.addEvent('click', function (e) { e.stop(); if (e.control) { diff --git a/src/webui/www/public/scripts/misc.js b/src/webui/www/public/scripts/misc.js index 7087f8281..645353127 100644 --- a/src/webui/www/public/scripts/misc.js +++ b/src/webui/www/public/scripts/misc.js @@ -38,11 +38,11 @@ function friendlyDuration(seconds) { if (minutes < 60) return "QBT_TR(%1m)QBT_TR".replace("%1", parseInt(minutes)); var hours = minutes / 60; - minutes = minutes - hours * 60; + minutes = minutes % 60; if (hours < 24) return "QBT_TR(%1h %2m)QBT_TR".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes)) var days = hours / 24; - hours = hours - days * 24; + hours = hours % 24; if (days < 100) return "QBT_TR(%1d %2h)QBT_TR".replace("%1", parseInt(days)).replace("%2", parseInt(hours)) return "∞"; diff --git a/src/webui/www/public/scripts/mocha-init.js b/src/webui/www/public/scripts/mocha-init.js index 491b12a37..81b746f96 100644 --- a/src/webui/www/public/scripts/mocha-init.js +++ b/src/webui/www/public/scripts/mocha-init.js @@ -29,6 +29,10 @@ function getLocalStorageItem(name, defaultVal) { return val; } +var deleteFN = function() {}; +var startFN = function() {}; +var pauseFN = function() {}; + initializeWindows = function() { function addClickEvent(el, fn) { @@ -103,7 +107,7 @@ initializeWindows = function() { id: 'uploadLimitPage', title: "QBT_TR(Global Upload Speed Limit)QBT_TR", loadMethod: 'iframe', - contentURL: 'uploadlimit.html?hash=global', + contentURL: 'uploadlimit.html?hashes=global', scrollbars: false, resizable: false, maximizable: false, @@ -122,7 +126,7 @@ initializeWindows = function() { id: 'uploadLimitPage', title: "QBT_TR(Torrent Upload Speed Limiting)QBT_TR", loadMethod: 'iframe', - contentURL: 'uploadlimit.html?hash=' + hash, + contentURL: 'uploadlimit.html?hashes=' + h.join("|"), scrollbars: false, resizable: false, maximizable: false, @@ -162,12 +166,27 @@ initializeWindows = function() { } }; + setSuperSeedingFN = function(val) { + var h = myTable.selectedIds(); + if (h.length) { + new Request({ + url: 'command/setSuperSeeding', + method: 'post', + data: { + value: val, + hashes: h.join("|") + } + }).send(); + updateMainData(); + } + }; + globalDownloadLimitFN = function() { new MochaUI.Window({ id: 'downloadLimitPage', title: "QBT_TR(Global Download Speed Limit)QBT_TR", loadMethod: 'iframe', - contentURL: 'downloadlimit.html?hash=global', + contentURL: 'downloadlimit.html?hashes=global', scrollbars: false, resizable: false, maximizable: false, @@ -186,7 +205,7 @@ initializeWindows = function() { id: 'downloadLimitPage', title: "QBT_TR(Torrent Download Speed Limiting)QBT_TR", loadMethod: 'iframe', - contentURL: 'downloadlimit.html?hash=' + hash, + contentURL: 'downloadlimit.html?hashes=' + h.join("|"), scrollbars: false, resizable: false, maximizable: false, @@ -274,7 +293,7 @@ initializeWindows = function() { } }; - ['pause', 'resume', 'recheck'].each(function(item) { + ['pauseAll', 'resumeAll', 'pause', 'resume', 'recheck'].each(function(item) { addClickEvent(item, function(e) { new Event(e).stop(); var h = myTable.selectedIds(); diff --git a/src/webui/www/public/scripts/parametrics.js b/src/webui/www/public/scripts/parametrics.js index 07b7ca379..cda3272f5 100644 --- a/src/webui/www/public/scripts/parametrics.js +++ b/src/webui/www/public/scripts/parametrics.js @@ -14,7 +14,7 @@ Requires: */ MochaUI.extend({ - addUpLimitSlider: function(hash) { + addUpLimitSlider: function(hashes) { if ($('uplimitSliderarea')) { var windowOptions = MochaUI.Windows.windowOptions; var sliderFirst = true; @@ -31,15 +31,15 @@ MochaUI.extend({ maximum = tmp / 1024. } else { - if (hash == "global") + if (hashes[0] == "global") maximum = 10000; else maximum = 1000; } } - // Get torrent upload limit + // Get torrents upload limit // And create slider - if (hash == 'global') { + if (hashes[0] == 'global') { var up_limit = maximum; if (up_limit < 0) up_limit = 0; maximum = 10000; @@ -69,15 +69,21 @@ MochaUI.extend({ } } else { - var req = new Request({ - url: 'command/getTorrentUpLimit', + var req = new Request.JSON({ + url: 'command/getTorrentsUpLimit', + noCache : true, method: 'post', data: { - hash: hash + hashes: hashes.join('|') }, onSuccess: function(data) { if (data) { - var up_limit = data.toInt(); + var up_limit = data[hashes[0]]; + for(var key in data) + if (up_limit != data[key]) { + up_limit = 0; + break; + } if (up_limit < 0) up_limit = 0; var mochaSlide = new Slider($('uplimitSliderarea'), $('uplimitSliderknob'), { steps: maximum, @@ -112,7 +118,7 @@ MochaUI.extend({ } }, - addDlLimitSlider: function(hash) { + addDlLimitSlider: function(hashes) { if ($('dllimitSliderarea')) { var windowOptions = MochaUI.Windows.windowOptions; var sliderFirst = true; @@ -129,15 +135,15 @@ MochaUI.extend({ maximum = tmp / 1024. } else { - if (hash == "global") + if (hashes[0] == "global") maximum = 10000; else maximum = 1000; } } - // Get torrent download limit + // Get torrents download limit // And create slider - if (hash == "global") { + if (hashes[0] == 'global') { var dl_limit = maximum; if (dl_limit < 0) dl_limit = 0; maximum = 10000; @@ -167,15 +173,21 @@ MochaUI.extend({ } } else { - var req = new Request({ - url: 'command/getTorrentDlLimit', + var req = new Request.JSON({ + url: 'command/getTorrentsDlLimit', + noCache : true, method: 'post', data: { - hash: hash + hashes: hashes.join('|') }, onSuccess: function(data) { if (data) { - var dl_limit = data.toInt(); + var dl_limit = data[hashes[0]]; + for(var key in data) + if (dl_limit != data[key]) { + dl_limit = 0; + break; + } if (dl_limit < 0) dl_limit = 0; var mochaSlide = new Slider($('dllimitSliderarea'), $('dllimitSliderknob'), { steps: maximum, diff --git a/src/webui/www/public/scripts/progressbar.js b/src/webui/www/public/scripts/progressbar.js index f4a959950..32fee1fcf 100644 --- a/src/webui/www/public/scripts/progressbar.js +++ b/src/webui/www/public/scripts/progressbar.js @@ -37,7 +37,7 @@ var ProgressBar = new Class({ 'text-align': 'center', 'left': 0, 'top': 0, - 'line-height': vals.height - 2 + 'line-height': vals.height } }); obj.vals.light = new Element('div', { @@ -52,7 +52,7 @@ var ProgressBar = new Class({ 'text-align': 'center', 'left': 0, 'top': 0, - 'line-height': vals.height - 2 + 'line-height': vals.height } }); obj.appendChild(obj.vals.dark); diff --git a/src/webui/www/public/transferlist.html b/src/webui/www/public/transferlist.html index d12e2027a..b65dcd96a 100644 --- a/src/webui/www/public/transferlist.html +++ b/src/webui/www/public/transferlist.html @@ -51,6 +51,9 @@ }, FirstLastPiecePrio : function (element, ref) { toggleFirstLastPiecePrioFN(); + }, + SuperSeeding : function (element, ref) { + setSuperSeedingFN(!ref.getItemChecked('SuperSeeding')); } }, offsets : { diff --git a/src/webui/www/public/uploadlimit.html b/src/webui/www/public/uploadlimit.html index 4b63183b3..733ce393c 100644 --- a/src/webui/www/public/uploadlimit.html +++ b/src/webui/www/public/uploadlimit.html @@ -20,10 +20,10 @@