File indexing completed on 2024-12-15 03:45:02

0001 /*
0002     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include "schemaeditor.h"
0008 #include "ui_schemaeditor.h"
0009 
0010 #include <core/aggregation.h>
0011 #include <core/product.h>
0012 #include <core/schemaentrytemplates.h>
0013 #include <rest/restapi.h>
0014 
0015 #include <QFileDialog>
0016 #include <QMenu>
0017 #include <QMessageBox>
0018 #include <QNetworkReply>
0019 
0020 using namespace KUserFeedback::Console;
0021 
0022 
0023 SchemaEditor::SchemaEditor(QWidget* parent) :
0024     QWidget(parent),
0025     ui(new Ui::SchemaEditor)
0026 {
0027     ui->setupUi(this);
0028 
0029     connect(ui->schema, &SchemaEditWidget::logMessage, this, &SchemaEditor::logMessage);
0030     connect(ui->schema, &SchemaEditWidget::productChanged, ui->aggregation, [this]() {
0031         ui->aggregation->setProduct(product());
0032         setDirty();
0033     });
0034     connect(ui->aggregation, &AggregationEditWidget::productChanged, this, [this]() {
0035         setDirty();
0036     });
0037 
0038     connect(ui->tabWidget, &QTabWidget::currentChanged, this, &SchemaEditor::updateState);
0039 
0040     auto templateMenu = new QMenu(tr("Source Templates"), this);
0041     for (const auto &t : SchemaEntryTemplates::availableTemplates()) {
0042         auto a = templateMenu->addAction(t.name());
0043         a->setData(QVariant::fromValue(t));
0044         connect(a, &QAction::triggered, this, [this, a]() {
0045             const auto t = a->data().value<Product>();
0046             auto p = product();
0047             p.addTemplate(t);
0048             setProduct(p);
0049             setDirty();
0050         });
0051     }
0052 
0053     m_createFromTemplateAction = templateMenu->menuAction();
0054     m_createFromTemplateAction->setIcon(QIcon::fromTheme(QStringLiteral("document-new-from-template")));
0055 
0056     ui->actionSave->setShortcut(QKeySequence::Save);
0057     connect(ui->actionSave, &QAction::triggered, this, &SchemaEditor::save);
0058     connect(ui->actionImportSchema, &QAction::triggered, this, &SchemaEditor::importSchema);
0059     connect(ui->actionExportSchema, &QAction::triggered, this, &SchemaEditor::exportSchema);
0060 
0061     addActions({ m_createFromTemplateAction, ui->actionSave, ui->actionImportSchema, ui->actionExportSchema });
0062     auto sep = new QAction(this);
0063     sep->setSeparator(true);
0064     addAction(sep);
0065     addActions(ui->schema->actions());
0066     addActions(ui->aggregation->actions());
0067 
0068     updateState();
0069 }
0070 
0071 SchemaEditor::~SchemaEditor() = default;
0072 
0073 void SchemaEditor::setRESTClient(RESTClient* client)
0074 {
0075     m_restClient = client;
0076     ui->schema->setRESTClient(client);
0077 }
0078 
0079 Product SchemaEditor::product() const
0080 {
0081     auto p = ui->schema->product();
0082     p.setAggregations(ui->aggregation->product().aggregations());
0083     return p;
0084 }
0085 
0086 void SchemaEditor::setProduct(const Product& product)
0087 {
0088     ui->schema->setProduct(product);
0089     ui->aggregation->setProduct(product);
0090     setDirty(false);
0091 }
0092 
0093 bool SchemaEditor::isDirty() const
0094 {
0095     return m_isDirty;
0096 }
0097 
0098 void SchemaEditor::setDirty(bool dirty)
0099 {
0100     m_isDirty = dirty;
0101     updateState();
0102 }
0103 
0104 void SchemaEditor::save()
0105 {
0106     auto reply = RESTApi::updateProduct(m_restClient, product());
0107     connect(reply, &QNetworkReply::finished, this, [this, reply]() {
0108         if (reply->error() != QNetworkReply::NoError)
0109             return;
0110         setDirty(false);
0111         Q_EMIT logMessage(QString::fromUtf8((reply->readAll())));
0112         Q_EMIT productChanged(product());
0113         reply->deleteLater();
0114     });
0115 }
0116 
0117 void SchemaEditor::exportSchema()
0118 {
0119     const auto fileName = QFileDialog::getSaveFileName(this, tr("Export Schema"));
0120     if (fileName.isEmpty())
0121         return;
0122 
0123     QFile f(fileName);
0124     if (!f.open(QFile::WriteOnly)) {
0125         QMessageBox::critical(this, tr("Export Failed"), tr("Could not open file: %1").arg(f.errorString()));
0126         return;
0127     }
0128     f.write(product().toJson());
0129     Q_EMIT logMessage(tr("Schema of %1 exported to %2.").arg(product().name(), f.fileName()));
0130 }
0131 
0132 void SchemaEditor::importSchema()
0133 {
0134     const auto fileName = QFileDialog::getOpenFileName(this, tr("Import Schema"));
0135     if (fileName.isEmpty())
0136         return;
0137 
0138     QFile f(fileName);
0139     if (!f.open(QFile::ReadOnly)) {
0140         QMessageBox::critical(this, tr("Import Failed"), tr("Could not open file: %1").arg(f.errorString()));
0141         return;
0142     }
0143     const auto products = Product::fromJson(f.readAll());
0144     if (products.size() != 1 || !products.at(0).isValid()) {
0145         QMessageBox::critical(this, tr("Import Failed"), tr("Selected file contains no valid product schema."));
0146         return;
0147     }
0148 
0149     auto p = products.at(0);
0150     p.setName(product().name());
0151     setProduct(p);
0152     setDirty();
0153     Q_EMIT logMessage(tr("Schema of %1 imported from %2.").arg(product().name(), f.fileName()));
0154 }
0155 
0156 void SchemaEditor::updateState()
0157 {
0158     const auto p = product();
0159 
0160     m_createFromTemplateAction->setEnabled(p.isValid());
0161     ui->actionSave->setEnabled(p.isValid() && isDirty());
0162     ui->actionExportSchema->setEnabled(p.isValid());
0163     ui->actionImportSchema->setEnabled(p.isValid());
0164 
0165     const auto schemaEditActive = ui->tabWidget->currentWidget() == ui->schema;
0166     const auto aggrEditActive = ui->tabWidget->currentWidget() == ui->aggregation;
0167     for (auto action : ui->schema->actions())
0168         action->setVisible(schemaEditActive);
0169     for (auto action : ui->aggregation->actions())
0170         action->setVisible(aggrEditActive);
0171 }
0172 
0173 #include "moc_schemaeditor.cpp"