File indexing completed on 2024-06-16 04:47:17

0001 /***************************************************************************
0002  * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
0003  * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  ***************************************************************************/
0006 /** @file
0007  * A plugin to manage properties on objects.
0008  *
0009  * @author Stephane MANKOWSKI
0010  */
0011 #include "skgpropertiesplugindockwidget.h"
0012 
0013 #include <kmessagebox.h>
0014 
0015 #include <qdesktopservices.h>
0016 #include <qfile.h>
0017 #include <qfiledialog.h>
0018 #include <qlineedit.h>
0019 
0020 #include "skgdocument.h"
0021 #include "skgmainpanel.h"
0022 #include "skgnamedobject.h"
0023 #include "skgobjectmodelbase.h"
0024 #include "skgpropertyobject.h"
0025 #include "skgservices.h"
0026 #include "skgsortfilterproxymodel.h"
0027 #include "skgtraces.h"
0028 #include "skgtransactionmng.h"
0029 
0030 
0031 SKGPropertiesPluginDockWidget::SKGPropertiesPluginDockWidget(QWidget* iParent, SKGDocument* iDocument)
0032     : SKGWidget(iParent, iDocument)
0033 {
0034     SKGTRACEINFUNC(1)
0035     if (iDocument == nullptr) {
0036         return;
0037     }
0038 
0039     ui.setupUi(this);
0040 
0041     ui.kPicture->hide();
0042 
0043     ui.kAdd->setMaximumWidth(ui.kAdd->height());
0044     ui.kRemove->setMaximumWidth(ui.kRemove->height());
0045     ui.kSelectFile->setMaximumWidth(ui.kSelectFile->height());
0046 
0047     ui.kAdd->setIcon(SKGServices::fromTheme(QStringLiteral("list-add")));
0048     ui.kRename->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-ok")));
0049     ui.kRemove->setIcon(SKGServices::fromTheme(QStringLiteral("list-remove")));
0050     ui.kSelectFile->setIcon(SKGServices::fromTheme(QStringLiteral("document-open")));
0051     ui.kOpenBtn->setIcon(SKGServices::fromTheme(QStringLiteral("quickopen")));
0052 
0053     ui.kAttribute->lineEdit()->setPlaceholderText(i18n("Name"));
0054     ui.kValue->lineEdit()->setPlaceholderText(i18n("Value"));
0055 
0056     ui.kForCmb->addItem(i18n("Selection"));
0057     ui.kForCmb->addItem(i18n("All"));
0058 
0059     // Add model
0060     auto modelview = new SKGObjectModelBase(getDocument(), QStringLiteral("parameters"), QStringLiteral("1=1 ORDER BY t_uuid_parent, t_name"), this, QLatin1String(""), false);
0061     auto modelproxy = new SKGSortFilterProxyModel(this);
0062     modelproxy->setSourceModel(modelview);
0063     ui.kView->setModel(modelproxy);
0064 
0065     connect(ui.kFilterEdit, &QLineEdit::textChanged, this, [ = ](const QString & itext) {
0066         modelproxy->setFilterKeyColumn(-1);
0067         modelproxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
0068         modelproxy->setFilterFixedString(itext);
0069     });
0070 
0071     auto actOpenPropertyFileAction = new QAction(QStringLiteral("internal action to open property file"), this);
0072     connect(actOpenPropertyFileAction, &QAction::triggered, this, &SKGPropertiesPluginDockWidget::onOpenPropertyFileByUrl);
0073     SKGMainPanel::getMainPanel()->registerGlobalAction(QStringLiteral("open_property_file"), actOpenPropertyFileAction);
0074 
0075     ui.kView->setDefaultSaveParameters(getDocument(), QStringLiteral("SKG_DEFAULT_PROPERTIES"));
0076     connect(modelview, &SKGObjectModelBase::beforeReset, ui.kView, &SKGTreeView::saveSelection);
0077     connect(modelview, &SKGObjectModelBase::afterReset, ui.kView, &SKGTreeView::resetSelection);
0078     connect(ui.kView, &SKGTableView::selectionChangedDelayed, this, &SKGPropertiesPluginDockWidget::onSelectionChanged);
0079     connect(ui.kForCmb, static_cast<void (SKGComboBox::*)(const QString&)>(&SKGComboBox::currentTextChanged), this, &SKGPropertiesPluginDockWidget::refresh);
0080     connect(ui.kAdd, &QPushButton::clicked, this, &SKGPropertiesPluginDockWidget::onAddProperty);
0081     connect(ui.kRemove, &QPushButton::clicked, this, &SKGPropertiesPluginDockWidget::onRemoveProperty);
0082     connect(ui.kSelectFile, &QPushButton::clicked, this, &SKGPropertiesPluginDockWidget::onSelectFile);
0083     connect(ui.kOpenBtn, &QPushButton::clicked, this, &SKGPropertiesPluginDockWidget::onOpenFile);
0084     connect(ui.kView, &SKGTableView::clickEmptyArea, this, &SKGPropertiesPluginDockWidget::cleanEditor);
0085     connect(ui.kRename, &QPushButton::clicked, this, &SKGPropertiesPluginDockWidget::onRenameProperty);
0086     ui.kView->setTextResizable(false);
0087 }
0088 
0089 SKGPropertiesPluginDockWidget::~SKGPropertiesPluginDockWidget()
0090 {
0091     SKGTRACEINFUNC(1)
0092 }
0093 
0094 void SKGPropertiesPluginDockWidget::refresh()
0095 {
0096     SKGTRACEINFUNC(1)
0097 
0098     // Change filter
0099     auto* proxyModel = qobject_cast<QSortFilterProxyModel*>(ui.kView->model());
0100     auto* model = qobject_cast<SKGObjectModelBase*>(proxyModel->sourceModel());
0101     if (model != nullptr) {
0102         QString filter;
0103         if (ui.kForCmb->currentIndex() == 1) {
0104             filter = QStringLiteral("t_uuid_parent!='document' AND t_name NOT LIKE 'SKG_%'");
0105             ui.kAdd->setEnabled(false);
0106             ui.kSelectFile->setEnabled(false);
0107             ui.kRemove->setEnabled(false);
0108             ui.kAttribute->setEnabled(false);
0109             ui.kValue->setEnabled(false);
0110         } else if (ui.kForCmb->currentIndex() == 0) {
0111             filter = QStringLiteral("t_uuid_parent IN (");
0112             SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
0113             int nb = selection.count();
0114             if (nb != 0) {
0115                 ui.kAdd->setEnabled(true);
0116                 ui.kSelectFile->setEnabled(true);
0117                 ui.kRemove->setEnabled(false);
0118                 ui.kAttribute->setEnabled(true);
0119                 ui.kValue->setEnabled(true);
0120 
0121                 QString tableName;
0122                 for (int i = 0; i < nb; ++i) {
0123                     if (i > 0) {
0124                         filter += ',';
0125                     } else {
0126                         tableName = selection.at(i).getRealTable();
0127                     }
0128                     filter += '\'' % selection.at(i).getUniqueID() % '\'';
0129                 }
0130 
0131                 // Fill combo box
0132                 QString t = tableName;
0133                 if (t.startsWith(QLatin1String("sub"))) {
0134                     t = t.right(t.length() - 3);
0135                 }
0136                 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kAttribute, getDocument(), QStringLiteral("parameters"), QStringLiteral("t_name"), "(t_uuid_parent like '%-" % t % "' OR t_uuid_parent like '%-sub" % t % "') AND t_name NOT LIKE 'SKG_%'");
0137                 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kValue, getDocument(), QStringLiteral("parameters"), QStringLiteral("t_value"), "(t_uuid_parent like '%-" % t % "' OR t_uuid_parent like '%-sub" % t % "') AND t_name NOT LIKE 'SKG_%'");
0138             } else {
0139                 filter += QStringLiteral("'XXX'");  // Always false
0140                 ui.kAdd->setEnabled(false);
0141                 ui.kSelectFile->setEnabled(false);
0142                 ui.kRemove->setEnabled(false);
0143                 ui.kAttribute->setEnabled(false);
0144                 ui.kValue->setEnabled(false);
0145             }
0146             filter += QStringLiteral(") AND t_name NOT LIKE 'SKG_%'");
0147         }
0148         filter += QStringLiteral(" ORDER BY t_uuid_parent, t_name");
0149         ui.kView->saveSelection();
0150 
0151         model->setFilter(filter);
0152         model->refresh();
0153 
0154         ui.kView->resetSelection();
0155     }
0156 
0157     ui.kView->setState(QLatin1String(""));
0158     if (ui.kView->isAutoResized()) {
0159         ui.kView->resizeColumnsToContentsDelayed();
0160     }
0161 
0162     onSelectionChanged();
0163 }
0164 
0165 void SKGPropertiesPluginDockWidget::onSelectionChanged()
0166 {
0167     SKGTRACEINFUNC(10)
0168     int nbSelected = getNbSelectedObjects();
0169     ui.kPicture->hide();
0170     ui.kOpenBtn->hide();
0171     ui.kRemove->setEnabled(nbSelected > 0);
0172     if (nbSelected > 0) {
0173         SKGObjectBase::SKGListSKGObjectBase objs = getSelectedObjects();
0174         SKGPropertyObject obj(objs.at(0));
0175         ui.kAttribute->setText(obj.getAttribute(QStringLiteral("t_name")));
0176         ui.kValue->setText(obj.getAttribute(QStringLiteral("t_value")));
0177 
0178         if (nbSelected == 1) {
0179             QUrl u = obj.getUrl(true);
0180 
0181             ui.kOpenBtn->show();
0182             if (u.scheme() == QStringLiteral("file")) {
0183                 ui.kPicture->show();
0184                 ui.kPicture->showPreview(u);
0185             }
0186         }
0187     }
0188 
0189     if (ui.kView->isAutoResized()) {
0190         ui.kView->resizeColumnsToContentsDelayed();
0191     }
0192 }
0193 
0194 void SKGPropertiesPluginDockWidget::openPropertyFile(const SKGPropertyObject& iProp)
0195 {
0196     SKGTRACEINFUNC(10)
0197     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
0198     QUrl url = iProp.getUrl(true);
0199 
0200     if (!url.scheme().isEmpty() && !QDesktopServices::openUrl(url)) {
0201         QString fileNameToSave = SKGMainPanel::getSaveFileName(QStringLiteral("kfiledialog:///IMPEXP"), QLatin1String(""), SKGMainPanel::getMainPanel());
0202         if (!fileNameToSave.isEmpty()) {
0203             QFile(url.toLocalFile()).copy(fileNameToSave);
0204         }
0205     }
0206     QApplication::restoreOverrideCursor();
0207 }
0208 
0209 void SKGPropertiesPluginDockWidget::onOpenPropertyFileByUrl()
0210 {
0211     SKGTRACEINFUNC(10)
0212     auto* act = qobject_cast<QAction*>(sender());
0213     if (act != nullptr) {
0214         SKGPropertyObject obj(getDocument(), SKGServices::stringToInt(act->property("id").toString()));
0215         openPropertyFile(obj);
0216     }
0217 }
0218 
0219 void SKGPropertiesPluginDockWidget::onOpenFile()
0220 {
0221     SKGTRACEINFUNC(10)
0222     int nbSelected = getNbSelectedObjects();
0223     if (nbSelected == 1) {
0224         SKGObjectBase::SKGListSKGObjectBase objs = getSelectedObjects();
0225         SKGPropertyObject obj(objs.at(0));
0226         openPropertyFile(obj);
0227     }
0228 
0229     if (ui.kView->isAutoResized()) {
0230         ui.kView->resizeColumnsToContentsDelayed();
0231     }
0232 }
0233 
0234 void SKGPropertiesPluginDockWidget::onAddProperty()
0235 {
0236     SKGTRACEINFUNC(10)
0237     SKGError err;
0238     QStringList listUUID;
0239     // Scope for the transaction
0240     {
0241         // Get parameters
0242         QString name = ui.kAttribute->text();
0243         QString value = ui.kValue->text();
0244         QVariant blob;
0245         QFile file(value);
0246         if (file.exists()) {
0247 #ifdef SKG_KF_5102
0248             int mode = KMessageBox::questionTwoActionsCancel(this, i18nc("Question", "Do you want copy or link the file?"),
0249                        QString(),
0250                        KGuiItem(i18nc("Question", "Copy"), QStringLiteral("edit-copy")),
0251                        KGuiItem(i18nc("Question", "Link"), QStringLiteral("edit-link")));
0252             if (mode == KMessageBox::SecondaryAction) {
0253                 return;
0254             }
0255             if (mode == KMessageBox::PrimaryAction) {
0256 #else
0257             int mode = KMessageBox::questionYesNoCancel(this, i18nc("Question", "Do you want copy or link the file?"),
0258                        QString(),
0259                        KGuiItem(i18nc("Question", "Copy"), QStringLiteral("edit-copy")),
0260                        KGuiItem(i18nc("Question", "Link"), QStringLiteral("edit-link")));
0261             if (mode == KMessageBox::Cancel) {
0262                 return;
0263             }
0264             if (mode == KMessageBox::Yes) {
0265 #endif
0266 
0267                 // Value is a file name ==> blob
0268                 if (Q_UNLIKELY(!file.open(QIODevice::ReadOnly))) {
0269                     err = SKGError(ERR_INVALIDARG, i18nc("Error message: could not open the requested file", "Open file '%1' failed", value));
0270                 } else {
0271                     QByteArray blob_bytes = file.readAll();
0272                     if (blob_bytes.isEmpty()) {
0273                         err = SKGError(ERR_INVALIDARG, i18nc("Error message: could not open the requested file", "Open file '%1' failed", value));
0274                     } else {
0275                         blob = blob_bytes;
0276                         value = QFileInfo(value).fileName();
0277                     }
0278 
0279                     // close file
0280                     file.close();
0281                 }
0282             }
0283         }
0284 
0285         // Create properties
0286         IFOK(err) {
0287             SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
0288             int nb = selection.count();
0289             SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Create a user defined property", "Property creation"), err, nb)
0290             for (int i = 0; !err && i < nb; ++i) {
0291                 SKGPropertyObject prop;
0292                 err = selection.at(i).setProperty(name, value, blob, &prop);
0293 
0294                 IFOK(err) {
0295                     listUUID.push_back(prop.getUniqueID());
0296                     err = getDocument()->stepForward(i + 1);
0297                 }
0298             }
0299         }
0300     }
0301 
0302     // status bar
0303     IFOK(err) {
0304         err = SKGError(0, i18nc("The user defined property was successfully created", "Property created"));
0305         ui.kView->selectObjects(listUUID, true);
0306     }
0307     SKGMainPanel::displayErrorMessage(err);
0308 }
0309 
0310 void SKGPropertiesPluginDockWidget::onRenameProperty()
0311 {
0312     SKGTRACEINFUNC(10)
0313     SKGError err;
0314     QStringList listUUID;
0315     // Scope for the transaction
0316     {
0317         // Rename properties
0318         IFOK(err) {
0319             SKGObjectBase::SKGListSKGObjectBase selection = ui.kView->getSelectedObjects();
0320             int nb = selection.count();
0321             SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Create a user defined property", "Rename property"), err, nb)
0322             for (int i = 0; !err && i < nb; ++i) {
0323                 const SKGObjectBase& prop(selection.at(i));
0324                 IFOKDO(err, getDocument()->executeSqliteOrder("UPDATE parameters SET t_name='" % SKGServices::stringToSqlString(ui.kAttribute->text()) % "' WHERE id=" % SKGServices::intToString(prop.getID())))
0325                 IFOK(err) {
0326                     listUUID.push_back(prop.getUniqueID());
0327                     err = getDocument()->stepForward(i + 1);
0328                 }
0329             }
0330         }
0331     }
0332 
0333     // status bar
0334     IFOK(err) {
0335         err = SKGError(0, i18nc("The user property was successfully renamed", "Property renamed"));
0336         ui.kView->selectObjects(listUUID, true);
0337     }
0338     SKGMainPanel::displayErrorMessage(err);
0339 }
0340 
0341 void SKGPropertiesPluginDockWidget::onSelectFile()
0342 {
0343     QString fileName = QFileDialog::getOpenFileName(this, i18nc("Open panel caption", "Select a file"));
0344     ui.kValue->setText(fileName);
0345 }
0346 
0347 void SKGPropertiesPluginDockWidget::onRemoveProperty()
0348 {
0349     SKGError err;
0350     SKGTRACEINFUNCRC(10, err) {
0351         SKGObjectBase::SKGListSKGObjectBase selection = getSelectedObjects();
0352         int nb = selection.count();
0353         SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Verb, delete an item", "Delete"), err, nb)
0354         for (int i = 0; !err && i < nb; ++i) {
0355             err = selection.at(i).remove();
0356             IFOKDO(err, getDocument()->stepForward(i + 1))
0357         }
0358     }
0359 
0360     // status bar
0361     IFOKDO(err, SKGError(0, i18nc("The user defined property was successfully deleted", "Properties deleted.")))
0362     else {
0363         err.addError(ERR_FAIL, i18nc("Error message: Could not delete an item", "Delete failed"));
0364     }
0365 
0366     // Display error
0367     SKGMainPanel::displayErrorMessage(err);
0368 }
0369 
0370 void SKGPropertiesPluginDockWidget::cleanEditor()
0371 {
0372     if (getNbSelectedObjects() == 0) {
0373         ui.kAttribute->setText(QLatin1String(""));
0374         ui.kValue->setText(QLatin1String(""));
0375     }
0376 }
0377 
0378 QWidget* SKGPropertiesPluginDockWidget::mainWidget()
0379 {
0380     return ui.kView;
0381 }
0382 
0383 
0384 
0385