missing files

This commit is contained in:
Martin Rotter 2023-11-14 06:48:01 +01:00
parent 36fe7ccf73
commit 1ee283103d
7 changed files with 393 additions and 0 deletions

View File

@ -0,0 +1,46 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/greader/greaderfeed.h"
#include "database/databasequeries.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "services/greader/definitions.h"
#include "services/greader/greadernetwork.h"
#include "services/greader/greaderserviceroot.h"
#include <QPointer>
GreaderFeed::GreaderFeed(RootItem* parent) : Feed(parent) {}
GreaderServiceRoot* GreaderFeed::serviceRoot() const {
return qobject_cast<GreaderServiceRoot*>(getParentServiceRoot());
}
bool GreaderFeed::canBeDeleted() const {
return true;
}
bool GreaderFeed::deleteItem() {
try {
serviceRoot()->network()->subscriptionEdit(QSL(GREADER_API_EDIT_SUBSCRIPTION_DELETE),
customId(),
{},
{},
{},
serviceRoot()->networkProxy());
serviceRoot()->requestItemRemoval(this);
return true;
}
catch (const ApplicationException& ex) {
qWarningNN << LOGSEC_GREADER << "Unsubscribing from feed failed, error:" << QUOTE_W_SPACE_DOT(ex.message());
return false;
}
}
bool GreaderFeed::removeItself() {
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
return DatabaseQueries::deleteFeed(database, this, serviceRoot()->accountId());
}

View File

@ -0,0 +1,26 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef GREADERFEED_H
#define GREADERFEED_H
#include "services/abstract/feed.h"
class GreaderServiceRoot;
class GreaderFeed : public Feed {
Q_OBJECT
friend class FormGreaderFeedDetails;
public:
explicit GreaderFeed(RootItem* parent = nullptr);
virtual bool canBeDeleted() const;
virtual bool deleteItem();
private:
GreaderServiceRoot* serviceRoot() const;
bool removeItself();
};
#endif // TTRSSFEED_H

View File

@ -0,0 +1,108 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/greader/gui/formgreaderfeeddetails.h"
#include "exceptions/applicationexception.h"
#include "miscellaneous/application.h"
#include "services/greader/definitions.h"
#include "services/greader/greaderfeed.h"
#include "services/greader/greadernetwork.h"
#include "services/greader/greaderserviceroot.h"
#include "services/greader/gui/greaderfeeddetails.h"
#include <QMimeData>
#include <QTimer>
FormGreaderFeedDetails::FormGreaderFeedDetails(ServiceRoot* service_root,
RootItem* parent_to_select,
const QString& url,
QWidget* parent)
: FormFeedDetails(service_root, parent), m_feedDetails(nullptr), m_parentToSelect(parent_to_select),
m_urlToProcess(url) {}
void FormGreaderFeedDetails::apply() {
if (!m_creatingNew) {
if (!m_isBatchEdit) {
GreaderFeed* fd = feed<GreaderFeed>();
RootItem* parent = m_feedDetails->ui.m_cmbParentCategory->currentData().value<RootItem*>();
const QString category_id = parent->kind() == RootItem::Kind::ServiceRoot ? QString() : parent->customId();
try {
fd->serviceRoot()->network()->subscriptionEdit(QSL(GREADER_API_EDIT_SUBSCRIPTION_MODIFY),
fd->customId(),
m_feedDetails->ui.m_txtTitle->lineEdit()->text(),
category_id,
{},
m_serviceRoot->networkProxy());
}
catch (const ApplicationException& ex) {
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Feed NOT updated"),
tr("Error: %1").arg(ex.message()),
QSystemTrayIcon::MessageIcon::Critical},
GuiMessageDestination(true, true));
}
}
// NOTE: We can only edit base properties, therefore
// base method is fine.
FormFeedDetails::apply();
}
else {
RootItem* parent = m_feedDetails->ui.m_cmbParentCategory->currentData().value<RootItem*>();
auto* root = qobject_cast<GreaderServiceRoot*>(parent->getParentServiceRoot());
const QString category_id = parent->kind() == RootItem::Kind::ServiceRoot ? QString() : parent->customId();
try {
root->network()->subscriptionEdit(QSL(GREADER_API_EDIT_SUBSCRIPTION_ADD),
QSL("feed/") + m_feedDetails->ui.m_txtUrl->lineEdit()->text(),
m_feedDetails->ui.m_txtTitle->lineEdit()->text(),
category_id,
{},
m_serviceRoot->networkProxy());
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Feed added"),
tr("Feed was added, obtaining new tree of feeds now."),
QSystemTrayIcon::MessageIcon::Information});
QTimer::singleShot(300, root, &GreaderServiceRoot::syncIn);
}
catch (const ApplicationException& ex) {
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Feed NOT added"),
tr("Error: %1").arg(ex.message()),
QSystemTrayIcon::MessageIcon::Critical},
GuiMessageDestination(true, true));
}
}
}
void FormGreaderFeedDetails::loadFeedData() {
FormFeedDetails::loadFeedData();
if (!m_isBatchEdit) {
m_feedDetails = new GreaderFeedDetails(this);
insertCustomTab(m_feedDetails, tr("General"), 0);
activateTab(0);
GreaderFeed* fd = feed<GreaderFeed>();
m_feedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(),
m_serviceRoot,
m_creatingNew ? m_parentToSelect : fd->parent());
if (m_creatingNew) {
if (!m_urlToProcess.isEmpty()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess);
}
m_feedDetails->ui.m_txtUrl->setFocus();
m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll();
}
else {
m_feedDetails->ui.m_txtTitle->lineEdit()->setText(fd->title());
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(fd->source());
}
}
}

