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"