Qt desktop: add manage (edit/delete) and tag autocomplete
Brings the Qt uploader to parity with the web /manage page and the Android
app. Adds a stacked Manage page (reached from the post page) that lists
posts via GET /api/photos with thumbnails from GET /api/thumb/<slug>, edits
caption/date/tags in a QDialog via POST /api/edit, and deletes to trash via
POST /api/delete with a QMessageBox confirm. As a non-browser client it sends
no Origin and so passes the server's same-origin CSRF check.
Tag autocomplete now backs every tags field (post cards and the edit dialog)
via a per-token TagCompleter (QCompleter subclass, MatchContains) fed from
the unguarded GET /api/tags.json.
New files: managepostwidget.{h,cpp}, tagcompleter.{h,cpp}; network methods
and a RemotePhoto struct added to uploadclient. Built and linked clean; not
yet runtime-tested on a real display.
This commit is contained in:
1 parent
bb8c7109fa
commit
504b96ed31
12 files changed
+677
-2
No files matched your search
@@ -0,0 +1,92 @@
|
||||
#include "managepostwidget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QImage>
|
||||
#include <QLabel>
|
||||
#include <QPixmap>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace {
|
||||
constexpr int kThumbSize = 72;
|
||||
}
|
||||
|
||||
ManagePostWidget::ManagePostWidget(const QString &slug, const QString &caption,
|
||||
const QString &date, const QStringList &tags,
|
||||
const QString &url, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_slug(slug)
|
||||
, m_caption(caption)
|
||||
, m_date(date)
|
||||
, m_tags(tags)
|
||||
, m_url(url)
|
||||
{
|
||||
auto *row = new QHBoxLayout(this);
|
||||
row->setContentsMargins(0, 4, 0, 4);
|
||||
|
||||
m_thumb = new QLabel;
|
||||
m_thumb->setFixedSize(kThumbSize, kThumbSize);
|
||||
m_thumb->setAlignment(Qt::AlignCenter);
|
||||
m_thumb->setFrameShape(QFrame::Box);
|
||||
row->addWidget(m_thumb, 0, Qt::AlignTop);
|
||||
|
||||
auto *fields = new QVBoxLayout;
|
||||
m_captionLabel = new QLabel;
|
||||
m_captionLabel->setTextFormat(Qt::RichText);
|
||||
m_captionLabel->setOpenExternalLinks(true);
|
||||
m_captionLabel->setWordWrap(true);
|
||||
fields->addWidget(m_captionLabel);
|
||||
|
||||
m_metaLabel = new QLabel;
|
||||
m_metaLabel->setWordWrap(true);
|
||||
m_metaLabel->setStyleSheet(QStringLiteral("color:#a89984;"));
|
||||
fields->addWidget(m_metaLabel);
|
||||
row->addLayout(fields, 1);
|
||||
|
||||
m_edit = new QPushButton(QStringLiteral("Edit"));
|
||||
connect(m_edit, &QPushButton::clicked, this, [this]() { emit editRequested(this); });
|
||||
row->addWidget(m_edit, 0, Qt::AlignTop);
|
||||
|
||||
m_delete = new QPushButton(QStringLiteral("Delete"));
|
||||
connect(m_delete, &QPushButton::clicked, this, [this]() { emit deleteRequested(this); });
|
||||
row->addWidget(m_delete, 0, Qt::AlignTop);
|
||||
|
||||
refreshSummary();
|
||||
}
|
||||
|
||||
void ManagePostWidget::setThumbnail(const QImage &image)
|
||||
{
|
||||
if (image.isNull()) {
|
||||
m_thumb->setText(QStringLiteral("?"));
|
||||
return;
|
||||
}
|
||||
m_thumb->setPixmap(QPixmap::fromImage(image).scaled(
|
||||
kThumbSize, kThumbSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
void ManagePostWidget::applyEdit(const QString &caption, const QString &date,
|
||||
const QStringList &tags)
|
||||
{
|
||||
m_caption = caption;
|
||||
m_date = date;
|
||||
m_tags = tags;
|
||||
refreshSummary();
|
||||
}
|
||||
|
||||
void ManagePostWidget::setBusy(bool busy)
|
||||
{
|
||||
m_edit->setEnabled(!busy);
|
||||
m_delete->setEnabled(!busy);
|
||||
}
|
||||
|
||||
void ManagePostWidget::refreshSummary()
|
||||
{
|
||||
const QString shown = m_caption.isEmpty() ? m_slug : m_caption;
|
||||
m_captionLabel->setText(
|
||||
QStringLiteral("<a href=\"%1\">%2</a>").arg(m_url, shown.toHtmlEscaped()));
|
||||
|
||||
QString meta = m_date;
|
||||
if (!m_tags.isEmpty())
|
||||
meta += QStringLiteral(" · ") + m_tags.join(QStringLiteral(", "));
|
||||
m_metaLabel->setText(meta);
|
||||
}
|
||||
Reference in new issue
Block a user