View File

@ -0,0 +1,30 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef FORMGREADERFEEDDETAILS_H
#define FORMGREADERFEEDDETAILS_H
#include "services/abstract/gui/formfeeddetails.h"
class GreaderFeed;
class GreaderFeedDetails;
class FormGreaderFeedDetails : public FormFeedDetails {
public:
explicit FormGreaderFeedDetails(ServiceRoot* service_root,
RootItem* parent_to_select = nullptr,
const QString& url = QString(),
QWidget* parent = nullptr);
protected slots:
virtual void apply();
private:
virtual void loadFeedData();
private:
GreaderFeedDetails* m_feedDetails;
RootItem* m_parentToSelect;
QString m_urlToProcess;
};
#endif // FORMGREADERFEEDDETAILS_H

View File

@ -0,0 +1,70 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/greader/gui/greaderfeeddetails.h"
#include "definitions/definitions.h"
#include "services/abstract/category.h"
GreaderFeedDetails::GreaderFeedDetails(QWidget* parent) : QWidget(parent) {
ui.setupUi(this);
ui.m_txtUrl->lineEdit()->setPlaceholderText(tr("Full feed URL including scheme"));
ui.m_txtUrl->lineEdit()->setToolTip(tr("Provide URL for your feed."));
connect(ui.m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &GreaderFeedDetails::onUrlChanged);
onUrlChanged(QString());
connect(ui.m_txtTitle->lineEdit(), &BaseLineEdit::textChanged, this, &GreaderFeedDetails::onTitleChanged);
onTitleChanged(QString());
}
void GreaderFeedDetails::onUrlChanged(const QString& new_url) {
if (QRegularExpression(QSL(URL_REGEXP)).match(new_url).hasMatch()) {
// New url is well-formed.
ui.m_txtUrl->setStatus(LineEditWithStatus::StatusType::Ok, tr("The URL is ok."));
}
else if (!new_url.simplified().isEmpty()) {
// New url is not well-formed but is not empty on the other hand.
ui.m_txtUrl->setStatus(
LineEditWithStatus::StatusType::Warning,
tr(R"(The URL does not meet standard pattern. Does your URL start with "http://" or "https://" prefix.)"));
}
else {
// New url is empty.
ui.m_txtUrl->setStatus(LineEditWithStatus::StatusType::Error, tr("The URL is empty."));
}
}
void GreaderFeedDetails::onTitleChanged(const QString& new_title) {
if (new_title.isEmpty()) {
ui.m_txtTitle->setStatus(WidgetWithStatus::StatusType::Ok, tr("Title is entered."));
}
else {
ui.m_txtTitle->setStatus(WidgetWithStatus::StatusType::Warning,
tr("No title is entered. If you are creating new feed, title will be automatically "
"extracted from it."));
}
}
void GreaderFeedDetails::loadCategories(const QList<Category*>& categories,
RootItem* root_item,
RootItem* parent_to_select) {
ui.m_cmbParentCategory->addItem(root_item->fullIcon(), root_item->title(), QVariant::fromValue(root_item));
for (Category* category : categories) {
ui.m_cmbParentCategory->addItem(category->fullIcon(), category->title(), QVariant::fromValue(category));
}
if (parent_to_select != nullptr) {
if (parent_to_select->kind() == RootItem::Kind::Category) {
ui.m_cmbParentCategory->setCurrentIndex(ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select)));
}
else if (parent_to_select->kind() == RootItem::Kind::Feed) {
int target_item = ui.m_cmbParentCategory->findData(QVariant::fromValue(parent_to_select->parent()));
if (target_item >= 0) {
ui.m_cmbParentCategory->setCurrentIndex(target_item);
}
}
}
}

View File

@ -0,0 +1,32 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef GREADERFEEDDETAILS_H
#define GREADERFEEDDETAILS_H
#include <QWidget>
#include "ui_greaderfeeddetails.h"
class Category;
class RootItem;
class GreaderFeedDetails : public QWidget {
Q_OBJECT
friend class FormGreaderFeedDetails;
public:
explicit GreaderFeedDetails(QWidget* parent = nullptr);
private slots:
void onUrlChanged(const QString& new_url);
void onTitleChanged(const QString& new_title);
private:
void loadCategories(const QList<Category*>& categories, RootItem* root_item, RootItem* parent_to_select = nullptr);
private:
Ui::GreaderFeedDetails ui;
};
#endif // GREADERFEEDDETAILS_H

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GreaderFeedDetails</class>
<widget class="QWidget" name="GreaderFeedDetails">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>367</width>
<height>202</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_lblParentCategory">
<property name="text">
<string>Parent folder</string>
</property>
<property name="buddy">
<cstring>m_cmbParentCategory</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="m_cmbParentCategory">
<property name="toolTip">
<string>Select parent item for your feed.</string>
</property>
<property name="iconSize">
<size>
<width>12</width>
<height>12</height>
</size>
</property>
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>URL</string>
</property>
<property name="buddy">
<cstring>m_txtUrl</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LineEditWithStatus" name="m_txtUrl" native="true"/>
</item>
<item row="1" column="1">
<widget class="LineEditWithStatus" name="m_txtTitle" native="true"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtTitle</cstring>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LineEditWithStatus</class>
<extends>QWidget</extends>
<header>lineeditwithstatus.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>