From 95e431a2967ca7aeb4a3a10013c8180b7b417874 Mon Sep 17 00:00:00 2001 From: Vladimir Golovnev Date: Sun, 7 Jul 2024 08:24:30 +0300 Subject: [PATCH] Fix handling of tags containing '&' character PR #21024. Closes #20773. --- src/gui/torrenttagsdialog.cpp | 9 +++++---- src/gui/transferlistwidget.cpp | 3 ++- src/gui/utils.cpp | 27 +++++++++++++++++++++++++++ src/gui/utils.h | 5 +++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/gui/torrenttagsdialog.cpp b/src/gui/torrenttagsdialog.cpp index eb4d86168..31c66328d 100644 --- a/src/gui/torrenttagsdialog.cpp +++ b/src/gui/torrenttagsdialog.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2024 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,6 +37,7 @@ #include "base/global.h" #include "autoexpandabledialog.h" #include "flowlayout.h" +#include "utils.h" #include "ui_torrenttagsdialog.h" @@ -55,7 +56,7 @@ TorrentTagsDialog::TorrentTagsDialog(const TagSet &initialTags, QWidget *parent) auto *tagsLayout = new FlowLayout(m_ui->scrollArea); 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)) tagWidget->setChecked(true); tagsLayout->addWidget(tagWidget); @@ -83,7 +84,7 @@ TagSet TorrentTagsDialog::tags() const { const auto *tagWidget = static_cast(layout->itemAt(i)->widget()); if (tagWidget->isChecked()) - tags.insert(tagWidget->text()); + tags.insert(Utils::Gui::widgetTextToTag(tagWidget->text())); } return tags; @@ -113,7 +114,7 @@ void TorrentTagsDialog::addNewTag() { auto *layout = m_ui->scrollArea->layout(); auto *btn = layout->takeAt(layout->count() - 1); - auto *tagWidget = new QCheckBox(tag); + auto *tagWidget = new QCheckBox(Utils::Gui::tagToWidgetText(tag)); tagWidget->setChecked(true); layout->addWidget(tagWidget); layout->addItem(btn); diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index ff76167f8..7fc717ece 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2023-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -1191,7 +1192,7 @@ void TransferListWidget::displayListMenu() for (const QString &tag : asConst(tags)) { - auto *action = new TriStateAction(tag, tagsMenu); + auto *action = new TriStateAction(Utils::Gui::tagToWidgetText(tag), tagsMenu); action->setCloseOnInteraction(false); const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked diff --git a/src/gui/utils.cpp b/src/gui/utils.cpp index 9688c5f72..4a775689f 100644 --- a/src/gui/utils.cpp +++ b/src/gui/utils.cpp @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Vladimir Golovnev * Copyright (C) 2017 Mike Tzou * * 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()); #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; +} diff --git a/src/gui/utils.h b/src/gui/utils.h index 34cfd58ee..79e415c49 100644 --- a/src/gui/utils.h +++ b/src/gui/utils.h @@ -1,5 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Vladimir Golovnev * Copyright (C) 2017 Mike Tzou * * This program is free software; you can redistribute it and/or @@ -34,6 +35,7 @@ class QIcon; class QPixmap; class QPoint; class QSize; +class QString; class QWidget; namespace Utils::Gui @@ -51,4 +53,7 @@ namespace Utils::Gui void openPath(const Path &path); void openFolderSelect(const Path &path); + + QString tagToWidgetText(const QString &tag); + QString widgetTextToTag(const QString &text); }