Browse Source

Implement TorrentCategoryDialog class

adaptive-webui-19844
Vladimir Golovnev (Glassez) 7 years ago
parent
commit
3ec992474d
No known key found for this signature in database
GPG Key ID: 52A2C7DEE2DFA6F7
  1. 5
      src/base/bittorrent/session.cpp
  2. 2
      src/base/bittorrent/session.h
  3. 3
      src/gui/CMakeLists.txt
  4. 2
      src/gui/addnewtorrentdialog.cpp
  5. 2
      src/gui/categoryfiltermodel.cpp
  6. 55
      src/gui/categoryfilterwidget.cpp
  7. 2
      src/gui/categoryfilterwidget.h
  8. 5
      src/gui/gui.pri
  9. 2
      src/gui/rss/automatedrssdownloader.cpp
  10. 125
      src/gui/torrentcategorydialog.cpp
  11. 58
      src/gui/torrentcategorydialog.h
  12. 129
      src/gui/torrentcategorydialog.ui
  13. 25
      src/gui/transferlistwidget.cpp
  14. 2
      src/webui/btjson.cpp

5
src/base/bittorrent/session.cpp

@ -698,9 +698,9 @@ QStringList Session::expandCategory(const QString &category) @@ -698,9 +698,9 @@ QStringList Session::expandCategory(const QString &category)
return result;
}
QStringList Session::categories() const
const QStringMap &Session::categories() const
{
return m_categories.keys();
return m_categories;
}
QString Session::categorySavePath(const QString &categoryName) const
@ -746,6 +746,7 @@ bool Session::editCategory(const QString &name, const QString &savePath) @@ -746,6 +746,7 @@ bool Session::editCategory(const QString &name, const QString &savePath)
if (categorySavePath(name) == savePath) return false;
m_categories[name] = savePath;
m_storedCategories = map_cast(m_categories);
if (isDisableAutoTMMWhenCategorySavePathChanged()) {
foreach (TorrentHandle *const torrent, torrents())
if (torrent->category() == name)

2
src/base/bittorrent/session.h

@ -251,7 +251,7 @@ namespace BitTorrent @@ -251,7 +251,7 @@ namespace BitTorrent
// returns category itself and all top level categories
static QStringList expandCategory(const QString &category);
QStringList categories() const;
const QStringMap &categories() const;
QString categorySavePath(const QString &categoryName) const;
bool addCategory(const QString &name, const QString &savePath = "");
bool editCategory(const QString &name, const QString &savePath);

3
src/gui/CMakeLists.txt

@ -59,6 +59,7 @@ statusbar.h @@ -59,6 +59,7 @@ statusbar.h
tagfiltermodel.h
tagfilterproxymodel.h
tagfilterwidget.h
torrentcategorydialog.h
torrentcontentfiltermodel.h
torrentcontentmodel.h
torrentcontentmodelfile.h
@ -102,6 +103,7 @@ statusbar.cpp @@ -102,6 +103,7 @@ statusbar.cpp
tagfiltermodel.cpp
tagfilterproxymodel.cpp
tagfilterwidget.cpp
torrentcategorydialog.cpp
torrentcontentfiltermodel.cpp
torrentcontentmodel.cpp
torrentcontentmodelfile.cpp
@ -144,6 +146,7 @@ addnewtorrentdialog.ui @@ -144,6 +146,7 @@ addnewtorrentdialog.ui
autoexpandabledialog.ui
statsdialog.ui
optionsdlg.ui
torrentcategorydialog.ui
torrentcreatordlg.ui
shutdownconfirmdlg.ui
)

2
src/gui/addnewtorrentdialog.cpp

@ -121,7 +121,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP @@ -121,7 +121,7 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
ui->doNotDeleteTorrentCheckBox->setVisible(TorrentFileGuard::autoDeleteMode() != TorrentFileGuard::Never);
// Load categories
QStringList categories = session->categories();
QStringList categories = session->categories().keys();
std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive);
QString defaultCategory = settings()->loadValue(KEY_DEFAULTCATEGORY).toString();

2
src/gui/categoryfiltermodel.cpp

