Fix handling of tags containing '&' character

PR #21024.
Closes #20773.
This commit is contained in:
Vladimir Golovnev 2024-07-07 08:24:30 +03:00 committed by Vladimir Golovnev (Glassez)
parent 5e81347933
commit 95e431a296
No known key found for this signature in database
GPG key ID: 52A2C7DEE2DFA6F7
4 changed files with 39 additions and 5 deletions

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2023-2024 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -37,6 +37,7 @@
#include "base/global.h" #include "base/global.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
#include "flowlayout.h" #include "flowlayout.h"
#include "utils.h"
#include "ui_torrenttagsdialog.h" #include "ui_torrenttagsdialog.h"
@ -55,7 +56,7 @@ TorrentTagsDialog::TorrentTagsDialog(const TagSet &initialTags, QWidget *parent)
auto *tagsLayout = new FlowLayout(m_ui->scrollArea); auto *tagsLayout = new FlowLayout(m_ui->scrollArea);
for (const QString &tag : asConst(initialTags.united(BitTorrent::Session::instance()->tags()))) for (const QString &tag : asConst(initialTags.united(BitTorrent::Session::instance()->tags())))
{ {
auto *tagWidget = new QCheckBox(tag); auto *tagWidget = new QCheckBox(Utils::Gui::tagToWidgetText(tag));
if (initialTags.contains(tag)) if (initialTags.contains(tag))
tagWidget->setChecked(true); tagWidget->setChecked(true);
tagsLayout->addWidget(tagWidget); tagsLayout->addWidget(tagWidget);
@ -83,7 +84,7 @@ TagSet TorrentTagsDialog::tags() const
{ {
const auto *tagWidget = static_cast<QCheckBox *>(layout->itemAt(i)->widget()); const auto *tagWidget = static_cast<QCheckBox *>(layout->itemAt(i)->widget());
if (tagWidget->isChecked()) if (tagWidget->isChecked())
tags.insert(tagWidget->text()); tags.insert(Utils::Gui::widgetTextToTag(tagWidget->text()));
} }
return tags; return tags;
@ -113,7 +114,7 @@ void TorrentTagsDialog::addNewTag()
{ {
auto *layout = m_ui->scrollArea->layout(); auto *layout = m_ui->scrollArea->layout();
auto *btn = layout->takeAt(layout->count() - 1); auto *btn = layout->takeAt(layout->count() - 1);
auto *tagWidget = new QCheckBox(tag); auto *tagWidget = new QCheckBox(Utils::Gui::tagToWidgetText(tag));
tagWidget->setChecked(true); tagWidget->setChecked(true);
layout->addWidget(tagWidget); layout->addWidget(tagWidget);
layout->addItem(btn); layout->addItem(btn);

View file

@ -1,5 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2023-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -1191,7 +1192,7 @@ void TransferListWidget::displayListMenu()
for (const QString &tag : asConst(tags)) for (const QString &tag : asConst(tags))
{ {
auto *action = new TriStateAction(tag, tagsMenu); auto *action = new TriStateAction(Utils::Gui::tagToWidgetText(tag), tagsMenu);
action->setCloseOnInteraction(false); action->setCloseOnInteraction(false);
const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked

View file

@ -1,5 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2017 Mike Tzou * Copyright (C) 2017 Mike Tzou
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -218,3 +219,29 @@ void Utils::Gui::openFolderSelect(const Path &path)
openPath(path.parentPath()); openPath(path.parentPath());
#endif #endif
} }
QString Utils::Gui::tagToWidgetText(const QString &tag)
{
return QString(tag).replace(u'&', u"&&"_s);
}
QString Utils::Gui::widgetTextToTag(const QString &text)
{
// replace pairs of '&' with single '&' and remove non-paired occurrences of '&'
QString cleanedText;
cleanedText.reserve(text.size());
bool amp = false;
for (const QChar c : text)
{
if (c == u'&')
{
amp = !amp;
if (amp)
continue;
}
cleanedText.append(c);
}
return cleanedText;
}

View file

@ -1,5 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2017 Mike Tzou * Copyright (C) 2017 Mike Tzou
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -34,6 +35,7 @@ class QIcon;
class QPixmap; class QPixmap;
class QPoint; class QPoint;
class QSize; class QSize;
class QString;
class QWidget; class QWidget;
namespace Utils::Gui namespace Utils::Gui
@ -51,4 +53,7 @@ namespace Utils::Gui
void openPath(const Path &path); void openPath(const Path &path);
void openFolderSelect(const Path &path); void openFolderSelect(const Path &path);
QString tagToWidgetText(const QString &tag);
QString widgetTextToTag(const QString &text);
} }