File indexing completed on 2024-12-22 04:17:28
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2007 The University of Toronto * 0004 * netterfield@astro.utoronto.ca * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 ***************************************************************************/ 0012 0013 #include "datamanager.h" 0014 #include "databuttonaction.h" 0015 #include "databutton.h" 0016 0017 #include "dialoglauncher.h" 0018 0019 #include "document.h" 0020 #include "sessionmodel.h" 0021 #include "datacollection.h" 0022 #include "plotitem.h" 0023 #include "plotaxis.h" 0024 #include "labelitem.h" 0025 0026 #include "objectstore.h" 0027 #include "dataobject.h" 0028 #include "curve.h" 0029 #include "equation.h" 0030 #include "vector.h" 0031 #include "matrix.h" 0032 #include "histogram.h" 0033 #include "psd.h" 0034 #include "eventmonitorentry.h" 0035 #include "image.h" 0036 #include "csd.h" 0037 #include "basicplugin.h" 0038 #include "updateserver.h" 0039 0040 #include <QHeaderView> 0041 #include <QToolBar> 0042 #include <QMenu> 0043 #include <QShortcut> 0044 #include <QSortFilterProxyModel> 0045 0046 #ifdef QT5 0047 #define setResizeMode setSectionResizeMode 0048 #endif 0049 0050 namespace Kst { 0051 0052 DataManager::DataManager(QWidget *parent, Document *doc) 0053 : QDialog(parent), _doc(doc), _currentObject(0) { 0054 0055 setupUi(this); 0056 0057 MainWindow::setWidgetFlags(this); 0058 0059 // Setup proxy model for filtering / sorting 0060 _proxyModel = new QSortFilterProxyModel(this); 0061 _proxyModel->setSourceModel(doc->session()); 0062 _proxyModel->setFilterKeyColumn(-1); // Filter on all columns by default 0063 _proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 0064 _session->setModel(_proxyModel); 0065 0066 #if QT_VERSION >= 0x040700 0067 _filterText->setPlaceholderText(tr("Enter your filter here (wildcards allowed)")); 0068 #endif 0069 0070 connect(_filterText, SIGNAL(textChanged(QString)), _proxyModel, SLOT(setFilterWildcard(QString))); 0071 connect(_caseSensitive, SIGNAL(stateChanged(int)), this, SLOT(setCaseSensitivity(int))); 0072 connect(_filterColumn, SIGNAL(currentIndexChanged(int)), this, SLOT(setFilterColumn(int))); 0073 0074 0075 _session->header()->setResizeMode(QHeaderView::ResizeToContents); 0076 _session->setContextMenuPolicy(Qt::CustomContextMenu); 0077 _session->setSortingEnabled(true); 0078 _session->sortByColumn(1); // Sort by type by default 0079 _session->setUniformRowHeights(true); 0080 connect(_session, SIGNAL(customContextMenuRequested(QPoint)), 0081 this, SLOT(showContextMenu(QPoint))); 0082 connect(_session, SIGNAL(doubleClicked(QModelIndex)), 0083 this, SLOT(showEditDialog(QModelIndex))); 0084 0085 // Simple keyboard shortcut for fast object deletion 0086 _deleteShortcut = new QShortcut(Qt::Key_Delete, this); 0087 connect(_deleteShortcut, SIGNAL(activated()), this, SLOT(deleteObject())); 0088 0089 _contextMenu = new QMenu(this); 0090 0091 connect(_purge, SIGNAL(clicked()), this, SLOT(purge())); 0092 connect(_delete, SIGNAL(clicked()), this, SLOT(deleteObject())); 0093 connect(_edit, SIGNAL(clicked()), this, SLOT(showEditDialog())); 0094 } 0095 0096 DataManager::~DataManager() { 0097 // the data manager is only destroyed at exit, so there is no real 0098 // need to clean up anything... (though valgrind thinks we really 0099 // ought to delete all of our actions before we exit) 0100 } 0101 0102 0103 void DataManager::showEvent(QShowEvent*) 0104 { 0105 _session->header()->setResizeMode(QHeaderView::ResizeToContents); 0106 _session->header()->setStretchLastSection(false); 0107 QApplication::processEvents(); 0108 _session->header()->setResizeMode(QHeaderView::Interactive); 0109 } 0110 0111 0112 void DataManager::showContextMenu(const QPoint &position) { 0113 QList<QAction *> actions; 0114 if (_session->indexAt(position).isValid()) { 0115 SessionModel *model = static_cast<SessionModel*>(_doc->session()); 0116 if (!model->parent(_proxyModel->mapToSource(_session->indexAt(position))).isValid()) { 0117 _currentObject = model->objectList()->at(_proxyModel->mapToSource(_session->indexAt(position)).row()); 0118 if (_currentObject) { 0119 QAction *action = new QAction(_currentObject->Name(), this); 0120 action->setEnabled(false); 0121 actions.append(action); 0122 0123 action = new QAction(tr("Edit"), this); 0124 connect(action, SIGNAL(triggered()), this, SLOT(showEditDialog())); 0125 actions.append(action); 0126 0127 if (VectorPtr v = kst_cast<Vector>(_currentObject)) { 0128 0129 action = new QAction(tr("Make Curve"), this); 0130 connect(action, SIGNAL(triggered()), this, SLOT(showCurveDialog())); 0131 actions.append(action); 0132 0133 action = new QAction(tr("Make Power Spectrum"), this); 0134 connect(action, SIGNAL(triggered()), this, SLOT(showPowerSpectrumDialog())); 0135 actions.append(action); 0136 0137 action = new QAction(tr("Make Spectrogram"), this); 0138 connect(action, SIGNAL(triggered()), this, SLOT(showCSDDialog())); 0139 actions.append(action); 0140 0141 action = new QAction(tr("Make Histogram"), this); 0142 connect(action, SIGNAL(triggered()), this, SLOT(showHistogramDialog())); 0143 actions.append(action); 0144 0145 if (!DataObject::filterPluginList().empty()) { 0146 action = new QAction(tr("Apply Filter"), this); 0147 connect(action, SIGNAL(triggered()), this, SLOT(showFilterDialog())); 0148 actions.append(action); 0149 } 0150 } else if (MatrixPtr m = kst_cast<Matrix>(_currentObject)) { 0151 action = new QAction(tr("Make Image"), this); 0152 connect(action, SIGNAL(triggered()), this, SLOT(showImageDialog())); 0153 actions.append(action); 0154 } else if (RelationPtr r = kst_cast<Relation>(_currentObject)) { 0155 0156 QMenu *addMenu = new QMenu(this); 0157 QMenu *removeMenu = new QMenu(this); 0158 0159 foreach (PlotItemInterface *plot, Data::self()->plotList()) { 0160 action = new QAction(plot->plotName(), this); 0161 action->setData(qVariantFromValue(plot)); 0162 addMenu->addAction(action); 0163 0164 PlotItem* plotItem = static_cast<PlotItem*>(plot); 0165 if (plotItem) { 0166 foreach (PlotRenderItem* renderItem, plotItem->renderItems()) { 0167 if (renderItem->relationList().contains(r)) { 0168 action = new QAction(plot->plotName(), this); 0169 action->setData(qVariantFromValue(plot)); 0170 removeMenu->addAction(action); 0171 break; 0172 } 0173 } 0174 } 0175 } 0176 0177 connect(addMenu, SIGNAL(triggered(QAction*)), this, SLOT(addToPlot(QAction*))); 0178 action = new QAction(tr("Add to Plot"), this); 0179 0180 action->setMenu(addMenu); 0181 actions.append(action); 0182 0183 connect(removeMenu, SIGNAL(triggered(QAction*)), this, SLOT(removeFromPlot(QAction*))); 0184 action = new QAction(tr("Remove From Plot"), this); 0185 connect(action, SIGNAL(triggered()), this, SLOT(showImageDialog())); 0186 0187 action->setMenu(removeMenu); 0188 actions.append(action); 0189 0190 if (!DataObject::fitsPluginList().empty()) { 0191 action = new QAction(tr("Apply Fit"), this); 0192 connect(action, SIGNAL(triggered()), this, SLOT(showFitDialog())); 0193 actions.append(action); 0194 } 0195 0196 if (!DataObject::filterPluginList().empty()) { 0197 action = new QAction(tr("Apply Filter"), this); 0198 connect(action, SIGNAL(triggered()), this, SLOT(showFilterDialog())); 0199 actions.append(action); 0200 } 0201 } 0202 0203 // Also add delete action in the menu 0204 action = new QAction(tr("Delete"), this); 0205 connect(action, SIGNAL(triggered()), this, SLOT(deleteObject())); 0206 actions.append(action); 0207 } 0208 } else { 0209 DataObjectPtr dataObject = kst_cast<DataObject>(model->objectList()->at(_proxyModel->mapToSource(_session->indexAt(position)).parent().row())); 0210 if (dataObject) { 0211 if (dataObject->outputVectors().count() > _proxyModel->mapToSource(_session->indexAt(position)).row()) { 0212 _currentObject = dataObject->outputVectors().values()[_proxyModel->mapToSource(_session->indexAt(position)).row()]; 0213 } else { 0214 _currentObject = dataObject->outputMatrices().values()[_proxyModel->mapToSource(_session->indexAt(position)).row() - dataObject->outputVectors().count()]; 0215 } 0216 if (_currentObject) { 0217 QAction *action = new QAction(_currentObject->Name(), this); 0218 action->setEnabled(false); 0219 actions.append(action); 0220 0221 if (VectorPtr v = kst_cast<Vector>(_currentObject)) { 0222 action = new QAction(tr("Make Curve"), this); 0223 connect(action, SIGNAL(triggered()), this, SLOT(showCurveDialog())); 0224 actions.append(action); 0225 0226 action = new QAction(tr("Make Power Spectrum"), this); 0227 connect(action, SIGNAL(triggered()), this, SLOT(showPowerSpectrumDialog())); 0228 actions.append(action); 0229 0230 action = new QAction(tr("Make Spectrogram"), this); 0231 connect(action, SIGNAL(triggered()), this, SLOT(showCSDDialog())); 0232 actions.append(action); 0233 0234 action = new QAction(tr("Make Histogram"), this); 0235 connect(action, SIGNAL(triggered()), this, SLOT(showHistogramDialog())); 0236 actions.append(action); 0237 0238 if (!DataObject::filterPluginList().empty()) { 0239 action = new QAction(tr("Apply Filter"), this); 0240 connect(action, SIGNAL(triggered()), this, SLOT(showFilterDialog())); 0241 actions.append(action); 0242 } 0243 0244 } else if (MatrixPtr m = kst_cast<Matrix>(_currentObject)) { 0245 action = new QAction(tr("Make Image"), this); 0246 connect(action, SIGNAL(triggered()), this, SLOT(showImageDialog())); 0247 actions.append(action); 0248 } 0249 } 0250 } 0251 } 0252 } 0253 if (actions.count() > 0) 0254 QMenu::exec(actions, _session->mapToGlobal(position)); 0255 } 0256 0257 void DataManager::showEditDialog(QModelIndex qml) { 0258 if (!qml.parent().isValid()) { // don't edit slave objects 0259 //SessionModel *model = static_cast<SessionModel*>(_doc->session()); 0260 0261 //_currentObject = model->objectList()->at(_proxyModel->mapToSource(qml).row()); 0262 0263 showEditDialog(_proxyModel->mapToSource(qml).row()); 0264 } 0265 } 0266 0267 0268 void DataManager::showEditDialog() { 0269 0270 if (_session->selectionModel()->selectedIndexes().size()<1) { 0271 return; 0272 } 0273 0274 QModelIndex qml = _session->selectionModel()->selectedIndexes()[0]; 0275 0276 if (qml.parent().isValid()) { // don't edit slave objects. 0277 return; 0278 } 0279 0280 int row = _proxyModel->mapToSource(qml).row(); // Single selection mode => only one selected index 0281 0282 showEditDialog(row); 0283 } 0284 0285 0286 void DataManager::showEditDialog(int row) { 0287 SessionModel *model = static_cast<SessionModel*>(_doc->session()); 0288 if ((row < 0) || (row >=model->objectList()->size())) { 0289 return; 0290 } 0291 DialogLauncher::self()->showObjectDialog(model->objectList()->at(row)); 0292 } 0293 0294 0295 void DataManager::showVectorDialog() { 0296 QString tmp; 0297 DialogLauncher::self()->showVectorDialog(tmp); 0298 } 0299 0300 0301 void DataManager::showMatrixDialog() { 0302 QString tmp; 0303 DialogLauncher::self()->showMatrixDialog(tmp); 0304 } 0305 0306 0307 void DataManager::showScalarDialog() { 0308 QString scalarName; 0309 DialogLauncher::self()->showScalarDialog(scalarName); 0310 } 0311 0312 0313 void DataManager::showStringDialog() { 0314 QString stringName; 0315 DialogLauncher::self()->showStringDialog(stringName); 0316 } 0317 0318 0319 void DataManager::showEventMonitorDialog() { 0320 DialogLauncher::self()->showEventMonitorDialog(); 0321 } 0322 0323 0324 void DataManager::showEquationDialog() { 0325 DialogLauncher::self()->showEquationDialog(); 0326 } 0327 0328 0329 void DataManager::showCurveDialog() { 0330 if (VectorPtr vector = kst_cast<Vector>(_currentObject)) { 0331 DialogLauncher::self()->showCurveDialog(0, vector); 0332 } else { 0333 DialogLauncher::self()->showCurveDialog(); 0334 } 0335 } 0336 0337 0338 void DataManager::showCSDDialog() { 0339 if (VectorPtr vector = kst_cast<Vector>(_currentObject)) { 0340 DialogLauncher::self()->showCSDDialog(0, vector); 0341 } else { 0342 DialogLauncher::self()->showCSDDialog(); 0343 } 0344 } 0345 0346 0347 void DataManager::showPowerSpectrumDialog() { 0348 if (VectorPtr vector = kst_cast<Vector>(_currentObject)) { 0349 DialogLauncher::self()->showPowerSpectrumDialog(0, vector); 0350 } else { 0351 DialogLauncher::self()->showPowerSpectrumDialog(); 0352 } 0353 } 0354 0355 0356 void DataManager::showHistogramDialog() { 0357 if (VectorPtr vector = kst_cast<Vector>(_currentObject)) { 0358 DialogLauncher::self()->showHistogramDialog(0, vector); 0359 } else { 0360 DialogLauncher::self()->showHistogramDialog(); 0361 } 0362 } 0363 0364 0365 void DataManager::showImageDialog() { 0366 if (MatrixPtr matrix = kst_cast<Matrix>(_currentObject)) { 0367 DialogLauncher::self()->showImageDialog(0, matrix); 0368 } else { 0369 DialogLauncher::self()->showImageDialog(); 0370 } 0371 } 0372 0373 0374 void DataManager::showPluginDialog(QString &pluginName) { 0375 if (VectorPtr vector = kst_cast<Vector>(_currentObject)) { 0376 DialogLauncher::self()->showBasicPluginDialog(pluginName, 0, vector); 0377 } else if (CurvePtr curve = kst_cast<Curve>(_currentObject)) { 0378 DialogLauncher::self()->showBasicPluginDialog(pluginName, 0, curve->xVector(), curve->yVector()); 0379 } else { 0380 DialogLauncher::self()->showBasicPluginDialog(pluginName); 0381 } 0382 } 0383 0384 0385 void DataManager::showFilterDialog() { 0386 showPluginDialog(DataObject::filterPluginList().first()); 0387 } 0388 0389 0390 void DataManager::showFitDialog() { 0391 showPluginDialog(DataObject::fitsPluginList().first()); 0392 } 0393 0394 0395 void DataManager::deleteObject() { 0396 SessionModel *model = static_cast<SessionModel*>(_doc->session()); 0397 0398 if (_session->selectionModel()->selectedIndexes().size()<1) { 0399 return; 0400 } 0401 0402 int row = _proxyModel->mapToSource(_session->selectionModel()->selectedIndexes()[0]).row(); // Single selection mode => only one selected index 0403 _currentObject = model->objectList()->at(row); 0404 if (RelationPtr relation = kst_cast<Relation>(_currentObject)) { 0405 Data::self()->removeCurveFromPlots(relation); 0406 _doc->objectStore()->removeObject(relation); 0407 } else if (DataObjectPtr dataObject = kst_cast<DataObject>(_currentObject)) { 0408 _doc->objectStore()->removeObject(dataObject); 0409 } else if (PrimitivePtr primitive = kst_cast<Primitive>(_currentObject)) { 0410 _doc->objectStore()->removeObject(primitive); 0411 } else if (DataSourcePtr datasource = kst_cast<DataSource>(_currentObject)) { 0412 _doc->objectStore()->removeObject(datasource); 0413 } 0414 _currentObject = 0; 0415 UpdateServer::self()->requestUpdateSignal(); 0416 0417 // Now select the next item 0418 _session->selectionModel()->select(_proxyModel->mapFromSource(model->index(row,0)), QItemSelectionModel::Select); 0419 // Cleanup and return 0420 _doc->objectStore()->cleanUpDataSourceList(); 0421 } 0422 0423 void DataManager::addToPlot(QAction* action) { 0424 PlotItem* plotItem = static_cast<PlotItem*>(action->data().value<PlotItemInterface*>()); 0425 RelationPtr relation = kst_cast<Relation>(_currentObject); 0426 if (plotItem && relation) { 0427 PlotRenderItem *renderItem = plotItem->renderItem(PlotRenderItem::Cartesian); 0428 renderItem->addRelation(kst_cast<Relation>(relation)); 0429 plotItem->update(); 0430 } 0431 } 0432 0433 0434 void DataManager::removeFromPlot(QAction* action) { 0435 bool plotUpdated = false; 0436 0437 PlotItem* plotItem = static_cast<PlotItem*>(action->data().value<PlotItemInterface*>()); 0438 RelationPtr relation = kst_cast<Relation>(_currentObject); 0439 if (plotItem && relation) { 0440 foreach (PlotRenderItem* renderItem, plotItem->renderItems()) { 0441 if (renderItem->relationList().contains(relation)) { 0442 renderItem->removeRelation(relation); 0443 plotUpdated = true; 0444 } 0445 } 0446 if (plotUpdated) { 0447 plotItem->update(); 0448 } 0449 } 0450 } 0451 0452 // search through all the objects to see what is a dependency of anything shown. 0453 // FIXME: this is very fragile - objects use objects in all sorts of ways, 0454 // all which have to be listed here. 0455 void DataManager::setUsedFlags() { 0456 _doc->objectStore()->clearUsedFlags(); 0457 0458 // for each relation used in an unhidden plot mark 'used' - O(N) 0459 QList<PlotItem*> plotlist = ViewItem::getItems<PlotItem>(); 0460 foreach (PlotItem *plot, plotlist) { 0461 if (plot->isVisible()) { 0462 foreach (PlotRenderItem *renderer, plot->renderItems()) { 0463 foreach (RelationPtr relation, renderer->relationList()) { 0464 relation->setUsed(true); 0465 } 0466 } 0467 if (plot->xAxis()->axisPlotMarkers().isCurveSource()) { 0468 plot->xAxis()->axisPlotMarkers().curve()->setUsed(true); 0469 } 0470 if (plot->yAxis()->axisPlotMarkers().isCurveSource()) { 0471 plot->yAxis()->axisPlotMarkers().curve()->setUsed(true); 0472 } 0473 if (plot->xAxis()->axisPlotMarkers().isVectorSource()) { 0474 plot->xAxis()->axisPlotMarkers().vector()->setUsed(true); 0475 } 0476 if (plot->yAxis()->axisPlotMarkers().isVectorSource()) { 0477 plot->yAxis()->axisPlotMarkers().vector()->setUsed(true); 0478 } 0479 } 0480 } 0481 0482 QList<LabelItem*> labels = ViewItem::getItems<LabelItem>(); 0483 foreach (LabelItem * label, labels) { 0484 if (label->_labelRc) { 0485 foreach (Primitive* primitive, label->_labelRc->_refObjects) { 0486 primitive->setUsed(true); 0487 } 0488 } 0489 } 0490 0491 // for each primitive used by a relation mark 'used' - O(N) 0492 ObjectList<Relation> relationList = _doc->objectStore()->getObjects<Relation>(); 0493 foreach (RelationPtr object, relationList) { 0494 object->readLock(); 0495 //set used all input and output primitives 0496 foreach (VectorPtr v, object->inputVectors()) { 0497 v->setUsed(true); 0498 } 0499 foreach (VectorPtr v, object->outputVectors()) { 0500 v->setUsed(true); 0501 } 0502 foreach (ScalarPtr s, object->inputScalars()) { 0503 s->setUsed(true); 0504 } 0505 foreach (ScalarPtr s, object->outputScalars()) { 0506 s->setUsed(true); 0507 } 0508 foreach (StringPtr s, object->inputStrings()) { 0509 s->setUsed(true); 0510 } 0511 foreach (StringPtr s, object->outputStrings()) { 0512 s->setUsed(true); 0513 } 0514 foreach (MatrixPtr m, object->inputMatrices()) { 0515 m->setUsed(true); 0516 } 0517 foreach (MatrixPtr m, object->outputMatrices()) { 0518 m->setUsed(true); 0519 } 0520 object->unlock(); 0521 } 0522 0523 0524 ObjectList<DataObject> dataObjectList = _doc->objectStore()->getObjects<DataObject>(); 0525 foreach (DataObjectPtr object, dataObjectList) { 0526 object->readLock(); 0527 //set used all input and output primitives 0528 foreach (PrimitivePtr p, object->inputPrimitives()) { 0529 p->setUsed(true); 0530 } 0531 object->unlock(); 0532 } 0533 } 0534 0535 void DataManager::purge() { 0536 do { 0537 setUsedFlags(); 0538 } while (_doc->objectStore()->deleteUnsetUsedFlags()); 0539 _doc->objectStore()->cleanUpDataSourceList(); 0540 UpdateServer::self()->requestUpdateSignal(); 0541 _session->reset(); 0542 } 0543 0544 void DataManager::setFilterColumn(int column) { 0545 _proxyModel->setFilterKeyColumn(column-1); 0546 } 0547 0548 void DataManager::setCaseSensitivity(int state) { 0549 if (state) { 0550 _proxyModel->setFilterCaseSensitivity(Qt::CaseSensitive); 0551 } else { 0552 _proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 0553 } 0554 } 0555 0556 } 0557 // vim: ts=2 sw=2 et