feat: add labels to DetailsDialog of Qt client

This commit is contained in:
Nick 2023-12-25 23:09:20 +01:00 committed by GitHub
parent b562983cbd
commit e80ec7b7a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 5 deletions

View File

@ -25,6 +25,7 @@
#include <QResizeEvent> #include <QResizeEvent>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
#include <QString>
#include <QStyle> #include <QStyle>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
@ -282,6 +283,9 @@ DetailsDialog::DetailsDialog(Session& session, Prefs& prefs, TorrentModel const&
// set up the debounce timer // set up the debounce timer
connect(&ui_debounce_timer_, &QTimer::timeout, this, &DetailsDialog::refreshUI); connect(&ui_debounce_timer_, &QTimer::timeout, this, &DetailsDialog::refreshUI);
ui_debounce_timer_.setSingleShot(true); ui_debounce_timer_.setSingleShot(true);
// set labels
connect(ui_.dialogButtons, &QDialogButtonBox::clicked, this, &DetailsDialog::onButtonBoxClicked);
} }
DetailsDialog::~DetailsDialog() DetailsDialog::~DetailsDialog()
@ -300,6 +304,8 @@ void DetailsDialog::setIds(torrent_ids_t const& ids)
session_.refreshDetailInfo(ids_); session_.refreshDetailInfo(ids_);
tracker_model_->refresh(model_, ids_); tracker_model_->refresh(model_, ids_);
labels_need_refresh_ = true;
refreshModel(); refreshModel();
refreshUI(); refreshUI();
} }
@ -386,6 +392,40 @@ void DetailsDialog::onSessionCalled(Session::Tag tag)
} }
} }
void DetailsDialog::onButtonBoxClicked(QAbstractButton* button)
{
if (ui_.dialogButtons->standardButton(button) == QDialogButtonBox::Close)
{
if (ui_.labelsTextEdit->isReadOnly()) // no edits could have been made
{
return;
}
QString const labels_text = ui_.labelsTextEdit->toPlainText().trimmed();
if (labels_text == labels_baseline_) // no edits have been made
{
return;
}
QString const re = QStringLiteral("((,|;)\\s*)");
//see https://doc.qt.io/qt-5/qt.html#SplitBehaviorFlags-enum
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList const labels_list = labels_text.split(QRegularExpression(re), QString::SkipEmptyParts);
#else
QStringList const labels_list = labels_text.split(QRegularExpression(re), Qt::SkipEmptyParts);
#endif
torrentSet(TR_KEY_labels, labels_list);
if (!ids_.empty())
{
session_.refreshDetailInfo(ids_);
}
}
}
namespace namespace
{ {
@ -849,6 +889,39 @@ void DetailsDialog::refreshUI()
ui_.privacyValueLabel->setText(string); ui_.privacyValueLabel->setText(string);
// myLabelsTextEdit
if (labels_need_refresh_)
{
labels_need_refresh_ = false;
if (torrents.empty())
{
labels_baseline_.clear();
ui_.labelsTextEdit->setText({});
ui_.labelsTextEdit->setPlaceholderText(none);
ui_.labelsTextEdit->setReadOnly(true);
ui_.labelsTextEdit->setEnabled(true);
}
else if (auto const& baseline = torrents[0]->labels(); std::all_of(
std::begin(torrents),
std::end(torrents),
[&baseline](auto const* tor) { return tor->labels() == baseline; }))
{
labels_baseline_ = baseline.join(QStringLiteral(", "));
ui_.labelsTextEdit->setText(labels_baseline_);
ui_.labelsTextEdit->setPlaceholderText(none);
ui_.labelsTextEdit->setReadOnly(false);
ui_.labelsTextEdit->setEnabled(true);
}
else // mixed
{
labels_baseline_.clear();
ui_.labelsTextEdit->setText({});
ui_.labelsTextEdit->setPlaceholderText(mixed);
ui_.labelsTextEdit->setEnabled(false);
}
}
// myCommentBrowser // myCommentBrowser
string = none; string = none;
bool is_comment_mixed = false; bool is_comment_mixed = false;
@ -1250,8 +1323,12 @@ void DetailsDialog::setEnabled(bool enabled)
void DetailsDialog::initInfoTab() void DetailsDialog::initInfoTab()
{ {
int const h = QFontMetrics{ ui_.commentBrowser->font() }.lineSpacing() * 4; int const cbh = QFontMetrics{ ui_.commentBrowser->font() }.lineSpacing() * 4;
ui_.commentBrowser->setFixedHeight(h); ui_.commentBrowser->setFixedHeight(cbh);
int const lteh = QFontMetrics{ ui_.labelsTextEdit->font() }.lineSpacing() * 2;
ui_.labelsTextEdit->setFixedHeight(lteh);
ui_.labelsTextEdit->setText(QStringLiteral("Initializing..."));
auto* cr = new ColumnResizer{ this }; auto* cr = new ColumnResizer{ this };
cr->addLayout(ui_.activitySectionLayout); cr->addLayout(ui_.activitySectionLayout);

View File

@ -66,6 +66,9 @@ private slots:
void onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t const& fields); void onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t const& fields);
void onSessionCalled(Session::Tag tag); void onSessionCalled(Session::Tag tag);
// Details tab
void onButtonBoxClicked(QAbstractButton* button);
// Tracker tab // Tracker tab
void onTrackerSelectionChanged(); void onTrackerSelectionChanged();
void onAddTrackerClicked(); void onAddTrackerClicked();
@ -131,6 +134,8 @@ private:
torrent_ids_t ids_; torrent_ids_t ids_;
QTimer model_timer_; QTimer model_timer_;
QTimer ui_debounce_timer_; QTimer ui_debounce_timer_;
bool labels_need_refresh_ = true;
QString labels_baseline_;
std::shared_ptr<TrackerModel> tracker_model_; std::shared_ptr<TrackerModel> tracker_model_;
std::shared_ptr<TrackerModelFilter> tracker_filter_; std::shared_ptr<TrackerModelFilter> tracker_filter_;

View File

@ -457,6 +457,23 @@
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="6" column="0">
<widget class="QLabel" name="labelsLabel">
<property name="text">
<string>Labels:</string>
</property>
<property name="buddy">
<cstring>labelsTextEdit</cstring>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QTextEdit" name="labelsTextEdit">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="commentLabel"> <widget class="QLabel" name="commentLabel">
<property name="text"> <property name="text">
<string>Comment:</string> <string>Comment:</string>
@ -466,7 +483,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="7" column="1">
<widget class="QTextBrowser" name="commentBrowser"> <widget class="QTextBrowser" name="commentBrowser">
<property name="textInteractionFlags"> <property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>

View File

@ -524,11 +524,12 @@ std::vector<std::string_view> const& Session::getKeyNames(TorrentProperties prop
if (names.empty()) if (names.empty())
{ {
// unchanging fields needed by the main window // unchanging fields needed by the main window
static auto constexpr MainInfoKeys = std::array<tr_quark, 8>{ static auto constexpr MainInfoKeys = std::array<tr_quark, 9>{
TR_KEY_addedDate, // TR_KEY_addedDate, //
TR_KEY_downloadDir, // TR_KEY_downloadDir, //
TR_KEY_file_count, // TR_KEY_file_count, //
TR_KEY_hashString, // TR_KEY_hashString, //
TR_KEY_labels, //
TR_KEY_name, // TR_KEY_name, //
TR_KEY_primary_mime_type, // TR_KEY_primary_mime_type, //
TR_KEY_totalSize, // TR_KEY_totalSize, //
@ -565,12 +566,13 @@ std::vector<std::string_view> const& Session::getKeyNames(TorrentProperties prop
}; };
// unchanging fields needed by the details dialog // unchanging fields needed by the details dialog
static auto constexpr DetailInfoKeys = std::array<tr_quark, 9>{ static auto constexpr DetailInfoKeys = std::array<tr_quark, 10>{
TR_KEY_comment, // TR_KEY_comment, //
TR_KEY_creator, // TR_KEY_creator, //
TR_KEY_dateCreated, // TR_KEY_dateCreated, //
TR_KEY_files, // TR_KEY_files, //
TR_KEY_isPrivate, // TR_KEY_isPrivate, //
TR_KEY_labels, //
TR_KEY_pieceCount, // TR_KEY_pieceCount, //
TR_KEY_pieceSize, // TR_KEY_pieceSize, //
TR_KEY_trackerList, // TR_KEY_trackerList, //

View File

@ -202,6 +202,7 @@ Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const*
HANDLE_KEY(isFinished, is_finished, IS_FINISHED) HANDLE_KEY(isFinished, is_finished, IS_FINISHED)
HANDLE_KEY(isPrivate, is_private, IS_PRIVATE) HANDLE_KEY(isPrivate, is_private, IS_PRIVATE)
HANDLE_KEY(isStalled, is_stalled, IS_STALLED) HANDLE_KEY(isStalled, is_stalled, IS_STALLED)
HANDLE_KEY(labels, labels, LABELS)
HANDLE_KEY(leftUntilDone, left_until_done, LEFT_UNTIL_DONE) HANDLE_KEY(leftUntilDone, left_until_done, LEFT_UNTIL_DONE)
HANDLE_KEY(manualAnnounceTime, manual_announce_time, MANUAL_ANNOUNCE_TIME) HANDLE_KEY(manualAnnounceTime, manual_announce_time, MANUAL_ANNOUNCE_TIME)
HANDLE_KEY(metadataPercentComplete, metadata_percent_complete, METADATA_PERCENT_COMPLETE) HANDLE_KEY(metadataPercentComplete, metadata_percent_complete, METADATA_PERCENT_COMPLETE)

View File

@ -16,6 +16,7 @@
#include <QMetaType> #include <QMetaType>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList>
#include <libtransmission/transmission.h> #include <libtransmission/transmission.h>
@ -415,6 +416,11 @@ public:
bool includesTracker(QString const& sitename) const; bool includesTracker(QString const& sitename) const;
[[nodiscard]] constexpr auto const& labels() const noexcept
{
return labels_;
}
[[nodiscard]] constexpr auto const& sitenames() const noexcept [[nodiscard]] constexpr auto const& sitenames() const noexcept
{ {
return sitenames_; return sitenames_;
@ -588,6 +594,7 @@ public:
IS_FINISHED, IS_FINISHED,
IS_PRIVATE, IS_PRIVATE,
IS_STALLED, IS_STALLED,
LABELS,
LEFT_UNTIL_DONE, LEFT_UNTIL_DONE,
MANUAL_ANNOUNCE_TIME, MANUAL_ANNOUNCE_TIME,
METADATA_PERCENT_COMPLETE, METADATA_PERCENT_COMPLETE,
@ -690,6 +697,7 @@ private:
PeerList peers_; PeerList peers_;
FileList files_; FileList files_;
QStringList labels_;
std::vector<QString> sitenames_; std::vector<QString> sitenames_;
TrackerStatsList tracker_stats_; TrackerStatsList tracker_stats_;