feat: add labels to DetailsDialog of Qt client
This commit is contained in:
parent
b562983cbd
commit
e80ec7b7a4
|
@ -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);
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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, //
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue