Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't forget to update filter items #20030

Merged
merged 2 commits into from Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 57 additions & 20 deletions src/gui/transferlistfilters/categoryfiltermodel.cpp
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2016-2023 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
Expand Down Expand Up @@ -38,6 +38,9 @@
class CategoryModelItem
{
public:
inline static const QString UID_ALL {QChar(1)};
inline static const QString UID_UNCATEGORIZED;

CategoryModelItem() = default;

CategoryModelItem(CategoryModelItem *parent, const QString &categoryName, const int torrentsCount = 0)
Expand Down Expand Up @@ -99,9 +102,21 @@ class CategoryModelItem

int pos() const
{
if (!m_parent) return -1;
if (!m_parent)
return -1;

if (const int posByName = m_parent->m_childUids.indexOf(m_name); posByName >= 0)
return posByName;

// special cases
if (this == m_parent->m_children[UID_ALL])
return 0;

if (this == m_parent->m_children[UID_UNCATEGORIZED])
return 1;

return m_parent->m_childUids.indexOf(m_name);
Q_ASSERT(false);
return -1;
}

bool hasChild(const QString &name) const
Expand Down Expand Up @@ -202,7 +217,8 @@ int CategoryFilterModel::columnCount(const QModelIndex &) const

QVariant CategoryFilterModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return {};
if (!index.isValid())
return {};

const auto *item = static_cast<const CategoryModelItem *>(index.internalPointer());

Expand Down Expand Up @@ -248,8 +264,8 @@ QModelIndex CategoryFilterModel::index(int row, int column, const QModelIndex &p
if (parent.isValid() && (parent.column() != 0))
return {};

auto *parentItem = parent.isValid() ? static_cast<CategoryModelItem *>(parent.internalPointer())
: m_rootItem;
auto *parentItem = parent.isValid()
? static_cast<CategoryModelItem *>(parent.internalPointer()) : m_rootItem;
if (row < parentItem->childCount())
return createIndex(row, column, parentItem->childAt(row));

Expand All @@ -262,7 +278,8 @@ QModelIndex CategoryFilterModel::parent(const QModelIndex &index) const
return {};

auto *item = static_cast<CategoryModelItem *>(index.internalPointer());
if (!item) return {};
if (!item)
return {};

return this->index(item->parent());
}
Expand All @@ -276,7 +293,8 @@ int CategoryFilterModel::rowCount(const QModelIndex &parent) const
return m_rootItem->childCount();

auto *item = static_cast<CategoryModelItem *>(parent.internalPointer());
if (!item) return 0;
if (!item)
return 0;

return item->childCount();
}
Expand All @@ -288,13 +306,16 @@ QModelIndex CategoryFilterModel::index(const QString &categoryName) const

QString CategoryFilterModel::categoryName(const QModelIndex &index) const
{
if (!index.isValid()) return {};
if (!index.isValid())
return {};

return static_cast<CategoryModelItem *>(index.internalPointer())->fullName();
}

QModelIndex CategoryFilterModel::index(CategoryModelItem *item) const
{
if (!item || !item->parent()) return {};
if (!item || !item->parent())
return {};

return index(item->pos(), 0, index(item->parent()));
}
Expand Down Expand Up @@ -337,8 +358,17 @@ void CategoryFilterModel::torrentsLoaded(const QVector<BitTorrent::Torrent *> &t
Q_ASSERT(item);

item->increaseTorrentsCount();
QModelIndex i = index(item);
while (i.isValid())
{
emit dataChanged(i, i);
i = parent(i);
}

m_rootItem->childAt(0)->increaseTorrentsCount();
}

emit dataChanged(index(0, 0), index(0, 0));
}

void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::Torrent *const torrent)
Expand All @@ -347,18 +377,24 @@ void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::Torrent *const tor
Q_ASSERT(item);

item->decreaseTorrentsCount();
QModelIndex i = index(item);
while (i.isValid())
{
emit dataChanged(i, i);
i = parent(i);
}

m_rootItem->childAt(0)->decreaseTorrentsCount();
emit dataChanged(index(0, 0), index(0, 0));
}

