This commit is contained in:
Martin Rotter 2022-01-14 14:13:44 +01:00
parent aa893b9f4d
commit 17c233563a
14 changed files with 340 additions and 3 deletions

View File

@ -26,6 +26,7 @@
<file>./graphics/Breeze/actions/32/edit-reset.svg</file>
<file>./graphics/Breeze/actions/22/edit-select-all.svg</file>
<file>./graphics/Breeze/actions/22/edit-select-none.svg</file>
<file>./graphics/Breeze/emblems/22/emblem-shared.svg</file>
<file>./graphics/Breeze/places/96/folder.svg</file>
<file>./graphics/Breeze/actions/22/format-indent-more.svg</file>
<file>./graphics/Breeze/actions/22/format-justify-fill.svg</file>
@ -93,6 +94,7 @@
<file>./graphics/Breeze Dark/actions/32/edit-reset.svg</file>
<file>./graphics/Breeze Dark/actions/22/edit-select-all.svg</file>
<file>./graphics/Breeze Dark/actions/22/edit-select-none.svg</file>
<file>./graphics/Breeze Dark/emblems/22/emblem-shared.svg</file>
<file>./graphics/Breeze Dark/places/96/folder.svg</file>
<file>./graphics/Breeze Dark/actions/22/format-indent-more.svg</file>
<file>./graphics/Breeze Dark/actions/22/format-justify-fill.svg</file>
@ -159,6 +161,7 @@
<file>./graphics/Faenza/actions/64/edit-copy.png</file>
<file>./graphics/Faenza/actions/64/edit-select-all.png</file>
<file>./graphics/Faenza/emblems/64/emblem-downloads.png</file>
<file>./graphics/Faenza/emblems/64/emblem-shared.png</file>
<file>./graphics/Faenza/emblems/64/emblem-system.png</file>
<file>./graphics/Faenza/places/64/folder.png</file>
<file>./graphics/Faenza/actions/64/format-indent-more.png</file>
@ -230,6 +233,7 @@
<file>./graphics/Numix/22/actions/edit-copy.svg</file>
<file>./graphics/Numix/22/actions/edit-select-all.svg</file>
<file>./graphics/Numix/22/emblems/emblem-downloads.svg</file>
<file>./graphics/Numix/22/emblems/emblem-shared.svg</file>
<file>./graphics/Numix/22/emblems/emblem-system.svg</file>
<file>./graphics/Numix/22/places/folder.svg</file>
<file>./graphics/Numix/22/actions/format-indent-more.svg</file>

View File