@ -405,7 +405,7 @@ void CategoryFilterModel::populate() @@ -405,7 +405,7 @@ void CategoryFilterModel::populate()
, [](Torrent *torrent) { return torrent->category().isEmpty(); })));
using Torrent = BitTorrent::TorrentHandle;
foreach (const QString &category, session->categories()) {
foreach (const QString &category, session->categories().keys()) {
if (m_isSubcategoriesEnabled) {
CategoryModelItem *parent = m_rootItem;
foreach (const QString &subcat, session->expandCategory(category)) {

55
src/gui/categoryfilterwidget.cpp

@ -36,10 +36,10 @@ @@ -36,10 +36,10 @@
#include "base/bittorrent/session.h"
#include "base/utils/misc.h"
#include "autoexpandabledialog.h"
#include "categoryfiltermodel.h"
#include "categoryfilterproxymodel.h"
#include "guiiconprovider.h"
#include "torrentcategorydialog.h"
namespace
{
@ -124,6 +124,11 @@ void CategoryFilterWidget::showMenu(QPoint) @@ -124,6 +124,11 @@ void CategoryFilterWidget::showMenu(QPoint)
connect(addSubAct, &QAction::triggered, this, &CategoryFilterWidget::addSubcategory);
}
QAction *editAct = menu.addAction(
GuiIconProvider::instance()->getIcon("document-edit")
, tr("Edit category..."));
connect(editAct, &QAction::triggered, this, &CategoryFilterWidget::editCategory);
QAction *removeAct = menu.addAction(
GuiIconProvider::instance()->getIcon("list-remove")
, tr("Remove category"));
@ -199,53 +204,19 @@ void CategoryFilterWidget::rowsInserted(const QModelIndex &parent, int start, in @@ -199,53 +204,19 @@ void CategoryFilterWidget::rowsInserted(const QModelIndex &parent, int start, in
updateGeometry();
}
QString CategoryFilterWidget::askCategoryName()
{
bool ok;
QString category = "";
bool invalid;
do {
invalid = false;
category = AutoExpandableDialog::getText(
this, tr("New Category"), tr("Category:"), QLineEdit::Normal, category, &ok);
if (ok && !category.isEmpty()) {
if (!BitTorrent::Session::isValidCategoryName(category)) {
QMessageBox::warning(
this, tr("Invalid category name")
, tr("Category name must not contain '\\'.\n"
"Category name must not start/end with '/'.\n"
"Category name must not contain '//' sequence."));
invalid = true;
}
}
} while (invalid);
return ok ? category : QString();
}
void CategoryFilterWidget::addCategory()
{
const QString category = askCategoryName();
if (category.isEmpty()) return;
if (BitTorrent::Session::instance()->categories().contains(category))
QMessageBox::warning(this, tr("Category exists"), tr("Category name already exists."));
else
BitTorrent::Session::instance()->addCategory(category);
TorrentCategoryDialog::createCategory(this);
}
void CategoryFilterWidget::addSubcategory()
{
const QString subcat = askCategoryName();
if (subcat.isEmpty()) return;
const QString category = QString(QStringLiteral("%1/%2")).arg(currentCategory()).arg(subcat);
TorrentCategoryDialog::createCategory(this, currentCategory());
}
if (BitTorrent::Session::instance()->categories().contains(category))
QMessageBox::warning(this, tr("Category exists")
, tr("Subcategory name already exists in selected category."));
else
BitTorrent::Session::instance()->addCategory(category);
void CategoryFilterWidget::editCategory()
{
TorrentCategoryDialog::editCategory(this, currentCategory());
}
void CategoryFilterWidget::removeCategory()
@ -261,7 +232,7 @@ void CategoryFilterWidget::removeCategory() @@ -261,7 +232,7 @@ void CategoryFilterWidget::removeCategory()
void CategoryFilterWidget::removeUnusedCategories()
{
auto session = BitTorrent::Session::instance();
foreach (const QString &category, session->categories())
foreach (const QString &category, session->categories().keys())
if (model()->data(static_cast<CategoryFilterProxyModel *>(model())->index(category), Qt::UserRole) == 0)
session->removeCategory(category);
updateGeometry();

2
src/gui/categoryfilterwidget.h

@ -50,6 +50,7 @@ private slots: @@ -50,6 +50,7 @@ private slots:
void callUpdateGeometry();
void addCategory();
void addSubcategory();
void editCategory();
void removeCategory();
void removeUnusedCategories();
@ -57,7 +58,6 @@ private: @@ -57,7 +58,6 @@ private:
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
void rowsInserted(const QModelIndex &parent, int start, int end) override;
QString askCategoryName();
int m_defaultIndentation;
};

5
src/gui/gui.pri

@ -11,6 +11,7 @@ HEADERS += \ @@ -11,6 +11,7 @@ HEADERS += \
$$PWD/transferlistdelegate.h \
$$PWD/transferlistfilterswidget.h \
$$PWD/transferlistsortmodel.h \
$$PWD/torrentcategorydialog.h \
$$PWD/torrentcontentmodel.h \
$$PWD/torrentcontentmodelitem.h \
$$PWD/torrentcontentmodelfolder.h \
@ -69,6 +70,7 @@ SOURCES += \ @@ -69,6 +70,7 @@ SOURCES += \
$$PWD/transferlistsortmodel.cpp \
$$PWD/transferlistdelegate.cpp \
$$PWD/transferlistfilterswidget.cpp \
$$PWD/torrentcategorydialog.cpp \
$$PWD/torrentcontentmodel.cpp \
$$PWD/torrentcontentmodelitem.cpp \
$$PWD/torrentcontentmodelfolder.cpp \
@ -149,6 +151,7 @@ FORMS += \ @@ -149,6 +151,7 @@ FORMS += \
$$PWD/cookiesdialog.ui \
$$PWD/banlistoptions.ui \
$$PWD/rss/rsswidget.ui \
$$PWD/rss/automatedrssdownloader.ui
$$PWD/rss/automatedrssdownloader.ui \
$$PWD/torrentcategorydialog.ui
RESOURCES += $$PWD/about.qrc

2
src/gui/rss/automatedrssdownloader.cpp

@ -305,7 +305,7 @@ void AutomatedRssDownloader::clearRuleDefinitionBox() @@ -305,7 +305,7 @@ void AutomatedRssDownloader::clearRuleDefinitionBox()
void AutomatedRssDownloader::initCategoryCombobox()
{
// Load torrent categories
QStringList categories = BitTorrent::Session::instance()->categories();
QStringList categories = BitTorrent::Session::instance()->categories().keys();
std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive);
m_ui->comboCategory->addItem("");
m_ui->comboCategory->addItems(categories);

125
src/gui/torrentcategorydialog.cpp

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include "torrentcategorydialog.h"
#include <QMap>
#include <QMessageBox>
#include "base/bittorrent/session.h"
#include "ui_torrentcategorydialog.h"
TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent)
: QDialog {parent}
, m_ui {new Ui::TorrentCategoryDialog}
{
m_ui->setupUi(this);
m_ui->comboSavePath->setMode(FileSystemPathEdit::Mode::DirectorySave);
m_ui->comboSavePath->setDialogCaption(tr("Choose save path"));
}
TorrentCategoryDialog::~TorrentCategoryDialog()
{
delete m_ui;
}
QString TorrentCategoryDialog::createCategory(QWidget *parent, const QString &parentCategoryName)
{
using BitTorrent::Session;
QString newCategoryName {parentCategoryName};
if (!newCategoryName.isEmpty())
newCategoryName += QLatin1Char('/');
newCategoryName += tr("New Category");
TorrentCategoryDialog dialog(parent);
dialog.setCategoryName(newCategoryName);
while (dialog.exec() == TorrentCategoryDialog::Accepted) {
newCategoryName = dialog.categoryName();
if (!BitTorrent::Session::isValidCategoryName(newCategoryName)) {
QMessageBox::critical(
parent, tr("Invalid category name")
, tr("Category name cannot contain '\\'.\n"
"Category name cannot start/end with '/'.\n"
"Category name cannot contain '//' sequence."));
}
else if (BitTorrent::Session::instance()->categories().contains(newCategoryName)) {
QMessageBox::critical(
parent, tr("Category creation error")
, tr("Category with the given name already exists.\n"
"Please choose a different name and try again."));
}
else {
Session::instance()->addCategory(newCategoryName, dialog.savePath());
return newCategoryName;
}
}
return {};
}
void TorrentCategoryDialog::editCategory(QWidget *parent, const QString &categoryName)
{
using BitTorrent::Session;
Q_ASSERT(Session::instance()->categories().contains(categoryName));
TorrentCategoryDialog dialog(parent);
dialog.setCategoryNameEditable(false);
dialog.setCategoryName(categoryName);
dialog.setSavePath(Session::instance()->categories()[categoryName]);
if (dialog.exec() == TorrentCategoryDialog::Accepted) {
Session::instance()->editCategory(categoryName, dialog.savePath());
}
}
void TorrentCategoryDialog::setCategoryNameEditable(bool editable)
{
m_ui->textCategoryName->setEnabled(editable);
}
QString TorrentCategoryDialog::categoryName() const
{
return m_ui->textCategoryName->text();
}
void TorrentCategoryDialog::setCategoryName(const QString &categoryName)
{
m_ui->textCategoryName->setText(categoryName);
}
QString TorrentCategoryDialog::savePath() const
{
return m_ui->comboSavePath->selectedPath();
}
void TorrentCategoryDialog::setSavePath(const QString &savePath)
{
m_ui->comboSavePath->setSelectedPath(savePath);
}

58
src/gui/torrentcategorydialog.h

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#pragma once
#include <QDialog>
namespace Ui
{
class TorrentCategoryDialog;
}
class TorrentCategoryDialog : public QDialog
{
Q_OBJECT
Q_DISABLE_COPY(TorrentCategoryDialog)
public:
static QString createCategory(QWidget *parent, const QString &parentCategoryName = QString());
static void editCategory(QWidget *parent, const QString &categoryName);
explicit TorrentCategoryDialog(QWidget *parent = nullptr);
~TorrentCategoryDialog() override;
void setCategoryNameEditable(bool editable);
QString categoryName() const;
void setCategoryName(const QString &categoryName);
QString savePath() const;
void setSavePath(const QString &savePath);
private:
Ui::TorrentCategoryDialog *m_ui;
};

129
src/gui/torrentcategorydialog.ui

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TorrentCategoryDialog</class>
<widget class="QDialog" name="TorrentCategoryDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>100</height>
</rect>
</property>
<property name="windowTitle">
<string>Torrent Category Properties</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelCategoryName">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="textCategoryName"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelSavePath">
<property name="text">
<string>Save path:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="FileSystemPathComboEdit" name="comboSavePath" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FileSystemPathComboEdit</class>
<extends>QWidget</extends>
<header>fspathedit.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TorrentCategoryDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TorrentCategoryDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

25
src/gui/transferlistwidget.cpp

@ -56,6 +56,7 @@ @@ -56,6 +56,7 @@
#include "optionsdlg.h"
#include "previewselect.h"
#include "speedlimitdlg.h"
#include "torrentcategorydialog.h"
#include "torrentmodel.h"
#include "transferlistdelegate.h"
#include "transferlistsortmodel.h"
@ -729,25 +730,9 @@ void TransferListWidget::setSelectedAutoTMMEnabled(bool enabled) const @@ -729,25 +730,9 @@ void TransferListWidget::setSelectedAutoTMMEnabled(bool enabled) const
void TransferListWidget::askNewCategoryForSelection()
{
// Ask for category
bool ok;
bool invalid;
do {
invalid = false;
const QString category = AutoExpandableDialog::getText(this, tr("New Category"), tr("Category:"), QLineEdit::Normal, "", &ok).trimmed();
if (ok && !category.isEmpty()) {
if (!BitTorrent::Session::isValidCategoryName(category)) {
QMessageBox::warning(this, tr("Invalid category name"),
tr("Category name must not contain '\\'.\n"
"Category name must not start/end with '/'.\n"
"Category name must not contain '//' sequence."));
invalid = true;
}
else {
setSelectionCategory(category);
}
}
} while(invalid);
const QString newCategoryName = TorrentCategoryDialog::createCategory(this);
if (!newCategoryName.isEmpty())
setSelectionCategory(newCategoryName);
}
void TransferListWidget::askAddTagsForSelection()
@ -998,7 +983,7 @@ void TransferListWidget::displayListMenu(const QPoint&) @@ -998,7 +983,7 @@ void TransferListWidget::displayListMenu(const QPoint&)
if (selectedIndexes.size() == 1)
listMenu.addAction(&actionRename);
// Category Menu
QStringList categories = BitTorrent::Session::instance()->categories();
QStringList categories = BitTorrent::Session::instance()->categories().keys();
std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive);
QList<QAction*> categoryActions;
QMenu *categoryMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Category"));

2
src/webui/btjson.cpp

@ -651,7 +651,7 @@ QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData @@ -651,7 +651,7 @@ QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData
data["torrents"] = torrents;
QVariantList categories;
foreach (const QString &category, session->categories())
foreach (const QString &category, session->categories().keys())
categories << category;
data["categories"] = categories;

Loading…
Cancel
Save