mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-31 00:44:19 +00:00
parent
b55d4b1733
commit
d40be79c69
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2021 Mike Tzou (Chocobo1)
|
* Copyright (C) 2021 Mike Tzou (Chocobo1)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -100,9 +101,18 @@ public:
|
|||||||
return (BaseType::erase(value) > 0);
|
return (BaseType::erase(value) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThisType &unite(const ThisType &other)
|
template <typename Set>
|
||||||
|
ThisType &unite(const Set &other)
|
||||||
{
|
{
|
||||||
BaseType::insert(other.cbegin(), other.cend());
|
BaseType::insert(other.cbegin(), other.cend());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Set>
|
||||||
|
ThisType united(const Set &other) const
|
||||||
|
{
|
||||||
|
ThisType result = *this;
|
||||||
|
result.unite(other);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,7 @@ qt_wrap_ui(UI_HEADERS
|
|||||||
torrentcategorydialog.ui
|
torrentcategorydialog.ui
|
||||||
torrentcreatordialog.ui
|
torrentcreatordialog.ui
|
||||||
torrentoptionsdialog.ui
|
torrentoptionsdialog.ui
|
||||||
|
torrenttagsdialog.ui
|
||||||
trackerentriesdialog.ui
|
trackerentriesdialog.ui
|
||||||
uithemedialog.ui
|
uithemedialog.ui
|
||||||
watchedfolderoptionsdialog.ui
|
watchedfolderoptionsdialog.ui
|
||||||
@ -58,6 +59,7 @@ add_library(qbt_gui STATIC
|
|||||||
desktopintegration.h
|
desktopintegration.h
|
||||||
downloadfromurldialog.h
|
downloadfromurldialog.h
|
||||||
executionlogwidget.h
|
executionlogwidget.h
|
||||||
|
flowlayout.h
|
||||||
fspathedit.h
|
fspathedit.h
|
||||||
fspathedit_p.h
|
fspathedit_p.h
|
||||||
guiapplicationcomponent.h
|
guiapplicationcomponent.h
|
||||||
@ -114,6 +116,7 @@ add_library(qbt_gui STATIC
|
|||||||
torrentcontentwidget.h
|
torrentcontentwidget.h
|
||||||
torrentcreatordialog.h
|
torrentcreatordialog.h
|
||||||
torrentoptionsdialog.h
|
torrentoptionsdialog.h
|
||||||
|
torrenttagsdialog.h
|
||||||
trackerentriesdialog.h
|
trackerentriesdialog.h
|
||||||
transferlistdelegate.h
|
transferlistdelegate.h
|
||||||
transferlistfilterswidget.h
|
transferlistfilterswidget.h
|
||||||
@ -146,6 +149,7 @@ add_library(qbt_gui STATIC
|
|||||||
desktopintegration.cpp
|
desktopintegration.cpp
|
||||||
downloadfromurldialog.cpp
|
downloadfromurldialog.cpp
|
||||||
executionlogwidget.cpp
|
executionlogwidget.cpp
|
||||||
|
flowlayout.cpp
|
||||||
fspathedit.cpp
|
fspathedit.cpp
|
||||||
fspathedit_p.cpp
|
fspathedit_p.cpp
|
||||||
guiapplicationcomponent.cpp
|
guiapplicationcomponent.cpp
|
||||||
@ -201,6 +205,7 @@ add_library(qbt_gui STATIC
|
|||||||
torrentcontentwidget.cpp
|
torrentcontentwidget.cpp
|
||||||
torrentcreatordialog.cpp
|
torrentcreatordialog.cpp
|
||||||
torrentoptionsdialog.cpp
|
torrentoptionsdialog.cpp
|
||||||
|
torrenttagsdialog.cpp
|
||||||
trackerentriesdialog.cpp
|
trackerentriesdialog.cpp
|
||||||
transferlistdelegate.cpp
|
transferlistdelegate.cpp
|
||||||
transferlistfilterswidget.cpp
|
transferlistfilterswidget.cpp
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "lineedit.h"
|
#include "lineedit.h"
|
||||||
#include "raisedmessagebox.h"
|
#include "raisedmessagebox.h"
|
||||||
|
#include "torrenttagsdialog.h"
|
||||||
#include "ui_addnewtorrentdialog.h"
|
#include "ui_addnewtorrentdialog.h"
|
||||||
#include "uithememanager.h"
|
#include "uithememanager.h"
|
||||||
|
|
||||||
@ -368,10 +369,23 @@ AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inP
|
|||||||
|
|
||||||
for (const QString &category : asConst(categories))
|
for (const QString &category : asConst(categories))
|
||||||
{
|
{
|
||||||
if (category != defaultCategory && category != m_torrentParams.category)
|
if ((category != defaultCategory) && (category != m_torrentParams.category))
|
||||||
m_ui->categoryComboBox->addItem(category);
|
m_ui->categoryComboBox->addItem(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ui->tagsLineEdit->setText(m_torrentParams.tags.join(u", "_qs));
|
||||||
|
connect(m_ui->tagsEditButton, &QAbstractButton::clicked, this, [this]
|
||||||
|
{
|
||||||
|
auto *dlg = new TorrentTagsDialog(m_torrentParams.tags, this);
|
||||||
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
connect(dlg, &TorrentTagsDialog::accepted, this, [this, dlg]
|
||||||
|
{
|
||||||
|
m_torrentParams.tags = dlg->tags();
|
||||||
|
m_ui->tagsLineEdit->setText(m_torrentParams.tags.join(u", "_qs));
|
||||||
|
});
|
||||||
|
dlg->open();
|
||||||
|
});
|
||||||
|
|
||||||
// Torrent content filtering
|
// Torrent content filtering
|
||||||
m_filterLine->setPlaceholderText(tr("Filter files..."));
|
m_filterLine->setPlaceholderText(tr("Filter files..."));
|
||||||
m_filterLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
m_filterLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
@ -201,6 +201,46 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="tagsLayout" stretch="0,0,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="tagsLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tags:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="tagsLineEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Click [...] button to add/remove tags.</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="tagsEditButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add/remove tags</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
195
src/gui/flowlayout.cpp
Normal file
195
src/gui/flowlayout.cpp
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
* Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
*
|
||||||
|
* 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 "flowlayout.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "base/global.h"
|
||||||
|
|
||||||
|
FlowLayout::FlowLayout(QWidget *parent, const int margin, const int hSpacing, const int vSpacing)
|
||||||
|
: QLayout(parent)
|
||||||
|
, m_hSpace {hSpacing}
|
||||||
|
, m_vSpace {vSpacing}
|
||||||
|
{
|
||||||
|
setContentsMargins(margin, margin, margin, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowLayout::FlowLayout(const int margin, const int hSpacing, const int vSpacing)
|
||||||
|
: m_hSpace {hSpacing}
|
||||||
|
, m_vSpace {vSpacing}
|
||||||
|
{
|
||||||
|
setContentsMargins(margin, margin, margin, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowLayout::~FlowLayout()
|
||||||
|
{
|
||||||
|
QLayoutItem *item;
|
||||||
|
while ((item = takeAt(0)))
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowLayout::addItem(QLayoutItem *item)
|
||||||
|
{
|
||||||
|
m_itemList.append(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::horizontalSpacing() const
|
||||||
|
{
|
||||||
|
if (m_hSpace >= 0)
|
||||||
|
return m_hSpace;
|
||||||
|
|
||||||
|
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::verticalSpacing() const
|
||||||
|
{
|
||||||
|
if (m_vSpace >= 0)
|
||||||
|
return m_vSpace;
|
||||||
|
|
||||||
|
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::count() const
|
||||||
|
{
|
||||||
|
return m_itemList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QLayoutItem *FlowLayout::itemAt(const int index) const
|
||||||
|
{
|
||||||
|
return m_itemList.value(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLayoutItem *FlowLayout::takeAt(const int index)
|
||||||
|
{
|
||||||
|
if ((index >= 0) && (index < m_itemList.size()))
|
||||||
|
return m_itemList.takeAt(index);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::Orientations FlowLayout::expandingDirections() const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlowLayout::hasHeightForWidth() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::heightForWidth(const int width) const
|
||||||
|
{
|
||||||
|
const int height = doLayout(QRect(0, 0, width, 0), true);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowLayout::setGeometry(const QRect &rect)
|
||||||
|
{
|
||||||
|
QLayout::setGeometry(rect);
|
||||||
|
doLayout(rect, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize FlowLayout::sizeHint() const
|
||||||
|
{
|
||||||
|
return minimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize FlowLayout::minimumSize() const
|
||||||
|
{
|
||||||
|
QSize size;
|
||||||
|
for (const QLayoutItem *item : asConst(m_itemList))
|
||||||
|
size = size.expandedTo(item->minimumSize());
|
||||||
|
|
||||||
|
const QMargins margins = contentsMargins();
|
||||||
|
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::doLayout(const QRect &rect, const bool testOnly) const
|
||||||
|
{
|
||||||
|
int left, top, right, bottom;
|
||||||
|
getContentsMargins(&left, &top, &right, &bottom);
|
||||||
|
|
||||||
|
const QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||||
|
int x = effectiveRect.x();
|
||||||
|
int y = effectiveRect.y();
|
||||||
|
int lineHeight = 0;
|
||||||
|
|
||||||
|
for (QLayoutItem *item : asConst(m_itemList))
|
||||||
|
{
|
||||||
|
const QWidget *wid = item->widget();
|
||||||
|
|
||||||
|
int spaceX = horizontalSpacing();
|
||||||
|
if (spaceX == -1)
|
||||||
|
{
|
||||||
|
spaceX = wid->style()->layoutSpacing(
|
||||||
|
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
||||||
|
}
|
||||||
|
|
||||||
|
int spaceY = verticalSpacing();
|
||||||
|
if (spaceY == -1)
|
||||||
|
{
|
||||||
|
spaceY = wid->style()->layoutSpacing(
|
||||||
|
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextX = x + item->sizeHint().width() + spaceX;
|
||||||
|
if (((nextX - spaceX) > effectiveRect.right()) && (lineHeight > 0))
|
||||||
|
{
|
||||||
|
x = effectiveRect.x();
|
||||||
|
y = y + lineHeight + spaceY;
|
||||||
|
nextX = x + item->sizeHint().width() + spaceX;
|
||||||
|
lineHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!testOnly)
|
||||||
|
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||||
|
|
||||||
|
x = nextX;
|
||||||
|
lineHeight = std::max(lineHeight, item->sizeHint().height());
|
||||||
|
}
|
||||||
|
|
||||||
|
return y + lineHeight - rect.y() + bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FlowLayout::smartSpacing(const QStyle::PixelMetric pm) const
|
||||||
|
{
|
||||||
|
QObject *parent = this->parent();
|
||||||
|
if (!parent)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (parent->isWidgetType())
|
||||||
|
{
|
||||||
|
auto *pw = static_cast<QWidget *>(parent);
|
||||||
|
return pw->style()->pixelMetric(pm, nullptr, pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<QLayout *>(parent)->spacing();
|
||||||
|
}
|
63
src/gui/flowlayout.h
Normal file
63
src/gui/flowlayout.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
* Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
*
|
||||||
|
* 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 <QLayout>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QStyle>
|
||||||
|
|
||||||
|
class FlowLayout final : public QLayout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||||
|
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||||
|
~FlowLayout() override;
|
||||||
|
|
||||||
|
void addItem(QLayoutItem *item) override;
|
||||||
|
int horizontalSpacing() const;
|
||||||
|
int verticalSpacing() const;
|
||||||
|
Qt::Orientations expandingDirections() const override;
|
||||||
|
bool hasHeightForWidth() const override;
|
||||||
|
int heightForWidth(int) const override;
|
||||||
|
int count() const override;
|
||||||
|
QLayoutItem *itemAt(int index) const override;
|
||||||
|
QSize minimumSize() const override;
|
||||||
|
void setGeometry(const QRect &rect) override;
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
QLayoutItem *takeAt(int index) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int doLayout(const QRect &rect, bool testOnly) const;
|
||||||
|
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||||
|
|
||||||
|
QList<QLayoutItem *> m_itemList;
|
||||||
|
int m_hSpace;
|
||||||
|
int m_vSpace;
|
||||||
|
};
|
@ -16,6 +16,7 @@ HEADERS += \
|
|||||||
$$PWD/desktopintegration.h \
|
$$PWD/desktopintegration.h \
|
||||||
$$PWD/downloadfromurldialog.h \
|
$$PWD/downloadfromurldialog.h \
|
||||||
$$PWD/executionlogwidget.h \
|
$$PWD/executionlogwidget.h \
|
||||||
|
$$PWD/flowlayout.h \
|
||||||
$$PWD/fspathedit.h \
|
$$PWD/fspathedit.h \
|
||||||
$$PWD/fspathedit_p.h \
|
$$PWD/fspathedit_p.h \
|
||||||
$$PWD/guiapplicationcomponent.h \
|
$$PWD/guiapplicationcomponent.h \
|
||||||
@ -72,6 +73,7 @@ HEADERS += \
|
|||||||
$$PWD/torrentcontentwidget.h \
|
$$PWD/torrentcontentwidget.h \
|
||||||
$$PWD/torrentcreatordialog.h \
|
$$PWD/torrentcreatordialog.h \
|
||||||
$$PWD/torrentoptionsdialog.h \
|
$$PWD/torrentoptionsdialog.h \
|
||||||
|
$$PWD/torrenttagsdialog.h \
|
||||||
$$PWD/trackerentriesdialog.h \
|
$$PWD/trackerentriesdialog.h \
|
||||||
$$PWD/transferlistdelegate.h \
|
$$PWD/transferlistdelegate.h \
|
||||||
$$PWD/transferlistfilterswidget.h \
|
$$PWD/transferlistfilterswidget.h \
|
||||||
@ -104,6 +106,7 @@ SOURCES += \
|
|||||||
$$PWD/desktopintegration.cpp \
|
$$PWD/desktopintegration.cpp \
|
||||||
$$PWD/downloadfromurldialog.cpp \
|
$$PWD/downloadfromurldialog.cpp \
|
||||||
$$PWD/executionlogwidget.cpp \
|
$$PWD/executionlogwidget.cpp \
|
||||||
|
$$PWD/flowlayout.cpp \
|
||||||
$$PWD/fspathedit.cpp \
|
$$PWD/fspathedit.cpp \
|
||||||
$$PWD/fspathedit_p.cpp \
|
$$PWD/fspathedit_p.cpp \
|
||||||
$$PWD/guiapplicationcomponent.cpp \
|
$$PWD/guiapplicationcomponent.cpp \
|
||||||
@ -159,6 +162,7 @@ SOURCES += \
|
|||||||
$$PWD/torrentcontentwidget.cpp \
|
$$PWD/torrentcontentwidget.cpp \
|
||||||
$$PWD/torrentcreatordialog.cpp \
|
$$PWD/torrentcreatordialog.cpp \
|
||||||
$$PWD/torrentoptionsdialog.cpp \
|
$$PWD/torrentoptionsdialog.cpp \
|
||||||
|
$$PWD/torrenttagsdialog.cpp \
|
||||||
$$PWD/trackerentriesdialog.cpp \
|
$$PWD/trackerentriesdialog.cpp \
|
||||||
$$PWD/transferlistdelegate.cpp \
|
$$PWD/transferlistdelegate.cpp \
|
||||||
$$PWD/transferlistfilterswidget.cpp \
|
$$PWD/transferlistfilterswidget.cpp \
|
||||||
@ -202,6 +206,7 @@ FORMS += \
|
|||||||
$$PWD/torrentcategorydialog.ui \
|
$$PWD/torrentcategorydialog.ui \
|
||||||
$$PWD/torrentcreatordialog.ui \
|
$$PWD/torrentcreatordialog.ui \
|
||||||
$$PWD/torrentoptionsdialog.ui \
|
$$PWD/torrentoptionsdialog.ui \
|
||||||
|
$$PWD/torrenttagsdialog.ui \
|
||||||
$$PWD/trackerentriesdialog.ui \
|
$$PWD/trackerentriesdialog.ui \
|
||||||
$$PWD/uithemedialog.ui \
|
$$PWD/uithemedialog.ui \
|
||||||
$$PWD/watchedfolderoptionsdialog.ui
|
$$PWD/watchedfolderoptionsdialog.ui
|
||||||
|
121
src/gui/torrenttagsdialog.cpp
Normal file
121
src/gui/torrenttagsdialog.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 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
|
||||||
|
* 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 "torrenttagsdialog.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
|
#include "base/global.h"
|
||||||
|
#include "autoexpandabledialog.h"
|
||||||
|
#include "flowlayout.h"
|
||||||
|
|
||||||
|
#include "ui_torrenttagsdialog.h"
|
||||||
|
|
||||||
|
#define SETTINGS_KEY(name) u"GUI/TorrentTagsDialog/" name
|
||||||
|
|
||||||
|
TorrentTagsDialog::TorrentTagsDialog(const TagSet &initialTags, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_ui {new Ui::TorrentTagsDialog}
|
||||||
|
, m_storeDialogSize {SETTINGS_KEY(u"Size"_qs)}
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
auto *tagsLayout = new FlowLayout(m_ui->scrollArea);
|
||||||
|
for (const QString &tag : asConst(initialTags.united(BitTorrent::Session::instance()->tags())))
|
||||||
|
{
|
||||||
|
auto *tagWidget = new QCheckBox(tag);
|
||||||
|
if (initialTags.contains(tag))
|
||||||
|
tagWidget->setChecked(true);
|
||||||
|
tagsLayout->addWidget(tagWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *addTagButton = new QPushButton(u"+"_qs);
|
||||||
|
connect(addTagButton, &QPushButton::clicked, this, &TorrentTagsDialog::addNewTag);
|
||||||
|
tagsLayout->addWidget(addTagButton);
|
||||||
|
|
||||||
|
if (const QSize dialogSize = m_storeDialogSize; dialogSize.isValid())
|
||||||
|
resize(dialogSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
TorrentTagsDialog::~TorrentTagsDialog()
|
||||||
|
{
|
||||||
|
m_storeDialogSize = size();
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagSet TorrentTagsDialog::tags() const
|
||||||
|
{
|
||||||
|
TagSet tags;
|
||||||
|
auto *layout = m_ui->scrollArea->layout();
|
||||||
|
for (int i = 0; i < (layout->count() - 1); ++i)
|
||||||
|
{
|
||||||
|
const auto *tagWidget = static_cast<QCheckBox *>(layout->itemAt(i)->widget());
|
||||||
|
if (tagWidget->isChecked())
|
||||||
|
tags.insert(tagWidget->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TorrentTagsDialog::addNewTag()
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
QString tag;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
tag = AutoExpandableDialog::getText(this
|
||||||
|
, tr("New Tag"), tr("Tag:"), QLineEdit::Normal, tag, &ok).trimmed();
|
||||||
|
if (!ok || tag.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!BitTorrent::Session::isValidTag(tag))
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Invalid tag name"), tr("Tag name '%1' is invalid.").arg(tag));
|
||||||
|
}
|
||||||
|
else if (BitTorrent::Session::instance()->tags().contains(tag))
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Tag exists"), tr("Tag name already exists."));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto *layout = m_ui->scrollArea->layout();
|
||||||
|
auto *btn = layout->takeAt(layout->count() - 1);
|
||||||
|
auto *tagWidget = new QCheckBox(tag);
|
||||||
|
tagWidget->setChecked(true);
|
||||||
|
layout->addWidget(tagWidget);
|
||||||
|
layout->addItem(btn);
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
src/gui/torrenttagsdialog.h
Normal file
57
src/gui/torrenttagsdialog.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 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
|
||||||
|
* 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 <QDialog>
|
||||||
|
|
||||||
|
#include "base/settingvalue.h"
|
||||||
|
#include "base/tagset.h"
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class TorrentTagsDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TorrentTagsDialog final : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY_MOVE(TorrentTagsDialog)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TorrentTagsDialog(const TagSet &initialTags, QWidget *parent = nullptr);
|
||||||
|
~TorrentTagsDialog() override;
|
||||||
|
|
||||||
|
TagSet tags() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addNewTag();
|
||||||
|
|
||||||
|
Ui::TorrentTagsDialog *m_ui;
|
||||||
|
SettingValue<QSize> m_storeDialogSize;
|
||||||
|
};
|
81
src/gui/torrenttagsdialog.ui
Normal file
81
src/gui/torrenttagsdialog.ui
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>TorrentTagsDialog</class>
|
||||||
|
<widget class="QDialog" name="TorrentTagsDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>484</width>
|
||||||
|
<height>313</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Torrent Tags</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>464</width>
|
||||||
|
<height>263</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>TorrentTagsDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>241</x>
|
||||||
|
<y>291</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>241</x>
|
||||||
|
<y>156</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>TorrentTagsDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>241</x>
|
||||||
|
<y>291</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>241</x>
|
||||||
|
<y>156</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
* Copyright (C) 2022 Mike Tzou (Chocobo1)
|
* Copyright (C) 2022 Mike Tzou (Chocobo1)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -26,6 +27,7 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
@ -114,16 +116,34 @@ private slots:
|
|||||||
{
|
{
|
||||||
const OrderedSet<QString> newData1 {u"z"_qs};
|
const OrderedSet<QString> newData1 {u"z"_qs};
|
||||||
const OrderedSet<QString> newData2 {u"y"_qs};
|
const OrderedSet<QString> newData2 {u"y"_qs};
|
||||||
|
const QSet<QString> newData3 {u"c"_qs, u"d"_qs, u"e"_qs};
|
||||||
|
|
||||||
OrderedSet<QString> set {u"a"_qs, u"b"_qs, u"c"_qs};
|
OrderedSet<QString> set {u"a"_qs, u"b"_qs, u"c"_qs};
|
||||||
set.unite(newData1);
|
set.unite(newData1);
|
||||||
QCOMPARE(set.join(u","_qs), u"a,b,c,z"_qs);
|
QCOMPARE(set.join(u","_qs), u"a,b,c,z"_qs);
|
||||||
set.unite(newData2);
|
set.unite(newData2);
|
||||||
QCOMPARE(set.join(u","_qs), u"a,b,c,y,z"_qs);
|
QCOMPARE(set.join(u","_qs), u"a,b,c,y,z"_qs);
|
||||||
|
set.unite(newData3);
|
||||||
|
QCOMPARE(set.join(u","_qs), u"a,b,c,d,e,y,z"_qs);
|
||||||
|
|
||||||
OrderedSet<QString> emptySet;
|
OrderedSet<QString> emptySet;
|
||||||
emptySet.unite(newData1).unite(newData2);
|
emptySet.unite(newData1).unite(newData2).unite(newData3);
|
||||||
QCOMPARE(emptySet.join(u","_qs), u"y,z"_qs);
|
QCOMPARE(emptySet.join(u","_qs), u"c,d,e,y,z"_qs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testUnited() const
|
||||||
|
{
|
||||||
|
const OrderedSet<QString> newData1 {u"z"_qs};
|
||||||
|
const OrderedSet<QString> newData2 {u"y"_qs};
|
||||||
|
const QSet<QString> newData3 {u"c"_qs, u"d"_qs, u"e"_qs};
|
||||||
|
|
||||||
|
OrderedSet<QString> set {u"a"_qs, u"b"_qs, u"c"_qs};
|
||||||
|
|
||||||
|
QCOMPARE(set.united(newData1).join(u","_qs), u"a,b,c,z"_qs);
|
||||||
|
QCOMPARE(set.united(newData2).join(u","_qs), u"a,b,c,y"_qs);
|
||||||
|
QCOMPARE(set.united(newData3).join(u","_qs), u"a,b,c,d,e"_qs);
|
||||||
|
|
||||||
|
QCOMPARE(OrderedSet<QString>().united(newData1).united(newData2).united(newData3).join(u","_qs), u"c,d,e,y,z"_qs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user