Revise tag related implementations

Fix #12690.
This commit is contained in:
Chocobo1
2021-04-02 13:45:50 +08:00
parent ab6141edb7
commit fdc186c92f
20 changed files with 257 additions and 50 deletions

View File

@@ -58,6 +58,7 @@ add_library(qbt_base STATIC
net/proxyconfigurationmanager.h
net/reverseresolution.h
net/smtp.h
orderedset.h
preferences.h
profile.h
profile_p.h
@@ -74,6 +75,7 @@ add_library(qbt_base STATIC
search/searchhandler.h
search/searchpluginmanager.h
settingsstorage.h
tagset.h
torrentfileguard.h
torrentfilter.h
types.h
@@ -152,6 +154,7 @@ add_library(qbt_base STATIC
search/searchhandler.cpp
search/searchpluginmanager.cpp
settingsstorage.cpp
tagset.cpp
torrentfileguard.cpp
torrentfilter.cpp
utils/bytearray.cpp

View File

@@ -57,6 +57,7 @@ HEADERS += \
$$PWD/net/proxyconfigurationmanager.h \
$$PWD/net/reverseresolution.h \
$$PWD/net/smtp.h \
$$PWD/orderedset.h \
$$PWD/preferences.h \
$$PWD/profile.h \
$$PWD/profile_p.h \
@@ -74,6 +75,7 @@ HEADERS += \
$$PWD/search/searchpluginmanager.h \
$$PWD/settingsstorage.h \
$$PWD/settingvalue.h \
$$PWD/tagset.h \
$$PWD/torrentfileguard.h \
$$PWD/torrentfilter.h \
$$PWD/types.h \
@@ -152,6 +154,7 @@ SOURCES += \
$$PWD/search/searchhandler.cpp \
$$PWD/search/searchpluginmanager.cpp \
$$PWD/settingsstorage.cpp \
$$PWD/tagset.cpp \
$$PWD/torrentfileguard.cpp \
$$PWD/torrentfilter.cpp \
$$PWD/utils/bytearray.cpp \

View File

@@ -30,10 +30,10 @@
#include <optional>
#include <QSet>
#include <QString>
#include <QVector>
#include "base/tagset.h"
#include "torrent.h"
#include "torrentcontentlayout.h"
@@ -45,7 +45,7 @@ namespace BitTorrent
{
QString name;
QString category;
QSet<QString> tags;
TagSet tags;
QString savePath;
bool disableTempPath = false; // e.g. for imported torrents
bool sequential = false;

View File

@@ -45,6 +45,7 @@
#include "base/global.h"
#include "base/logger.h"
#include "base/profile.h"
#include "base/tagset.h"
#include "base/utils/fs.h"
#include "base/utils/io.h"
#include "base/utils/string.h"
@@ -82,7 +83,7 @@ namespace
using ListType = lt::entry::list_type;
ListType setToEntryList(const QSet<QString> &input)
ListType setToEntryList(const TagSet &input)
{
ListType entryList;
entryList.reserve(input.size());

View File

@@ -30,9 +30,9 @@
#include <libtorrent/add_torrent_params.hpp>
#include <QSet>
#include <QString>
#include "base/tagset.h"
#include "torrent.h"
#include "torrentcontentlayout.h"
@@ -44,7 +44,7 @@ namespace BitTorrent
QString name;
QString category;
QSet<QString> tags;
TagSet tags;
QString savePath;
TorrentContentLayout contentLayout = TorrentContentLayout::Original;
TorrentOperatingMode operatingMode = TorrentOperatingMode::AutoManaged;

View File

@@ -33,6 +33,7 @@
#include <QString>
#include <QtContainerFwd>
#include "base/tagset.h"
#include "abstractfilestorage.h"
class QBitArray;
@@ -168,7 +169,7 @@ namespace BitTorrent
virtual bool belongsToCategory(const QString &category) const = 0;
virtual bool setCategory(const QString &category) = 0;
virtual QSet<QString> tags() const = 0;
virtual TagSet tags() const = 0;
virtual bool hasTag(const QString &tag) const = 0;
virtual bool addTag(const QString &tag) = 0;
virtual bool removeTag(const QString &tag) = 0;

View File

@@ -703,7 +703,7 @@ bool TorrentImpl::belongsToCategory(const QString &category) const
return false;
}
QSet<QString> TorrentImpl::tags() const
TagSet TorrentImpl::tags() const
{
return m_tags;
}
@@ -717,18 +717,18 @@ bool TorrentImpl::addTag(const QString &tag)
{
if (!Session::isValidTag(tag))
return false;
if (hasTag(tag))
return false;
if (!hasTag(tag))
if (!m_session->hasTag(tag))
{
if (!m_session->hasTag(tag))
if (!m_session->addTag(tag))
return false;
m_tags.insert(tag);
m_session->handleTorrentNeedSaveResumeData(this);
m_session->handleTorrentTagAdded(this, tag);
return true;
if (!m_session->addTag(tag))
return false;
}
return false;
m_tags.insert(tag);
m_session->handleTorrentNeedSaveResumeData(this);
m_session->handleTorrentTagAdded(this, tag);
return true;
}
bool TorrentImpl::removeTag(const QString &tag)

View File

@@ -42,10 +42,10 @@
#include <QMap>
#include <QObject>
#include <QQueue>
#include <QSet>
#include <QString>
#include <QVector>
#include "base/tagset.h"
#include "infohash.h"
#include "speedmonitor.h"
#include "torrent.h"
@@ -115,7 +115,7 @@ namespace BitTorrent
bool belongsToCategory(const QString &category) const override;
bool setCategory(const QString &category) override;
QSet<QString> tags() const override;
TagSet tags() const override;
bool hasTag(const QString &tag) const override;
bool addTag(const QString &tag) override;
bool removeTag(const QString &tag) override;
@@ -247,7 +247,7 @@ namespace BitTorrent
QString actualStorageLocation() const;
private:
typedef std::function<void ()> EventTrigger;
using EventTrigger = std::function<void ()>;
void updateStatus();
void updateStatus(const lt::torrent_status &nativeStatus);
@@ -315,7 +315,7 @@ namespace BitTorrent
QString m_name;
QString m_savePath;
QString m_category;
QSet<QString> m_tags;
TagSet m_tags;
qreal m_ratioLimit;
int m_seedingTimeLimit;
TorrentOperatingMode m_operatingMode;

108
src/base/orderedset.h Normal file
View File

@@ -0,0 +1,108 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2021 Mike Tzou (Chocobo1)
*
* 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 <functional>
#include <set>
#include <type_traits>
#include "algorithm.h"
template <typename T, typename Compare = std::less<T>>
class OrderedSet : public std::set<T, Compare>
{
using ThisType = OrderedSet<T, Compare>;
public:
using BaseType = std::set<T, Compare>;
using key_type = typename BaseType::key_type;
using value_type = typename BaseType::value_type;
using BaseType::BaseType;
using BaseType::operator=;
// The following are custom functions that are in line with Qt API interface, such as `QSet`
#if __cplusplus < 202002L
bool contains(const key_type &value) const
{
return (BaseType::find(value) != BaseType::cend());
}
#endif
int count() const
{
return static_cast<int>(BaseType::size());
}
ThisType &intersect(const ThisType &other)
{
Algorithm::removeIf(*this, [&other](const value_type &value) -> bool
{
return !other.contains(value);
});
return *this;
}
bool isEmpty() const
{
return BaseType::empty();
}
template <typename std::enable_if_t<std::is_same_v<value_type, QString>, int> = 0>
QString join(const QString &separator) const
{
auto iter = BaseType::cbegin();
if (iter == BaseType::cend())
return {};
QString ret = *iter;
++iter;
while (iter != BaseType::cend())
{
ret.push_back(separator + *iter);
++iter;
}
return ret;
}
bool remove(const key_type &value)
{
return (BaseType::erase(value) > 0);
}
ThisType &unite(const ThisType &other)
{
BaseType::insert(other.cbegin(), other.cend());
return *this;
}
};

37
src/base/tagset.cpp Normal file
View File

@@ -0,0 +1,37 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2021 Mike Tzou (Chocobo1)
*
* 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 "tagset.h"
bool TagLessThan::operator()(const QString &left, const QString &right) const
{
const int result = m_compare(left, right);
if (result != 0)
return (result < 0);
return (m_subCompare(left, right) < 0);
}

49
src/base/tagset.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2021 Mike Tzou (Chocobo1)
*
* 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 <QMetaType>
#include <QString>
#include "base/orderedset.h"
#include "base/utils/compare.h"
class TagLessThan
{
public:
bool operator()(const QString &left, const QString &right) const;
private:
Utils::Compare::NaturalCompare<Qt::CaseInsensitive> m_compare;
Utils::Compare::NaturalCompare<Qt::CaseSensitive> m_subCompare;
};
using TagSet = OrderedSet<QString, TagLessThan>;
Q_DECLARE_METATYPE(TagSet)