File indexing completed on 2024-04-21 14:44:32

0001 /*
0002     SPDX-FileCopyrightText: 2021 Valentin Boettcher <hiro at protagon.space; @hiro98:tchncs.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QCheckBox>
0008 #include <QMessageBox>
0009 #include <QFileDialog>
0010 #include "catalogsdbui.h"
0011 #include "ui_catalogsdbui.h"
0012 #include "catalogeditform.h"
0013 #include "catalogdetails.h"
0014 #include "catalogcoloreditor.h"
0015 
0016 CatalogsDBUI::CatalogsDBUI(QWidget *parent, const QString &db_path)
0017     : QDialog(parent), ui{ new Ui::CatalogsDBUI }, m_manager{ db_path }, m_last_dir{
0018           QDir::homePath()
0019       }
0020 {
0021     ui->setupUi(this);
0022     ui->objectsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
0023 
0024     const QStringList labels = {
0025         i18n("Enabled"),    i18n("ID"),      i18n("Name"),
0026         i18n("Precedence"), i18n("Author"),  i18n("Mutable"),
0027         i18n("Version"),    i18n("License"), i18n("Maintainer")
0028     };
0029 
0030     ui->objectsTable->setColumnCount(labels.size());
0031     ui->objectsTable->setHorizontalHeaderLabels(labels);
0032 
0033     refresh_db_table();
0034 
0035     connect(ui->objectsTable, &QTableWidget::cellClicked, this,
0036             &CatalogsDBUI::row_selected);
0037 
0038     connect(ui->objectsTable, &QTableWidget::itemSelectionChanged, this,
0039             &CatalogsDBUI::disable_buttons);
0040 
0041     connect(ui->activateButton, &QPushButton::clicked, this,
0042             &CatalogsDBUI::enable_disable_catalog);
0043 
0044     connect(ui->importButton, &QPushButton::clicked, this, &CatalogsDBUI::import_catalog);
0045 
0046     connect(ui->exportButton, &QPushButton::clicked, this, &CatalogsDBUI::export_catalog);
0047 
0048     connect(ui->removeButton, &QPushButton::clicked, this, &CatalogsDBUI::remove_catalog);
0049 
0050     connect(ui->createButton, &QPushButton::clicked, this,
0051             qOverload<>(&CatalogsDBUI::create_new_catalog));
0052 
0053     connect(ui->moreButton, &QPushButton::clicked, this, &CatalogsDBUI::show_more_dialog);
0054 
0055     connect(ui->dublicateButton, &QPushButton::clicked, this,
0056             &CatalogsDBUI::dublicate_catalog);
0057 
0058     connect(ui->colorButton, &QPushButton::clicked, this,
0059             &CatalogsDBUI::show_color_editor);
0060 }
0061 
0062 CatalogsDBUI::~CatalogsDBUI()
0063 {
0064     delete ui;
0065 }
0066 
0067 QWidget *centered_check_box_widget(bool checked)
0068 {
0069     auto *pWidget   = new QWidget{}; // no parent as receiver takes posession
0070     auto *pLayout   = new QHBoxLayout(pWidget);
0071     auto *pCheckBox = new QCheckBox(pWidget);
0072 
0073     pCheckBox->setChecked(checked);
0074     pCheckBox->setEnabled(false);
0075     pLayout->addWidget(pCheckBox);
0076     pLayout->setAlignment(Qt::AlignCenter);
0077     pLayout->setContentsMargins(0, 0, 0, 0);
0078 
0079     pWidget->setLayout(pLayout);
0080 
0081     return pWidget;
0082 }
0083 
0084 void CatalogsDBUI::refresh_db_table()
0085 {
0086     const auto catalogs = m_manager.get_catalogs(true);
0087 
0088     m_catalogs.resize(catalogs.size());
0089 
0090     auto &table = *ui->objectsTable;
0091     table.setRowCount(catalogs.size());
0092 
0093     int row{ 0 };
0094     for (const auto &catalog : catalogs)
0095     {
0096         m_catalogs[row] = catalog.id;
0097 
0098         // the table takes ownership of its items
0099         table.setCellWidget(row, 0, centered_check_box_widget(catalog.enabled));
0100 
0101         table.setItem(row, 1, new QTableWidgetItem{ QString::number(catalog.id) });
0102         table.setItem(row, 2, new QTableWidgetItem{ catalog.name });
0103         table.setItem(row, 3,
0104                       new QTableWidgetItem{ QString::number(catalog.precedence) });
0105         table.setItem(row, 4, new QTableWidgetItem{ catalog.author });
0106         table.setCellWidget(row, 5, centered_check_box_widget(catalog.mut));
0107         table.setItem(row, 6, new QTableWidgetItem{ QString::number(catalog.version) });
0108         table.setItem(row, 7, new QTableWidgetItem{ catalog.license });
0109         table.setItem(row, 8, new QTableWidgetItem{ catalog.maintainer });
0110         row++;
0111     }
0112 }
0113 
0114 void CatalogsDBUI::row_selected(int row, int)
0115 {
0116     const auto &success = m_manager.get_catalog(m_catalogs[row]);
0117     if (!success.first)
0118         return;
0119 
0120     const auto cat = success.second;
0121     ui->activateButton->setText(!cat.enabled ? i18n("Enable") : i18n("Disable"));
0122     ui->activateButton->setEnabled(true);
0123     ui->moreButton->setEnabled(true);
0124     ui->removeButton->setEnabled(true);
0125     ui->exportButton->setEnabled(true);
0126     ui->dublicateButton->setEnabled(true);
0127     ui->colorButton->setEnabled(true);
0128 }
0129 
0130 void CatalogsDBUI::disable_buttons()
0131 {
0132     if (ui->objectsTable->selectedItems().length() > 0)
0133         return;
0134 
0135     ui->activateButton->setText(i18n("Enable"));
0136     ui->activateButton->setEnabled(false);
0137     ui->moreButton->setEnabled(false);
0138     ui->removeButton->setEnabled(false);
0139     ui->exportButton->setEnabled(false);
0140     ui->dublicateButton->setEnabled(false);
0141 }
0142 
0143 void CatalogsDBUI::enable_disable_catalog()
0144 {
0145     const auto catalog = get_selected_catalog();
0146     if (!catalog.first)
0147         return;
0148 
0149     const auto success =
0150         m_manager.set_catalog_enabled(catalog.second.id, !catalog.second.enabled);
0151     if (!success.first)
0152         QMessageBox::warning(
0153             this, i18n("Warning"),
0154             i18n("Could not enable/disable the catalog.<br>%1", success.second));
0155 
0156     refresh_db_table();
0157     row_selected(ui->objectsTable->selectedItems().first()->row(), 0);
0158 }
0159 
0160 const std::pair<bool, CatalogsDB::Catalog> CatalogsDBUI::get_selected_catalog()
0161 {
0162     const auto items = ui->objectsTable->selectedItems();
0163     if (items.length() == 0)
0164         return { false, {} };
0165 
0166     return m_manager.get_catalog(m_catalogs[items.first()->row()]);
0167 }
0168 
0169 void CatalogsDBUI::export_catalog()
0170 {
0171     const auto cat = get_selected_catalog();
0172     if (!cat.first)
0173         return;
0174 
0175     QFileDialog dialog(this, i18nc("@title:window", "Export Catalog"), m_last_dir,
0176                        i18n("Catalog") +
0177                            QString(" (*.%1);;").arg(CatalogsDB::db_file_extension));
0178     dialog.setAcceptMode(QFileDialog::AcceptSave);
0179     dialog.setDefaultSuffix(CatalogsDB::db_file_extension);
0180 
0181     if (dialog.exec() != QDialog::Accepted)
0182         return;
0183 
0184     const auto fileName = dialog.selectedUrls().value(0).toLocalFile();
0185     const auto success  = m_manager.dump_catalog(cat.second.id, fileName);
0186     m_last_dir          = QFileInfo(fileName).absolutePath();
0187 
0188     if (!success.first)
0189         QMessageBox::warning(this, i18n("Warning"),
0190                              i18n("Could not export the catalog.<br>%1", success.second));
0191 }
0192 
0193 void CatalogsDBUI::import_catalog(bool force)
0194 {
0195     QFileDialog dialog(this, i18nc("@title:window", "Import Catalog"), m_last_dir,
0196                        i18n("Catalog") +
0197                            QString(" (*.%1);;").arg(CatalogsDB::db_file_extension));
0198     dialog.setAcceptMode(QFileDialog::AcceptOpen);
0199     dialog.setDefaultSuffix(CatalogsDB::db_file_extension);
0200 
0201     if (dialog.exec() != QDialog::Accepted)
0202         return;
0203 
0204     const auto fileName = dialog.selectedUrls().value(0).toLocalFile();
0205     const auto success  = m_manager.import_catalog(fileName, force);
0206     m_last_dir          = QFileInfo(fileName).absolutePath();
0207 
0208     if (!success.first && !force)
0209     {
0210         QMessageBox::warning(this, i18n("Warning"),
0211                              i18n("Could not import the catalog.<br>%1", success.second));
0212 
0213         if (QMessageBox::question(this, "Retry", "Retry and overwrite?",
0214                                   QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
0215             import_catalog(true);
0216     }
0217 
0218     refresh_db_table();
0219 }
0220 
0221 void CatalogsDBUI::remove_catalog()
0222 {
0223     const auto cat = get_selected_catalog();
0224     if (!cat.first)
0225         return;
0226 
0227     const auto success = m_manager.remove_catalog(cat.second.id);
0228 
0229     if (!success.first)
0230         QMessageBox::warning(this, i18n("Warning"),
0231                              i18n("Could not remove the catalog.<br>%1", success.second));
0232 
0233     refresh_db_table();
0234 }
0235 
0236 std::pair<bool, int> CatalogsDBUI::create_new_catalog(const CatalogsDB::Catalog &catalog)
0237 {
0238     auto *dialog = new CatalogEditForm(this, catalog);
0239     if (dialog->exec() != QDialog::Accepted)
0240         return { false, -1 };
0241 
0242     auto cat            = dialog->getCatalog();
0243     cat.mut             = true;
0244     const auto &success = m_manager.register_catalog(cat);
0245 
0246     if (!success.first)
0247     {
0248         QMessageBox::warning(this, i18n("Warning"),
0249                              i18n("Could not create the catalog.<br>%1", success.second));
0250         return create_new_catalog(cat);
0251     }
0252 
0253     refresh_db_table();
0254     return { true, cat.id };
0255 }
0256 
0257 void CatalogsDBUI::create_new_catalog()
0258 {
0259     create_new_catalog({ m_manager.find_suitable_catalog_id() });
0260 }
0261 
0262 void CatalogsDBUI::dublicate_catalog()
0263 {
0264     const auto &success = get_selected_catalog();
0265     if (!success.first)
0266         return;
0267 
0268     const auto &src = success.second;
0269 
0270     auto src_new       = src;
0271     src_new.id         = m_manager.find_suitable_catalog_id();
0272     src_new.enabled    = false;
0273     src_new.precedence = 1;
0274 
0275     const auto &create_success = create_new_catalog(src_new);
0276 
0277     if (!create_success.first)
0278         return;
0279 
0280     const auto copy_success = m_manager.copy_objects(src.id, create_success.second);
0281     if (!copy_success.first)
0282     {
0283         QMessageBox::warning(this, i18n("Warning"),
0284                              i18n("Could not copy the objects to the new catalog.<br>%1")
0285                                  .arg(copy_success.second));
0286 
0287         const auto &remove_success = m_manager.remove_catalog(create_success.second);
0288         if (!remove_success.first)
0289             QMessageBox::critical(
0290                 this, i18n("Critical error"),
0291                 i18n("Could not clean up and remove the new catalog.<br>%1",
0292                      remove_success.second));
0293     };
0294 }
0295 
0296 void CatalogsDBUI::show_more_dialog()
0297 {
0298     const auto success = get_selected_catalog();
0299     if (!success.first)
0300         return;
0301 
0302     auto *dialog = new CatalogDetails(this, m_manager.db_file_name(), success.second.id);
0303 
0304     connect(this, &QDialog::finished, dialog, &QDialog::done);
0305     connect(dialog, &QDialog::finished, this, &CatalogsDBUI::refresh_db_table);
0306 
0307     dialog->show();
0308 }
0309 
0310 void CatalogsDBUI::show_color_editor()
0311 {
0312     const auto &success = get_selected_catalog();
0313     if (!success.first)
0314         return;
0315 
0316     auto *dialog = new CatalogColorEditor(success.second.id, this);
0317 
0318     connect(this, &QDialog::finished, dialog, &QDialog::reject);
0319     dialog->show();
0320 }