void CategoryFilterModel::torrentCategoryChanged(BitTorrent::Torrent *const torrent, const QString &oldCategory)
{
QModelIndex i;

auto *item = findItem(oldCategory);
Q_ASSERT(item);

item->decreaseTorrentsCount();
i = index(item);
QModelIndex i = index(item);
while (i.isValid())
{
emit dataChanged(i, i);
Expand Down Expand Up @@ -392,17 +428,16 @@ void CategoryFilterModel::populate()
const auto torrents = session->torrents();
m_isSubcategoriesEnabled = session->isSubcategoriesEnabled();

const QString UID_ALL;
const QString UID_UNCATEGORIZED(QChar(1));

// All torrents
m_rootItem->addChild(UID_ALL, new CategoryModelItem(nullptr, tr("All"), torrents.count()));
m_rootItem->addChild(CategoryModelItem::UID_ALL
, new CategoryModelItem(nullptr, tr("All"), torrents.count()));

// Uncategorized torrents
using Torrent = BitTorrent::Torrent;
const int torrentsCount = std::count_if(torrents.begin(), torrents.end()
, [](Torrent *torrent) { return torrent->category().isEmpty(); });
m_rootItem->addChild(UID_UNCATEGORIZED, new CategoryModelItem(nullptr, tr("Uncategorized"), torrentsCount));
, [](Torrent *torrent) { return torrent->category().isEmpty(); });
m_rootItem->addChild(CategoryModelItem::UID_UNCATEGORIZED
, new CategoryModelItem(nullptr, tr("Uncategorized"), torrentsCount));

using BitTorrent::Torrent;
if (m_isSubcategoriesEnabled)
Expand Down Expand Up @@ -446,7 +481,9 @@ CategoryModelItem *CategoryFilterModel::findItem(const QString &fullName) const
for (const QString &subcat : asConst(BitTorrent::Session::expandCategory(fullName)))
{
const QString subcatName = shortName(subcat);
if (!item->hasChild(subcatName)) return nullptr;
if (!item->hasChild(subcatName))
return nullptr;

item = item->child(subcatName);
}

Expand Down
2 changes: 1 addition & 1 deletion src/gui/transferlistfilters/categoryfiltermodel.h
@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2016 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2016-2023 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
Expand Down
54 changes: 46 additions & 8 deletions src/gui/transferlistfilters/tagfiltermodel.cpp
@@ -1,5 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2017 Tony Gregerson <tony.gregerson@gmail.com>
*
* This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -36,6 +37,9 @@
#include "base/global.h"
#include "gui/uithememanager.h"

const int ROW_ALL = 0;
const int ROW_UNTAGGED = 1;

namespace
{
QString getSpecialAllTag()
Expand Down Expand Up @@ -203,29 +207,37 @@ void TagFilterModel::tagRemoved(const QString &tag)
void TagFilterModel::torrentTagAdded(BitTorrent::Torrent *const torrent, const QString &tag)
{
if (torrent->tags().count() == 1)
{
untaggedItem()->decreaseTorrentsCount();
const QModelIndex i = index(ROW_UNTAGGED, 0);
emit dataChanged(i, i);
}

const int row = findRow(tag);
Q_ASSERT(isValidRow(row));
TagModelItem &item = m_tagItems[row];

item.increaseTorrentsCount();
const QModelIndex i = index(row, 0, QModelIndex());
const QModelIndex i = index(row, 0);
emit dataChanged(i, i);
}

void TagFilterModel::torrentTagRemoved(BitTorrent::Torrent *const torrent, const QString &tag)
{
if (torrent->tags().empty())
{
untaggedItem()->increaseTorrentsCount();
const QModelIndex i = index(ROW_UNTAGGED, 0);
emit dataChanged(i, i);
}

const int row = findRow(tag);
if (row < 0)
return;

m_tagItems[row].decreaseTorrentsCount();

const QModelIndex i = index(row, 0, QModelIndex());
const QModelIndex i = index(row, 0);
emit dataChanged(i, i);
}

Expand All @@ -242,17 +254,39 @@ void TagFilterModel::torrentsLoaded(const QVector<BitTorrent::Torrent *> &torren
for (TagModelItem *item : items)
item->increaseTorrentsCount();
}

emit dataChanged(index(0, 0), index((rowCount() - 1), 0));
}

void TagFilterModel::torrentAboutToBeRemoved(BitTorrent::Torrent *const torrent)
{
allTagsItem()->decreaseTorrentsCount();

{
const QModelIndex i = index(ROW_ALL, 0);
emit dataChanged(i, i);
}

if (torrent->tags().isEmpty())
{
untaggedItem()->decreaseTorrentsCount();

for (TagModelItem *item : asConst(findItems(torrent->tags())))
item->decreaseTorrentsCount();
const QModelIndex i = index(ROW_UNTAGGED, 0);
emit dataChanged(i, i);
}
else
{
for (const QString &tag : asConst(torrent->tags()))
{
const int row = findRow(tag);
Q_ASSERT(isValidRow(row));
if (!isValidRow(row)) [[unlikely]]
continue;

m_tagItems[row].decreaseTorrentsCount();
const QModelIndex i = index(row, 0);
emit dataChanged(i, i);
}
}
}

QString TagFilterModel::tagDisplayName(const QString &tag)
Expand Down Expand Up @@ -299,11 +333,15 @@ void TagFilterModel::removeFromModel(int row)

int TagFilterModel::findRow(const QString &tag) const
{
if (!BitTorrent::Session::isValidTag(tag))
return -1;

for (int i = 0; i < m_tagItems.size(); ++i)
{
if (m_tagItems[i].tag() == tag)
return i;
}

return -1;
}

Expand Down Expand Up @@ -333,11 +371,11 @@ QVector<TagModelItem *> TagFilterModel::findItems(const TagSet &tags)
TagModelItem *TagFilterModel::allTagsItem()
{
Q_ASSERT(!m_tagItems.isEmpty());
return &m_tagItems[0];
return &m_tagItems[ROW_ALL];
}

TagModelItem *TagFilterModel::untaggedItem()
{
Q_ASSERT(m_tagItems.size() > 1);
return &m_tagItems[1];
Q_ASSERT(m_tagItems.size() > ROW_UNTAGGED);
return &m_tagItems[ROW_UNTAGGED];
}
1 change: 1 addition & 0 deletions src/gui/transferlistfilters/tagfiltermodel.h
@@ -1,5 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2017 Tony Gregerson <tony.gregerson@gmail.com>
*
* This program is free software; you can redistribute it and/or
Expand Down