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