///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011-2012 Statoil ASA, Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// //#include "RiaStdInclude.h" #include "cafPdmDocument.h" #include #include #include #include #include #include #include #include "RimUiTreeView.h" #include "RimUiTreeModelPdm.h" #include "RimReservoirView.h" #include "RimCalcScript.h" #include "RiaApplication.h" #include "RiuMainWindow.h" #include "RimInputPropertyCollection.h" #include "RimExportInputPropertySettings.h" #include "RiaPreferences.h" #include "RiuPreferencesDialog.h" #include "RifEclipseInputFileTools.h" #include "RimInputCase.h" #include "RimBinaryExportSettings.h" #include "RigCaseCellResultsData.h" #include "RimStatisticsCase.h" #include "RimResultCase.h" #include "RimMimeData.h" #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" #include "RimResultSlot.h" #include "RimStatisticsCaseCollection.h" #include "RimIdenticalGridCaseGroup.h" #include "RimCaseCollection.h" #include "RimScriptCollection.h" #include "RimWell.h" #include "RimCellEdgeResultSlot.h" #include "RimWellCollection.h" #include "RimWellPathCollection.h" #include "RimReservoirCellResultsCacher.h" #include "Rim3dOverlayInfoConfig.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" #include "RimProject.h" #include "RimOilField.h" #include "RimAnalysisModels.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimUiTreeView::RimUiTreeView(QWidget *parent /*= 0*/) : QTreeView(parent) { setHeaderHidden(true); m_pasteAction = new QAction(QString("Paste"), this); connect(m_pasteAction, SIGNAL(triggered()), SLOT(slotPastePdmObjects())); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimUiTreeView::~RimUiTreeView() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::contextMenuEvent(QContextMenuEvent* event) { m_pasteAction->setEnabled(hasClipboardValidData()); if (selectionModel() && selectionModel()->selection().size() == 0) { // Clicking in blank space in tree view QMenu menu; menu.addAction(QString("New Grid Case Group"), this, SLOT(slotAddCaseGroup())); menu.exec(event->globalPos()); return; } RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem && uiItem->dataObject()) { QMenu menu; // Range filters if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New View"), this, SLOT(slotAddView())); menu.addAction(QString("Copy View"), this, SLOT(slotCopyPdmObjectToClipboard())); menu.addAction(m_pasteAction); menu.addAction(QString("Delete"), this, SLOT(slotDeleteView())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New Range Filter"), this, SLOT(slotAddRangeFilter())); menu.addAction(QString("Slice I Filter"), this, SLOT(slotAddSliceFilterI())); menu.addAction(QString("Slice J Filter"), this, SLOT(slotAddSliceFilterJ())); menu.addAction(QString("Slice K Filter"), this, SLOT(slotAddSliceFilterK())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Insert Range Filter"), this, SLOT(slotAddRangeFilter())); menu.addAction(QString("Slice I Filter"), this, SLOT(slotAddSliceFilterI())); menu.addAction(QString("Slice J Filter"), this, SLOT(slotAddSliceFilterJ())); menu.addAction(QString("Slice K Filter"), this, SLOT(slotAddSliceFilterK())); menu.addSeparator(); menu.addAction(QString("Delete"), this, SLOT(slotDeleteRangeFilter())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New Property Filter"), this, SLOT(slotAddPropertyFilter())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Insert Property Filter"), this, SLOT(slotAddPropertyFilter())); menu.addSeparator(); menu.addAction(QString("Delete"), this, SLOT(slotDeletePropertyFilter())); } else if (dynamic_cast(uiItem->dataObject().p())) { RiaApplication* app = RiaApplication::instance(); { QAction* action = menu.addAction(QString("Edit"), this, SLOT(slotEditScript())); if (app->scriptEditorPath().isEmpty()) { action->setEnabled(false); } } menu.addAction(QString("New"), this, SLOT(slotNewScript())); menu.addSeparator(); { QAction* action = menu.addAction(QString("Execute"), this, SLOT(slotExecuteScript())); if (app->octavePath().isEmpty()) { action->setEnabled(false); } } } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Add Input Property"), this, SLOT(slotAddInputProperty())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Delete"), this, SLOT(slotDeleteObjectFromContainer())); menu.addAction(QString("Save Property To File"), this, SLOT(slotWriteInputProperty())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Save Property To File"), this, SLOT(slotWriteBinaryResultAsInputProperty())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New Statistics Case"), this, SLOT(slotNewStatisticsCase())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New View"), this, SLOT(slotAddView())); menu.addAction(QString("Compute"), this, SLOT(slotComputeStatistics())); menu.addAction(QString("Close"), this, SLOT(slotCloseCase())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Copy"), this, SLOT(slotCopyPdmObjectToClipboard())); menu.addAction(m_pasteAction); menu.addAction(QString("Close"), this, SLOT(slotCloseCase())); menu.addAction(QString("New View"), this, SLOT(slotAddView())); menu.addAction(QString("New Grid Case Group"), this, SLOT(slotAddCaseGroup())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("New Grid Case Group"), this, SLOT(slotAddCaseGroup())); menu.addAction(m_pasteAction); menu.addAction(QString("Close"), this, SLOT(slotDeleteObjectFromPdmPointersField())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(m_pasteAction); // Check if parent field is a StatisticsCaseCollection RimCaseCollection* rimCaseCollection = dynamic_cast(uiItem->dataObject().p()); if (RimIdenticalGridCaseGroup::isStatisticsCaseCollection(rimCaseCollection)) { menu.addAction(QString("New Statistics Case"), this, SLOT(slotNewStatisticsCase())); } } else if (dynamic_cast(uiItem->dataObject().p()) || dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Add Script Path"), this, SLOT(slotAddScriptPath())); menu.addAction(QString("Delete Script Path"), this, SLOT(slotDeleteScriptPath())); } else if (dynamic_cast(uiItem->dataObject().p())) { menu.addAction(QString("Delete All Well Paths"), this, SLOT(slotDeleteAllWellPaths())); RiuMainWindow* ruiMainWindow = RiuMainWindow::instance(); ruiMainWindow->appendActionsContextMenuForPdmObject(uiItem->dataObject().p(), &menu); } else if (dynamic_cast(uiItem->dataObject().p())) { RiuMainWindow* ruiMainWindow = RiuMainWindow::instance(); ruiMainWindow->appendActionsContextMenuForPdmObject(uiItem->dataObject().p(), &menu); menu.addAction(QString("New Grid Case Group"), this, SLOT(slotAddCaseGroup())); } // Execute script on selection of cases RiuMainWindow* ruiMainWindow = RiuMainWindow::instance(); if (ruiMainWindow) { std::vector cases; ruiMainWindow->selectedCases(cases); if (cases.size() > 0) { QMenu* executeMenu = menu.addMenu("Execute script"); RiaApplication* app = RiaApplication::instance(); RimProject* proj = app->project(); if (proj && proj->scriptCollection()) { RimScriptCollection* rootScriptCollection = proj->scriptCollection(); // Root script collection holds a list of subdirectories of user defined script folders for (size_t i = 0; i < rootScriptCollection->subDirectories.size(); i++) { RimScriptCollection* subDir = rootScriptCollection->subDirectories[i]; if (subDir) { appendScriptItems(executeMenu, subDir); } } } menu.addSeparator(); menu.addMenu(executeMenu); } } appendToggleItemActions(menu); menu.exec(event->globalPos()); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddChildItem() { QModelIndex index = currentIndex(); QAbstractItemModel* myModel = model(); // Insert a single row at the end of the collection of items int itemCount = myModel->rowCount(index); if (!myModel->insertRow(itemCount, index)) return; selectionModel()->setCurrentIndex(myModel->index(0, 0, index), QItemSelectionModel::ClearAndSelect); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteItem() { QModelIndex index = currentIndex(); QAbstractItemModel* myModel = model(); if (!myModel->removeRow(index.row(), index.parent())) return; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeletePropertyFilter() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { myModel->deletePropertyFilter(currentIndex()); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteRangeFilter() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { myModel->deleteRangeFilter(currentIndex()); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddPropertyFilter() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimCellPropertyFilter* propFilter = myModel->addPropertyFilter(currentIndex(), insertedIndex); setCurrentIndex(insertedIndex); if (propFilter) { propFilter->parentContainer()->reservoirView()->createDisplayModelAndRedraw(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddRangeFilter() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimCellRangeFilter* newFilter = myModel->addRangeFilter(currentIndex(), insertedIndex); setCurrentIndex(insertedIndex); if (newFilter && newFilter->parentContainer()) { newFilter->parentContainer()->reservoirView()->createDisplayModelAndRedraw(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddSliceFilterI() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimCellRangeFilter* rangeFilter = myModel->addRangeFilter(currentIndex(), insertedIndex); RimCellRangeFilterCollection* rangeFilterCollection = rangeFilter->parentContainer(); rangeFilter->name = QString("Slice I (%1)").arg(rangeFilterCollection->rangeFilters().size()); rangeFilter->cellCountI = 1; rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED); rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE); rangeFilterCollection->reservoirView()->createDisplayModelAndRedraw(); setCurrentIndex(insertedIndex); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddSliceFilterJ() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimCellRangeFilter* rangeFilter = myModel->addRangeFilter(currentIndex(), insertedIndex); RimCellRangeFilterCollection* rangeFilterCollection = rangeFilter->parentContainer(); rangeFilter->name = QString("Slice J (%1)").arg(rangeFilterCollection->rangeFilters().size()); rangeFilter->cellCountJ = 1; rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED); rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE); rangeFilterCollection->reservoirView()->createDisplayModelAndRedraw(); setCurrentIndex(insertedIndex); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddSliceFilterK() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimCellRangeFilter* rangeFilter = myModel->addRangeFilter(currentIndex(), insertedIndex); RimCellRangeFilterCollection* rangeFilterCollection = rangeFilter->parentContainer(); rangeFilter->name = QString("Slice K (%1)").arg(rangeFilterCollection->rangeFilters().size()); rangeFilter->cellCountK = 1; rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED); rangeFilterCollection->reservoirView()->scheduleGeometryRegen(RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE); rangeFilterCollection->reservoirView()->createDisplayModelAndRedraw(); setCurrentIndex(insertedIndex); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotEditScript() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem) { RimCalcScript* calcScript = dynamic_cast(uiItem->dataObject().p()); RiaApplication* app = RiaApplication::instance(); QString scriptEditor = app->scriptEditorPath(); if (!scriptEditor.isEmpty()) { QStringList arguments; arguments << calcScript->absolutePath; QProcess* myProcess = new QProcess(this); myProcess->start(scriptEditor, arguments); if (!myProcess->waitForStarted(1000)) { QMessageBox::warning(RiuMainWindow::instance(), "Script editor", "Failed to start script editor executable\n" + scriptEditor); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotNewScript() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); RimCalcScript* calcScript = NULL; RimScriptCollection * scriptColl = NULL; calcScript = dynamic_cast(uiItem->dataObject().p()); scriptColl = dynamic_cast(uiItem->dataObject().p()); QString fullPathNewScript; if (calcScript ) { QFileInfo existingScriptFileInfo(calcScript->absolutePath()); fullPathNewScript = existingScriptFileInfo.absolutePath(); } else if (scriptColl) { fullPathNewScript = scriptColl->directory(); } else { return; } QString fullPathFilenameNewScript; fullPathFilenameNewScript = fullPathNewScript + "/untitled.m"; int num= 1; while (QFileInfo(fullPathFilenameNewScript).exists()) { fullPathFilenameNewScript = fullPathNewScript + "/untitled" + QString::number(num) + ".m"; num++; } RiaApplication* app = RiaApplication::instance(); QString scriptEditor = app->scriptEditorPath(); if (!scriptEditor.isEmpty()) { QStringList arguments; arguments << fullPathFilenameNewScript; QProcess* myProcess = new QProcess(this); myProcess->start(scriptEditor, arguments); if (!myProcess->waitForStarted(1000)) { QMessageBox::warning(RiuMainWindow::instance(), "Script editor", "Failed to start script editor executable\n" + scriptEditor); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotExecuteScript() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem) { RimCalcScript* calcScript = dynamic_cast(uiItem->dataObject().p()); RiaApplication* app = RiaApplication::instance(); QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options // -p path // Add path to the head of the search path for function files. The value of path specified on the command line // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or // user startup files that set the internal load path through one of the path functions. // -q // Don't print the usual greeting and version message at startup. // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); QStringList arguments; arguments.append("--path"); arguments << octaveFunctionSearchPath; arguments.append("--path"); arguments << QApplication::applicationDirPath(); arguments.append("-q"); arguments << calcScript->absolutePath(); RiaApplication::instance()->launchProcess(octavePath, arguments); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotExecuteScriptForSelectedCases() { QAction* action = qobject_cast(sender()); if (!action) return; QString encodedModelIndex = action->data().toString(); QModelIndex mi = RimUiTreeView::getModelIndexFromString(model(), encodedModelIndex); RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (!myModel) return; caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(mi); if (uiItem) { RimCalcScript* calcScript = dynamic_cast(uiItem->dataObject().p()); if (!calcScript) return; RiaApplication* app = RiaApplication::instance(); QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options // -p path // Add path to the head of the search path for function files. The value of path specified on the command line // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or // user startup files that set the internal load path through one of the path functions. // -q // Don't print the usual greeting and version message at startup. // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); QStringList arguments; arguments.append("--path"); arguments << octaveFunctionSearchPath; arguments.append("--path"); arguments << QApplication::applicationDirPath(); arguments.append("-q"); arguments << calcScript->absolutePath(); // Get case ID from selected cases in selection model std::vector caseIdsInSelection; { QItemSelectionModel* m = selectionModel(); CVF_ASSERT(m); caf::PdmObjectGroup group; QModelIndexList mil = m->selectedRows(); myModel->populateObjectGroupFromModelIndexList(mil, &group); std::vector > typedObjects; group.objectsByType(&typedObjects); for (size_t i = 0; i < typedObjects.size(); i++) { RimCase* rimReservoir = typedObjects[i]; caseIdsInSelection.push_back(rimReservoir->caseId); } } if (caseIdsInSelection.size() > 0) { RiaApplication::instance()->launchProcessForMultipleCases(octavePath, arguments, caseIdsInSelection); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddView() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); QModelIndex insertedIndex; myModel->addReservoirView(index, insertedIndex); // Expand parent collection and inserted view item setExpandedUpToRoot(insertedIndex); setCurrentIndex(insertedIndex); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteView() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { myModel->deleteReservoirView(currentIndex()); RiaApplication* app = RiaApplication::instance(); app->setActiveReservoirView(NULL); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) { caf::PdmObject* pdmObject = NULL; if (selected.indexes().size() == 1) { QModelIndex mi = selected.indexes()[0]; if (mi.isValid()) { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { caf::PdmUiTreeItem* treeItem = myModel->getTreeItemFromIndex(mi); if (treeItem && treeItem->dataObject()) { pdmObject = treeItem->dataObject(); } } } } emit selectedObjectChanged(pdmObject); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::setModel(QAbstractItemModel* model) { QTreeView::setModel(model); if (selectionModel()) { connect(selectionModel(), SIGNAL(selectionChanged( const QItemSelection & , const QItemSelection & )), SLOT(slotSelectionChanged( const QItemSelection & , const QItemSelection & ))); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddInputProperty() { RiaApplication* app = RiaApplication::instance(); QString defaultDir = app->defaultFileDialogDirectory("INPUT_FILES"); QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Eclipse Input Property Files", defaultDir, "All Files (*.* *)"); if (fileNames.isEmpty()) return; // Remember the directory to next time defaultDir = QFileInfo(fileNames.last()).absolutePath(); app->setDefaultFileDialogDirectory("INPUT_FILES", defaultDir); QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); RimInputPropertyCollection* inputPropertyCollection = dynamic_cast(uiItem->dataObject().p()); if (inputPropertyCollection) { myModel->addInputProperty(index, fileNames); setCurrentIndex(index); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteObjectFromContainer() { QModelIndex index = currentIndex(); if (!index.isValid()) return; RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) myModel->deleteInputProperty(index); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotWriteInputProperty() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); RimInputProperty* inputProperty = dynamic_cast(uiItem->dataObject().p()); if (!inputProperty) return; { bool isResolved = false; if (inputProperty->resolvedState == RimInputProperty::RESOLVED || inputProperty->resolvedState == RimInputProperty::RESOLVED_NOT_SAVED) { isResolved = true; } if (!isResolved) { QMessageBox::warning(RiuMainWindow::instance(), "Export failure", "Property is not resolved, and then it is not possible to export the property."); return; } } RimExportInputSettings exportSettings; exportSettings.eclipseKeyword = inputProperty->eclipseKeyword; // Find input reservoir for this property RimInputCase* inputReservoir = NULL; { std::vector parentObjects; inputProperty->parentObjectsOfType(parentObjects); CVF_ASSERT(parentObjects.size() == 1); RimInputPropertyCollection* inputPropertyCollection = parentObjects[0]; if (!inputPropertyCollection) return; std::vector parentObjects2; inputPropertyCollection->parentObjectsOfType(parentObjects2); CVF_ASSERT(parentObjects2.size() == 1); inputReservoir = parentObjects2[0]; } if (!inputReservoir) return; { QString projectFolder; RiaApplication* app = RiaApplication::instance(); QString projectFileName = app->currentProjectFileName(); if (!projectFileName.isEmpty()) { QFileInfo fi(projectFileName); projectFolder = fi.absolutePath(); } else { projectFolder = inputReservoir->locationOnDisc(); } QString outputFileName = projectFolder + "/" + inputProperty->eclipseKeyword; exportSettings.fileName = outputFileName; } RiuPreferencesDialog preferencesDialog(this, &exportSettings, "Export Eclipse Property to Text File"); if (preferencesDialog.exec() == QDialog::Accepted) { bool isOk = RifEclipseInputFileTools::writePropertyToTextFile(exportSettings.fileName, inputReservoir->reservoirData(), 0, inputProperty->resultName, exportSettings.eclipseKeyword); if (isOk) { inputProperty->fileName = exportSettings.fileName; inputProperty->eclipseKeyword = exportSettings.eclipseKeyword; inputProperty->resolvedState = RimInputProperty::RESOLVED; inputProperty->updateConnectedEditors(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotWriteBinaryResultAsInputProperty() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); RimResultSlot* resultSlot = dynamic_cast(uiItem->dataObject().p()); if (!resultSlot) return; if (!resultSlot->reservoirView()) return; if (!resultSlot->reservoirView()->eclipseCase()) return; if (!resultSlot->reservoirView()->eclipseCase()->reservoirData()) return; RimBinaryExportSettings exportSettings; exportSettings.eclipseKeyword = resultSlot->resultVariable(); { QString projectFolder; RiaApplication* app = RiaApplication::instance(); QString projectFileName = app->currentProjectFileName(); if (!projectFileName.isEmpty()) { QFileInfo fi(projectFileName); projectFolder = fi.absolutePath(); } else { projectFolder = resultSlot->reservoirView()->eclipseCase()->locationOnDisc(); } QString outputFileName = projectFolder + "/" + resultSlot->resultVariable(); exportSettings.fileName = outputFileName; } RiuPreferencesDialog preferencesDialog(this, &exportSettings, "Export Binary Eclipse Data to Text File"); if (preferencesDialog.exec() == QDialog::Accepted) { size_t timeStep = resultSlot->reservoirView()->currentTimeStep(); RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); bool isOk = RifEclipseInputFileTools::writeBinaryResultToTextFile(exportSettings.fileName, resultSlot->reservoirView()->eclipseCase()->reservoirData(), porosityModel, timeStep, resultSlot->resultVariable(), exportSettings.eclipseKeyword, exportSettings.undefinedValue); if (!isOk) { QMessageBox::critical(NULL, "File export", "Failed to exported current result to " + exportSettings.fileName); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotCloseCase() { QModelIndexList miList; miList << currentIndex(); if (userConfirmedGridCaseGroupChange(miList)) { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QItemSelectionModel* m = selectionModel(); CVF_ASSERT(m); caf::PdmObjectGroup group; QModelIndexList mil = m->selectedRows(); myModel->populateObjectGroupFromModelIndexList(mil, &group); std::vector > typedObjects; group.objectsByType(&typedObjects); for (size_t i = 0; i < typedObjects.size(); i++) { RimCase* rimReservoir = typedObjects[i]; myModel->deleteReservoir(rimReservoir); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotNewStatisticsCase() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; RimStatisticsCase* newObject = myModel->addStatisticalCalculation(currentIndex(), insertedIndex); setCurrentIndex(insertedIndex); setExpanded(insertedIndex, true); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotComputeStatistics() { QModelIndex index = currentIndex(); RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); RimStatisticsCase* statisticsCase = dynamic_cast(uiItem->dataObject().p()); if (!statisticsCase) return; statisticsCase->computeStatistics(); if (statisticsCase->reservoirViews.size() == 0) { slotAddView(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddCaseGroup() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { QModelIndex insertedIndex; myModel->addCaseGroup(insertedIndex); setCurrentIndex(insertedIndex); setExpanded(insertedIndex, true); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteObjectFromPdmPointersField() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { myModel->deleteObjectFromPdmPointersField(currentIndex()); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotCopyPdmObjectToClipboard() { QItemSelectionModel* m = selectionModel(); QModelIndexList mil = m->selectedRows(); if (mil.size() == 0) { return; } MimeDataWithIndexes* myObject = new MimeDataWithIndexes; myObject->setIndexes(mil); QClipboard* clipboard = QApplication::clipboard(); if (clipboard) { clipboard->setMimeData(myObject); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotPastePdmObjects() { if (!currentIndex().isValid()) return; RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (!myModel) return; QModelIndexList miList; miList << currentIndex(); if (userConfirmedGridCaseGroupChange(miList)) { caf::PdmObjectGroup objectGroup; createPdmObjectsFromClipboard(&objectGroup); if (objectGroup.objects().size() == 0) return; myModel->addObjects(currentIndex(), objectGroup); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::createPdmObjectsFromClipboard(caf::PdmObjectGroup* objectGroup) { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (!myModel) return; QClipboard* clipboard = QApplication::clipboard(); if (!clipboard) return; const MimeDataWithIndexes* mdWithIndexes = dynamic_cast(clipboard->mimeData()); if (!mdWithIndexes) return; QModelIndexList indexList = mdWithIndexes->indexes(); myModel->populateObjectGroupFromModelIndexList(indexList, objectGroup); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::keyPressEvent(QKeyEvent* keyEvent) { RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem) { if (dynamic_cast(uiItem->dataObject().p()) || dynamic_cast(uiItem->dataObject().p())) { if (keyEvent->matches(QKeySequence::Copy)) { slotCopyPdmObjectToClipboard(); keyEvent->setAccepted(true); return; } } if (dynamic_cast(uiItem->dataObject().p()) || dynamic_cast(uiItem->dataObject().p()) || dynamic_cast(uiItem->dataObject().p()) || dynamic_cast(uiItem->dataObject().p())) { if (keyEvent->matches(QKeySequence::Paste)) { slotPastePdmObjects(); keyEvent->setAccepted(true); return; } } } switch (keyEvent->key()) { case Qt::Key_Space: case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Select: { executeSelectionToggleOperation(TOGGLE); keyEvent->setAccepted(true); return; } } QTreeView::keyPressEvent(keyEvent); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimUiTreeView::hasClipboardValidData() { QClipboard* clipboard = QApplication::clipboard(); if (clipboard) { if (dynamic_cast(clipboard->mimeData())) { return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::dropEvent(QDropEvent* dropEvent) { QModelIndexList affectedModels; if (dropEvent->dropAction() == Qt::MoveAction) { const MimeDataWithIndexes* myMimeData = qobject_cast(dropEvent->mimeData()); if (myMimeData) { affectedModels = myMimeData->indexes(); } } QModelIndex dropIndex = indexAt(dropEvent->pos()); if (dropIndex.isValid()) { affectedModels.push_back(dropIndex); } if (userConfirmedGridCaseGroupChange(affectedModels)) { QTreeView::dropEvent(dropEvent); } } //-------------------------------------------------------------------------------------------------- /// Displays a question to the user when a grid case group with statistical results is about to change //-------------------------------------------------------------------------------------------------- bool RimUiTreeView::userConfirmedGridCaseGroupChange(const QModelIndexList& itemIndexList) { if (itemIndexList.size() == 0) return true; RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { caf::PdmObjectGroup pog; for (int i = 0; i < itemIndexList.size(); i++) { QModelIndex itemIndex = itemIndexList.at(i); if (!itemIndex.isValid()) continue; RimIdenticalGridCaseGroup* gridCaseGroup = myModel->gridCaseGroupFromItemIndex(itemIndex); if (gridCaseGroup) { if (hasAnyStatisticsResults(gridCaseGroup)) { if (pog.objects().count(gridCaseGroup) == 0) { pog.addObject(gridCaseGroup); } } } } std::vector > typedObjects; pog.objectsByType(&typedObjects); if (typedObjects.size() > 0) { RiuMainWindow* mainWnd = RiuMainWindow::instance(); QMessageBox msgBox(mainWnd); msgBox.setIcon(QMessageBox::Question); QString questionText; if (typedObjects.size() == 1) { questionText = QString("This operation will invalidate statistics results in grid case group\n\"%1\".\n").arg(typedObjects[0]->name()); questionText += "Computed results in this group will be deleted if you continue."; } else { questionText = "This operation will invalidate statistics results in grid case groups\n"; for (size_t i = 0; i < typedObjects.size(); i++) { questionText += QString("\"%1\"\n").arg(typedObjects[i]->name()); } questionText += "Computed results in these groups will be deleted if you continue."; } msgBox.setText(questionText); msgBox.setInformativeText("Do you want to continue?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); int ret = msgBox.exec(); if (ret == QMessageBox::No) { return false; } } } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimUiTreeView::hasAnyStatisticsResults(RimIdenticalGridCaseGroup* gridCaseGroup) { CVF_ASSERT(gridCaseGroup); for (size_t i = 0; i < gridCaseGroup->statisticsCaseCollection()->reservoirs().size(); i++) { RimStatisticsCase* rimStaticsCase = dynamic_cast(gridCaseGroup->statisticsCaseCollection()->reservoirs[i]); if (rimStaticsCase) { if (rimStaticsCase->hasComputedStatistics()) { return true; } } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::mousePressEvent(QMouseEvent* mouseEvent) { // TODO: Handle multiple selection and changing state using mouse // This is a bit tricky due to the fact that there is no obvious way to trap if the check box is pressed // and not other parts of the check box GUI item /* if (checkAndHandleToggleOfMultipleSelection()) { mouseEvent->setAccepted(true); return; } */ QTreeView::mousePressEvent(mouseEvent); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void setExpandedState(QStringList& nodes, QTreeView* view, QAbstractItemModel* model, const QModelIndex startIndex, QString path) { path += QString::number(startIndex.row()) + QString::number(startIndex.column()); for (int i = 0; i < model->rowCount(startIndex); ++i) { QModelIndex nextIndex = model->index(i, 0, startIndex); QString nextPath = path + QString::number(nextIndex.row()) + QString::number(nextIndex.column()); if(!nodes.contains(nextPath)) continue; setExpandedState(nodes, view, model, model->index(i, 0, startIndex), path); } if (nodes.contains(path)) { view->setExpanded( startIndex.sibling(startIndex.row(), 0), true ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void storeExpandedState(QStringList & nodes, QTreeView * view, QAbstractItemModel * model, const QModelIndex startIndex, QString path) { path += QString::number(startIndex.row()) + QString::number(startIndex.column()); for (int i = 0; i < model->rowCount(startIndex); ++i) { if(!view->isExpanded(model->index(i, 0, startIndex))) continue; storeExpandedState(nodes, view, model, model->index(i, 0, startIndex), path); } if (view->isExpanded(startIndex)) { nodes << path; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::applyTreeViewStateFromString(const QString& treeViewState) { if (this->model()) { this->collapseAll(); QStringList nodes = treeViewState.split(";"); QString path; setExpandedState(nodes, this, this->model(), QModelIndex(), path); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::storeTreeViewStateToString(QString& treeViewState) { if (this->model()) { QStringList nodes; QString path; storeExpandedState(nodes, this, this->model(), QModelIndex(), path); treeViewState = nodes.join(";"); } } //-------------------------------------------------------------------------------------------------- /// Find index based of an encode QString ; ;...; /// Set the decoded index as current index in the QAbstractItemView //-------------------------------------------------------------------------------------------------- QModelIndex RimUiTreeView::getModelIndexFromString(QAbstractItemModel* model, const QString& currentIndexString) { QStringList modelIndexStringList = currentIndexString.split(";"); QModelIndex mi; foreach (QString modelIndexString, modelIndexStringList) { QStringList items = modelIndexString.split(" "); if (items.size() != 2) continue; int row = items[0].toInt(); int col = items[1].toInt(); mi = model->index(row, col, mi); } return mi; } //-------------------------------------------------------------------------------------------------- /// Store path to model index in item view using follwoing encoding into a QString ; ;...; //-------------------------------------------------------------------------------------------------- void RimUiTreeView::encodeStringFromModelIndex(const QModelIndex mi, QString& encodedModelIndex) { if (!mi.isValid()) return; QModelIndex localModelIdx = mi; while (localModelIdx.isValid()) { if (encodedModelIndex.isEmpty()) { encodedModelIndex = QString("%1 %2").arg(localModelIdx.row()).arg(localModelIdx.column()) + encodedModelIndex; } else { encodedModelIndex = QString("%1 %2;").arg(localModelIdx.row()).arg(localModelIdx.column()) + encodedModelIndex; } localModelIdx = localModelIdx.parent(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::setExpandedUpToRoot(const QModelIndex& itemIndex) { QModelIndex mi = itemIndex; while (mi.isValid()) { this->setExpanded(mi, true); mi = mi.parent(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotAddScriptPath() { QString selectedFolder = QFileDialog::getExistingDirectory(this, "Select script folder"); if (!selectedFolder.isEmpty()) { QString filePathString = RiaApplication::instance()->preferences()->scriptDirectories(); QChar separator(';'); if (!filePathString.isEmpty() && !filePathString.endsWith(separator, Qt::CaseInsensitive)) { filePathString += separator; } filePathString += selectedFolder; RiaApplication::instance()->preferences()->scriptDirectories = filePathString; RiaApplication::instance()->applyPreferences(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteScriptPath() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem) { if (dynamic_cast(uiItem->dataObject().p())) { RimScriptCollection* scriptCollection = dynamic_cast(uiItem->dataObject().p()); QString toBeRemoved = scriptCollection->directory; QString originalFilePathString = RiaApplication::instance()->preferences()->scriptDirectories(); QString filePathString = originalFilePathString.remove(toBeRemoved); // Remove duplicate separators QChar separator(';'); QString regExpString = QString("%1{1,5}").arg(separator); filePathString.replace(QRegExp(regExpString), separator); // Remove separator at end if (filePathString.endsWith(separator)) { filePathString = filePathString.left(filePathString.size() - 1); } RiaApplication::instance()->preferences()->scriptDirectories = filePathString; RiaApplication::instance()->applyPreferences(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::appendToggleItemActions(QMenu& contextMenu) { if (selectionModel() && selectionModel()->selectedIndexes().size() > 0) { foreach (QModelIndex index, selectionModel()->selectedIndexes()) { if (!index.isValid()) return; if (!(model()->flags(index) & Qt::ItemIsUserCheckable)) return; } if (contextMenu.actions().size() > 0) { contextMenu.addSeparator(); } if (selectionModel()->selectedIndexes().size() > 1) { contextMenu.addAction(QString("On"), this, SLOT(slotToggleItemsOn())); contextMenu.addAction(QString("Off"), this, SLOT(slotToggleItemsOff())); contextMenu.addAction(QString("Toggle"), this, SLOT(slotToggleItems())); } else { QModelIndex mIdx = selectionModel()->selectedIndexes()[0]; caf::PdmUiTreeItem* treeItem = caf::UiTreeModelPdm::getTreeItemFromIndex(mIdx); if (treeItem && treeItem->childCount()) { contextMenu.addAction(QString("Sub Items On"), this, SLOT(slotToggleItemsOn())); contextMenu.addAction(QString("Sub Items Off"), this, SLOT(slotToggleItemsOff())); contextMenu.addAction(QString("Toggle Sub items"), this, SLOT(slotToggleItems())); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotToggleItems() { executeSelectionToggleOperation(TOGGLE); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::executeSelectionToggleOperation(SelectionToggleType toggleState) { RimUiTreeModelPdm* myModel = dynamic_cast(model()); myModel->setObjectToggleStateForSelection(selectionModel()->selectedIndexes(), toggleState); return; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotToggleItemsOn() { executeSelectionToggleOperation(TOGGLE_ON); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotToggleItemsOff() { executeSelectionToggleOperation(TOGGLE_OFF); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::appendScriptItems(QMenu* menu, RimScriptCollection* scriptCollection) { CVF_ASSERT(menu); QDir dir(scriptCollection->directory); QMenu* subMenu = menu->addMenu(dir.dirName()); for (size_t i = 0; i < scriptCollection->calcScripts.size(); i++) { RimCalcScript* calcScript = scriptCollection->calcScripts[i]; QFileInfo fi(calcScript->absolutePath()); QString menuText = fi.baseName(); QAction* scriptAction = subMenu->addAction(menuText, this, SLOT(slotExecuteScriptForSelectedCases())); QModelIndex mi; RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { mi = myModel->getModelIndexFromPdmObject(calcScript); } QString encodedModelIndex; RimUiTreeView::encodeStringFromModelIndex(mi, encodedModelIndex); scriptAction->setData(QVariant(encodedModelIndex)); } for (size_t i = 0; i < scriptCollection->subDirectories.size(); i++) { RimScriptCollection* subDir = scriptCollection->subDirectories[i]; appendScriptItems(subMenu, subDir); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimUiTreeView::slotDeleteAllWellPaths() { RimUiTreeModelPdm* myModel = dynamic_cast(model()); if (myModel) { myModel->deleteAllWellPaths(currentIndex()); caf::PdmUiTreeItem* uiItem = myModel->getTreeItemFromIndex(currentIndex()); if (uiItem && uiItem->dataObject()) { RimWellPathCollection* wellPathCollection = dynamic_cast(uiItem->dataObject().p()); if (wellPathCollection) { wellPathCollection->scheduleGeometryRegenAndRedrawViews(); } } } }