@ -64,6 +64,10 @@ QMessageBox::StandardButton MessageBox::show(QWidget* parent,
bool* dont_show_again,
const QString& functor_heading,
const std::function<void()>& functor) {
if (parent == nullptr) {
parent = qApp->mainFormWidget();
}
// Create and find needed components.
MessageBox msg_box(parent);

View File

@ -220,10 +220,12 @@ HEADERS += core/feeddownloader.h \
services/tt-rss/definitions.h \
services/tt-rss/gui/formeditttrssaccount.h \
services/tt-rss/gui/formttrssfeeddetails.h \
services/tt-rss/gui/formttrssnote.h \
services/tt-rss/gui/ttrssaccountdetails.h \
services/tt-rss/gui/ttrssfeeddetails.h \
services/tt-rss/ttrssfeed.h \
services/tt-rss/ttrssnetworkfactory.h \
services/tt-rss/ttrssnotetopublish.h \
services/tt-rss/ttrssserviceentrypoint.h \
services/tt-rss/ttrssserviceroot.h
@ -403,6 +405,7 @@ SOURCES += core/feeddownloader.cpp \
services/standard/standardserviceroot.cpp \
services/tt-rss/gui/formeditttrssaccount.cpp \
services/tt-rss/gui/formttrssfeeddetails.cpp \
services/tt-rss/gui/formttrssnote.cpp \
services/tt-rss/gui/ttrssaccountdetails.cpp \
services/tt-rss/gui/ttrssfeeddetails.cpp \
services/tt-rss/ttrssfeed.cpp \
@ -455,6 +458,7 @@ FORMS += gui/dialogs/formabout.ui \
services/reddit/gui/redditaccountdetails.ui \
services/standard/gui/formstandardimportexport.ui \
services/standard/gui/standardfeeddetails.ui \
services/tt-rss/gui/formttrssnote.ui \
services/tt-rss/gui/ttrssaccountdetails.ui \
services/tt-rss/gui/ttrssfeeddetails.ui

View File

@ -239,8 +239,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
<x>325</x>
<y>424</y>
</hint>
<hint type="destinationlabel">
<x>286</x>

View File

@ -0,0 +1,79 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/tt-rss/gui/formttrssnote.h"
#include "gui/guiutilities.h"
#include "gui/messagebox.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "services/tt-rss/definitions.h"
#include "services/tt-rss/ttrssnetworkfactory.h"
#include "services/tt-rss/ttrssnotetopublish.h"
#include "services/tt-rss/ttrssserviceroot.h"
FormTtRssNote::FormTtRssNote(TtRssServiceRoot* root) : QDialog(qApp->mainFormWidget()), m_root(root), m_titleOk(false),
m_urlOk(false) {
m_ui.setupUi(this);
GuiUtilities::applyDialogProperties(*this,
qApp->icons()->fromTheme(QSL("emblem-shared")),
tr("Share note to \"Published\" feed"));
setTabOrder(m_ui.m_txtTitle->lineEdit(), m_ui.m_txtUrl->lineEdit());
setTabOrder(m_ui.m_txtUrl->lineEdit(), m_ui.m_txtContent);
setTabOrder(m_ui.m_txtContent, m_ui.m_btnBox);
connect(m_ui.m_txtTitle->lineEdit(), &BaseLineEdit::textChanged, this, &FormTtRssNote::onTitleChanged);
connect(m_ui.m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormTtRssNote::onUrlChanged);
connect(m_ui.m_btnBox, &QDialogButtonBox::accepted, this, &FormTtRssNote::sendNote);
emit m_ui.m_txtTitle->lineEdit()->textChanged({});
emit m_ui.m_txtUrl->lineEdit()->textChanged({});
}
void FormTtRssNote::sendNote() {
TtRssNoteToPublish note;
note.m_content = m_ui.m_txtContent->toPlainText();
note.m_url = m_ui.m_txtUrl->lineEdit()->text();
note.m_title = m_ui.m_txtTitle->lineEdit()->text();
auto res = m_root->network()->shareToPublished(note, m_root->networkProxy());
if (res.status() == TTRSS_API_STATUS_OK) {
accept();
}
else {
MessageBox::show({}, QMessageBox::Icon::Critical,
tr("Cannot share note"),
tr("There was an error, when trying to send your custom note."),
{},
res.error());
}
}
void FormTtRssNote::onTitleChanged(const QString& text) {
m_titleOk = !text.simplified().isEmpty();
m_ui.m_txtTitle->setStatus(m_titleOk
? WidgetWithStatus::StatusType::Ok
: WidgetWithStatus::StatusType::Error,
tr("Enter non-empty title."));
updateOkButton();
}
void FormTtRssNote::onUrlChanged(const QString& text) {
m_urlOk = text.startsWith(URI_SCHEME_HTTPS) || text.startsWith(URI_SCHEME_HTTP);
m_ui.m_txtUrl->setStatus(m_urlOk
? WidgetWithStatus::StatusType::Ok
: WidgetWithStatus::StatusType::Error,
tr("Enter valid URL."));
updateOkButton();
}
void FormTtRssNote::updateOkButton() {
m_ui.m_btnBox->button(QDialogButtonBox::StandardButton::Ok)->setEnabled(m_urlOk && m_titleOk);
}

View File

@ -0,0 +1,33 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef FORMTTRSSNOTE_H
#define FORMTTRSSNOTE_H
#include <QDialog>
#include "ui_formttrssnote.h"
class TtRssServiceRoot;
class FormTtRssNote : public QDialog {
Q_OBJECT
public:
explicit FormTtRssNote(TtRssServiceRoot* root);
private slots:
void sendNote();
void onTitleChanged(const QString& text);
void onUrlChanged(const QString& text);
private:
void updateOkButton();
private:
Ui::FormTtRssNote m_ui;
TtRssServiceRoot* m_root;
bool m_titleOk;
bool m_urlOk;
};
#endif // FORMTTRSSNOTE_H

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FormTtRssNote</class>
<widget class="QDialog" name="FormTtRssNote">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>340</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtTitle</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LineEditWithStatus" name="m_txtTitle" native="true"/>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtUrl" native="true"/>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="m_btnBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Content</string>
</property>
<property name="buddy">
<cstring>m_txtContent</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPlainTextEdit" name="m_txtContent"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LineEditWithStatus</class>
<extends>QWidget</extends>
<header>lineeditwithstatus.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>m_btnBox</sender>
<signal>rejected()</signal>
<receiver>FormTtRssNote</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>295</x>
<y>327</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -13,7 +13,7 @@
#include <QPointer>
TtRssFeed::TtRssFeed(RootItem* parent) : Feed(parent) {}
TtRssFeed::TtRssFeed(RootItem* parent) : Feed(parent), m_actionShareToPublished(nullptr) {}
TtRssServiceRoot* TtRssFeed::serviceRoot() const {
return qobject_cast<TtRssServiceRoot*>(getParentServiceRoot());
@ -39,6 +39,24 @@ bool TtRssFeed::deleteViaGui() {
}
}
QList<QAction*> TtRssFeed::contextMenuFeedsList() {
auto menu = Feed::contextMenuFeedsList();
if (customNumericId() == TTRSS_PUBLISHED_FEED_ID) {
if (m_actionShareToPublished == nullptr) {
m_actionShareToPublished = new QAction(qApp->icons()->fromTheme(QSL("emblem-shared")),
tr("Share to published"),
this);
connect(m_actionShareToPublished, &QAction::triggered, serviceRoot(), &TtRssServiceRoot::shareToPublished);
}
menu.append(m_actionShareToPublished);
}
return menu;
}
bool TtRssFeed::removeItself() {
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());

View File

@ -15,10 +15,14 @@ class TtRssFeed : public Feed {
virtual bool canBeDeleted() const;
virtual bool deleteViaGui();
virtual QList<QAction*> contextMenuFeedsList();
private:
TtRssServiceRoot* serviceRoot() const;
bool removeItself();
private:
QAction* m_actionShareToPublished;
};
#endif // TTRSSFEED_H

View File

@ -209,6 +209,61 @@ TtRssGetLabelsResponse TtRssNetworkFactory::getLabels(const QNetworkProxy& proxy
return result;
}
TtRssResponse TtRssNetworkFactory::shareToPublished(const TtRssNoteToPublish& note, const QNetworkProxy& proxy) {
QJsonObject json;
json[QSL("op")] = QSL("shareToPublished");
json[QSL("sid")] = m_sessionId;
json[QSL("title")] = note.m_title;
json[QSL("url")] = note.m_url;
json[QSL("content")] = note.m_content;
const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray result_raw;
QList<QPair<QByteArray, QByteArray>> headers;
headers << QPair<QByteArray, QByteArray>(HTTP_HEADERS_CONTENT_TYPE, TTRSS_CONTENT_TYPE_JSON);
headers << NetworkFactory::generateBasicAuthHeader(m_authUsername, m_authPassword);
NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl,
timeout,
QJsonDocument(json).toJson(QJsonDocument::JsonFormat::Compact),
result_raw,
QNetworkAccessManager::Operation::PostOperation,
headers,
false,
{},
{},
proxy);
TtRssResponse result(QString::fromUtf8(result_raw));
if (result.isNotLoggedIn()) {
// We are not logged in.
login(proxy);
json[QSL("sid")] = m_sessionId;
network_reply = NetworkFactory::performNetworkOperation(m_fullUrl,
timeout,
QJsonDocument(json).toJson(QJsonDocument::JsonFormat::Compact),
result_raw,
QNetworkAccessManager::Operation::PostOperation,
headers,
false,
{},
{},
proxy);
result = TtRssResponse(QString::fromUtf8(result_raw));
}
if (network_reply.first != QNetworkReply::NoError) {
qWarningNN << LOGSEC_TTRSS
<< "shareToPublished failed with error:"
<< QUOTE_W_SPACE_DOT(network_reply.first);
}
m_lastError = network_reply.first;
return result;
}
TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories(const QNetworkProxy& proxy) {
QJsonObject json;

View File

@ -5,6 +5,8 @@
#include "core/message.h"
#include "services/tt-rss/ttrssnotetopublish.h"
#include <QJsonObject>
#include <QNetworkReply>
#include <QPair>
@ -155,6 +157,9 @@ class TtRssNetworkFactory {
// Gets list of labels from the server.
TtRssGetLabelsResponse getLabels(const QNetworkProxy& proxy);
// Shares new item to "published" feed.
TtRssResponse shareToPublished(const TtRssNoteToPublish& note, const QNetworkProxy& proxy);
// Gets feeds from the server.
TtRssGetFeedsCategoriesResponse getFeedsCategories(const QNetworkProxy& proxy);

View File

@ -0,0 +1,15 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef TTRSSNOTETOPUBLISH_H
#define TTRSSNOTETOPUBLISH_H
#include <QString>
struct TtRssNoteToPublish {
public:
QString m_title;
QString m_url;
QString m_content;
};
#endif // TTRSSNOTETOPUBLISH_H

View File

@ -17,6 +17,7 @@
#include "services/tt-rss/definitions.h"
#include "services/tt-rss/gui/formeditttrssaccount.h"
#include "services/tt-rss/gui/formttrssfeeddetails.h"
#include "services/tt-rss/gui/formttrssnote.h"
#include "services/tt-rss/ttrssfeed.h"
#include "services/tt-rss/ttrssnetworkfactory.h"
#include "services/tt-rss/ttrssserviceentrypoint.h"
@ -297,6 +298,10 @@ TtRssNetworkFactory* TtRssServiceRoot::network() const {
return m_network;
}
void TtRssServiceRoot::shareToPublished() {
FormTtRssNote(this).exec();
}
void TtRssServiceRoot::updateTitle() {
QString host = QUrl(m_network->url()).host();

View File

@ -40,6 +40,9 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
// Access to network.
TtRssNetworkFactory* network() const;
public slots:
void shareToPublished();
protected:
virtual RootItem* obtainNewTreeForSyncIn() const;