From ccdf178ee73e8fb7f16ea968d251af2d9479558a 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 | 4 ++-- src/gui/utils.cpp | 28 ++++++++++++++++++++++++++++ src/gui/utils.h | 7 +++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/gui/torrenttagsdialog.cpp b/src/gui/torrenttagsdialog.cpp index 9e48443b0..c01ab1eae 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 Tag &tag : asConst(initialTags.united(BitTorrent::Session::instance()->tags()))) { - auto *tagWidget = new QCheckBox(tag.toString()); + 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(Tag(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.toString()); + 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 1e5f8afdd..b08e6b8b3 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2024 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -1191,7 +1191,7 @@ void TransferListWidget::displayListMenu() const TagSet tags = BitTorrent::Session::instance()->tags(); for (const Tag &tag : asConst(tags)) { - auto *action = new TriStateAction(tag.toString(), 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 c7c1f24c4..f310c7f26 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 @@ -54,6 +55,7 @@ #include "base/global.h" #include "base/path.h" +#include "base/tag.h" #include "base/utils/fs.h" #include "base/utils/version.h" @@ -216,3 +218,29 @@ void Utils::Gui::openFolderSelect(const Path &path) openPath(path.parentPath()); #endif } + +QString Utils::Gui::tagToWidgetText(const Tag &tag) +{ + return tag.toString().replace(u'&', u"&&"_s); +} + +Tag 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 Tag(cleanedText); +} diff --git a/src/gui/utils.h b/src/gui/utils.h index c633cb45d..46a49c2f6 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,8 +35,11 @@ class QIcon; class QPixmap; class QPoint; class QSize; +class QString; class QWidget; +class Tag; + namespace Utils::Gui { bool isDarkTheme(); @@ -51,4 +55,7 @@ namespace Utils::Gui void openPath(const Path &path); void openFolderSelect(const Path &path); + + QString tagToWidgetText(const Tag &tag); + Tag widgetTextToTag(const QString &text); } -- 2.11.4.GIT