mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Version 0.8.6
This commit is contained in:
@@ -331,6 +331,8 @@ bool RIApplication::closeProject(bool askToSaveIfDirty)
|
||||
{
|
||||
RIMainWindow* mainWnd = RIMainWindow::instance();
|
||||
|
||||
terminateProcess();
|
||||
|
||||
if (false)
|
||||
{
|
||||
QMessageBox msgBox(mainWnd);
|
||||
@@ -353,7 +355,7 @@ bool RIApplication::closeProject(bool askToSaveIfDirty)
|
||||
|
||||
mainWnd->cleanupGuiBeforeProjectClose();
|
||||
|
||||
caf::EffectCache::instance()->clear();
|
||||
caf::EffectGenerator::clearEffectCache();
|
||||
m_project->close();
|
||||
|
||||
onProjectOpenedOrClosed();
|
||||
@@ -417,16 +419,19 @@ bool RIApplication::openEclipseCase(const QString& caseName, const QString& case
|
||||
|
||||
RimReservoirView* riv = rimResultReservoir->createAndAddReservoirView();
|
||||
|
||||
// Select SOIL as default result variable
|
||||
riv->cellResult()->resultType = RimDefines::DYNAMIC_NATIVE;
|
||||
riv->cellResult()->resultVariable = "SOIL";
|
||||
riv->animationMode = true;
|
||||
if (m_preferences->autocomputeSOIL)
|
||||
{
|
||||
// Select SOIL as default result variable
|
||||
riv->cellResult()->resultType = RimDefines::DYNAMIC_NATIVE;
|
||||
riv->cellResult()->resultVariable = "SOIL";
|
||||
riv->animationMode = true;
|
||||
}
|
||||
|
||||
riv->loadDataAndUpdate();
|
||||
|
||||
if (!riv->cellResult()->hasResult())
|
||||
{
|
||||
riv->cellResult()->resultVariable = RimDefines::nonSelectedResultName();
|
||||
riv->cellResult()->resultVariable = RimDefines::undefinedResultName();
|
||||
}
|
||||
|
||||
onProjectOpenedOrClosed();
|
||||
@@ -455,7 +460,7 @@ bool RIApplication::openInputEclipseCase(const QString& caseName, const QStringL
|
||||
|
||||
if (!riv->cellResult()->hasResult())
|
||||
{
|
||||
riv->cellResult()->resultVariable = RimDefines::nonSelectedResultName();
|
||||
riv->cellResult()->resultVariable = RimDefines::undefinedResultName();
|
||||
}
|
||||
|
||||
onProjectOpenedOrClosed();
|
||||
@@ -536,10 +541,12 @@ void RIApplication::setUseShaders(bool enable)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RIApplication::useShaders() const
|
||||
{
|
||||
if (!m_preferences->useShaders) return false;
|
||||
|
||||
bool isShadersSupported = caf::Viewer::isShadersSupported();
|
||||
if (!isShadersSupported) return false;
|
||||
|
||||
return m_preferences->useShaders;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -721,7 +728,7 @@ void RIApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus
|
||||
// get a chance to run before we delete the object
|
||||
if (m_workerProcess)
|
||||
{
|
||||
m_workerProcess->deleteLater();
|
||||
m_workerProcess->close();
|
||||
}
|
||||
m_workerProcess = NULL;
|
||||
|
||||
@@ -749,23 +756,33 @@ void RIApplication::slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RIApplication::launchProcess(const QString& program, const QStringList& arguments)
|
||||
{
|
||||
m_workerProcess = new caf::UiProcess(this);
|
||||
connect(m_workerProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(slotWorkerProcessFinished(int, QProcess::ExitStatus)));
|
||||
|
||||
RIMainWindow::instance()->processMonitor()->startMonitorWorkProcess(m_workerProcess);
|
||||
|
||||
m_workerProcess->start(program, arguments);
|
||||
if (!m_workerProcess->waitForStarted(1000))
|
||||
if (m_workerProcess == NULL)
|
||||
{
|
||||
m_workerProcess->deleteLater();
|
||||
m_workerProcess = NULL;
|
||||
m_workerProcess = new caf::UiProcess(this);
|
||||
connect(m_workerProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(slotWorkerProcessFinished(int, QProcess::ExitStatus)));
|
||||
|
||||
RIMainWindow::instance()->processMonitor()->stopMonitorWorkProcess();
|
||||
RIMainWindow::instance()->processMonitor()->startMonitorWorkProcess(m_workerProcess);
|
||||
|
||||
m_workerProcess->start(program, arguments);
|
||||
if (!m_workerProcess->waitForStarted(1000))
|
||||
{
|
||||
m_workerProcess->close();
|
||||
m_workerProcess = NULL;
|
||||
|
||||
RIMainWindow::instance()->processMonitor()->stopMonitorWorkProcess();
|
||||
|
||||
QMessageBox::warning(RIMainWindow::instance(), "Script execution", "Failed to start script executable located at\n" + program);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(NULL, "Script execution", "An Octave process is still running. Please stop this process before executing a new script.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -853,3 +870,16 @@ void RIApplication::applyPreferences()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIApplication::terminateProcess()
|
||||
{
|
||||
if (m_workerProcess)
|
||||
{
|
||||
m_workerProcess->close();
|
||||
}
|
||||
|
||||
m_workerProcess = NULL;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
QString octavePath() const;
|
||||
|
||||
bool launchProcess(const QString& program, const QStringList& arguments);
|
||||
void terminateProcess();
|
||||
|
||||
RIPreferences* preferences();
|
||||
void readPreferences();
|
||||
|
||||
@@ -42,6 +42,8 @@ RIPreferences::RIPreferences(void)
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&lastUsedProjectFileName,"lastUsedProjectFileName", "Last Used Project File", "", "", "");
|
||||
lastUsedProjectFileName.setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "Compute SOIL if not on disk", "", "", "");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -41,6 +41,9 @@ public: // Pdm Fields
|
||||
|
||||
caf::PdmField<QString> lastUsedProjectFileName;
|
||||
|
||||
caf::PdmField<bool> autocomputeSOIL;
|
||||
|
||||
|
||||
protected:
|
||||
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute);
|
||||
};
|
||||
|
||||
@@ -66,7 +66,7 @@ bool RifEclipseInputFileTools::openGridFile(const QString& fileName, RigReservoi
|
||||
FILE* gridFilePointer = util_fopen(fileName.toLatin1().data(), "r");
|
||||
if (!gridFilePointer) return false;
|
||||
|
||||
// Main grid Dimentions
|
||||
// Main grid dimensions
|
||||
// SPECGRID - This is whats normally available, but not really the input to Eclipse.
|
||||
// DIMENS - Is what Eclipse expects and uses, but is not defined in the GRID section and is not (?) available normally
|
||||
// ZCORN, COORD, ACTNUM, MAPAXES
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#endif //USE_ECL_LIB
|
||||
|
||||
#include <QFileInfo>
|
||||
#include "cafProgressInfo.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Constructor
|
||||
@@ -105,7 +106,11 @@ bool RifEclipseOutputFileTools::keywordsOnFile(QStringList* keywords, size_t num
|
||||
CVF_ASSERT(keywords);
|
||||
keywords->clear();
|
||||
|
||||
|
||||
size_t numKeywords = ecl_file_get_num_distinct_kw(m_file);
|
||||
|
||||
caf::ProgressInfo info(numKeywords, "Reading Keywords on file");
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numKeywords; i++)
|
||||
{
|
||||
@@ -148,6 +153,8 @@ bool RifEclipseOutputFileTools::keywordsOnFile(QStringList* keywords, size_t num
|
||||
{
|
||||
keywords->append(QString(kw));
|
||||
}
|
||||
|
||||
info.setProgress(i);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -142,7 +142,15 @@ QStringList RifEclipseRestartFilesetAccess::resultNames()
|
||||
bool RifEclipseRestartFilesetAccess::results(const QString& resultName, size_t timeStep, std::vector<double>* values)
|
||||
{
|
||||
size_t numOccurrences = m_files[timeStep]->numOccurrences(resultName);
|
||||
CVF_ASSERT(m_numGrids == numOccurrences);
|
||||
|
||||
// No results for this result variable for current time step found
|
||||
if (numOccurrences == 0) return true;
|
||||
|
||||
// Result handling depends on presens of result values for all grids
|
||||
if (m_numGrids != numOccurrences)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < numOccurrences; i++)
|
||||
|
||||
@@ -67,7 +67,7 @@ bool RifReaderEclipseInput::open(const QString& fileName, RigReservoir* reservoi
|
||||
close();
|
||||
|
||||
// Should we handle gridless properties ?
|
||||
// If so, they must match dimentions, and a grid afterwards must match dimension
|
||||
// If so, they must match dimensions, and a grid afterwards must match dimension
|
||||
|
||||
// Add file:
|
||||
// Open file
|
||||
|
||||
@@ -381,7 +381,11 @@ bool RifReaderEclipseOutput::buildMetaData(RigReservoir* reservoir)
|
||||
QStringList staticResultNames = staticResults;
|
||||
|
||||
QList<QDateTime> staticDate;
|
||||
staticDate.push_back(m_timeSteps.front());
|
||||
if (m_timeSteps.size() > 0)
|
||||
{
|
||||
staticDate.push_back(m_timeSteps.front());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(staticResultNames.size()); ++i)
|
||||
{
|
||||
size_t resIndex = resCellResults->addEmptyScalarResult(RimDefines::STATIC_NATIVE, staticResultNames[i]);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "cvfTexture.h"
|
||||
#include "cvfSampler.h"
|
||||
#include "cvfScalarMapper.h"
|
||||
#include "cafEffectGenerator.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -87,22 +88,16 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(
|
||||
const RigGridBase* grid = dynamic_cast<const RigGridBase*>(generator->activeGrid());
|
||||
|
||||
CVF_ASSERT(grid != NULL);
|
||||
const std::vector< double >* cellScalarResults = NULL;
|
||||
bool cellScalarResultUseGlobalActiveIndex = true;
|
||||
|
||||
const std::vector< double >* edgeScalarResults[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
bool cellScalarResultUseGlobalActiveIndex = true;
|
||||
bool edgeScalarResultUseGlobalActiveIndex[6];
|
||||
|
||||
if (cellResultSlot->hasResult())
|
||||
{
|
||||
const std::vector< std::vector<double> >& scalarResultTimeSteps = grid->mainGrid()->results()->cellScalarResults(cellResultSlot->gridScalarIndex());
|
||||
if (cellResultSlot->hasDynamicResult())
|
||||
if (!cellResultSlot->hasDynamicResult())
|
||||
{
|
||||
cellScalarResults = &scalarResultTimeSteps[timeStepIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
cellScalarResults = &scalarResultTimeSteps[0];
|
||||
// Static result values are located at time step 0
|
||||
timeStepIndex = 0;
|
||||
}
|
||||
|
||||
cellScalarResultUseGlobalActiveIndex = grid->mainGrid()->results()->isUsingGlobalActiveIndex(cellResultSlot->gridScalarIndex());
|
||||
@@ -118,8 +113,6 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(
|
||||
{
|
||||
if (resultIndices[cubeFaceIdx] != cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
const std::vector< std::vector<double> >& scalarResultTimeSteps = grid->mainGrid()->results()->cellScalarResults(resultIndices[cubeFaceIdx]);
|
||||
edgeScalarResults[cubeFaceIdx] = &scalarResultTimeSteps[0]; // Assuming only static edge results
|
||||
edgeScalarResultUseGlobalActiveIndex[cubeFaceIdx] = grid->mainGrid()->results()->isUsingGlobalActiveIndex(resultIndices[cubeFaceIdx]);
|
||||
}
|
||||
}
|
||||
@@ -143,18 +136,16 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(
|
||||
float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color
|
||||
size_t cellIndex = quadToCell[quadIdx];
|
||||
|
||||
size_t resultIndex = cellIndex;
|
||||
size_t resultValueIndex = cellIndex;
|
||||
if (cellScalarResultUseGlobalActiveIndex)
|
||||
{
|
||||
resultIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
resultValueIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
}
|
||||
|
||||
if (cellScalarResults )
|
||||
{
|
||||
if (resultIndex != cvf::UNDEFINED_SIZE_T)
|
||||
double scalarValue = grid->mainGrid()->results()->cellScalarResult(timeStepIndex, cellResultSlot->gridScalarIndex(), resultValueIndex);
|
||||
if (scalarValue != HUGE_VAL)
|
||||
{
|
||||
double scalarValue = (*cellScalarResults)[resultIndex];
|
||||
|
||||
cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0];
|
||||
}
|
||||
else
|
||||
@@ -174,19 +165,17 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(
|
||||
{
|
||||
edgeColor = -1.0f; // Undefined texture coord. Shader handles this.
|
||||
|
||||
resultIndex = cellIndex;
|
||||
resultValueIndex = cellIndex;
|
||||
if (edgeScalarResultUseGlobalActiveIndex[cubeFaceIdx])
|
||||
{
|
||||
resultIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
resultValueIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
}
|
||||
|
||||
if (resultIndices[cubeFaceIdx] != cvf::UNDEFINED_SIZE_T && resultIndex != cvf::UNDEFINED_SIZE_T)
|
||||
// Assuming static values to be mapped onto cell edge, always using time step zero
|
||||
double scalarValue = grid->mainGrid()->results()->cellScalarResult(0, resultIndices[cubeFaceIdx], resultValueIndex);
|
||||
if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue)
|
||||
{
|
||||
double scalarValue = (*(edgeScalarResults[cubeFaceIdx]))[resultIndex];
|
||||
if(scalarValue != ignoredScalarValue)
|
||||
{
|
||||
edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0];
|
||||
}
|
||||
edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0];
|
||||
}
|
||||
|
||||
cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx);
|
||||
@@ -250,6 +239,20 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const
|
||||
&& m_defaultCellColor == otherCellFaceEffectGenerator->m_defaultCellColor
|
||||
)
|
||||
{
|
||||
cvf::ref<cvf::TextureImage> texImg2 = new cvf::TextureImage;
|
||||
|
||||
if (otherCellFaceEffectGenerator->m_edgeScalarMapper.notNull())
|
||||
{
|
||||
otherCellFaceEffectGenerator->m_edgeScalarMapper->updateTexture(texImg2.p());
|
||||
if (!caf::ScalarMapperEffectGenerator::isImagesEqual(m_edgeTextureImage.p(), texImg2.p())) return false;
|
||||
}
|
||||
|
||||
if (otherCellFaceEffectGenerator->m_cellScalarMapper.notNull())
|
||||
{
|
||||
otherCellFaceEffectGenerator->m_cellScalarMapper->updateTexture(texImg2.p());
|
||||
if (!caf::ScalarMapperEffectGenerator::isImagesEqual(m_cellTextureImage.p(), texImg2.p())) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -264,6 +267,9 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const
|
||||
caf::EffectGenerator* CellEdgeEffectGenerator::copy() const
|
||||
{
|
||||
CellEdgeEffectGenerator * newEffect = new CellEdgeEffectGenerator(m_edgeScalarMapper.p(), m_cellScalarMapper.p());
|
||||
newEffect->m_edgeTextureImage = m_edgeTextureImage;
|
||||
newEffect->m_cellTextureImage = m_cellTextureImage;
|
||||
|
||||
newEffect->setOpacityLevel(m_opacityLevel);
|
||||
newEffect->setCullBackfaces(m_cullBackfaces);
|
||||
newEffect->setUndefinedColor(m_undefinedColor);
|
||||
@@ -316,23 +322,25 @@ void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect)
|
||||
|
||||
// Set up textures
|
||||
|
||||
cvf::ref<cvf::TextureImage> edgeTexImg = new cvf::TextureImage;
|
||||
cvf::ref<cvf::TextureImage> cellTexImg = new cvf::TextureImage;
|
||||
m_edgeTextureImage = new cvf::TextureImage;
|
||||
m_cellTextureImage = new cvf::TextureImage;
|
||||
|
||||
m_edgeScalarMapper->updateTexture(edgeTexImg.p());
|
||||
cvf::ref<cvf::TextureImage> modifiedCellTextImage;
|
||||
m_edgeScalarMapper->updateTexture(m_edgeTextureImage.p());
|
||||
if (m_cellScalarMapper.notNull())
|
||||
{
|
||||
m_cellScalarMapper->updateTexture(cellTexImg.p());
|
||||
cellTexImg = caf::ScalarMapperEffectGenerator::addAlphaAndUndefStripes(cellTexImg.p(), m_undefinedColor, m_opacityLevel);
|
||||
m_cellScalarMapper->updateTexture(m_cellTextureImage.p());
|
||||
modifiedCellTextImage = caf::ScalarMapperEffectGenerator::addAlphaAndUndefStripes(m_cellTextureImage.p(), m_undefinedColor, m_opacityLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
cellTexImg->allocate(2,1);
|
||||
cellTexImg->fill(cvf::Color4ub(cvf::Color4f(m_defaultCellColor, m_opacityLevel)));
|
||||
modifiedCellTextImage = new cvf::TextureImage;
|
||||
modifiedCellTextImage->allocate(2,1);
|
||||
modifiedCellTextImage->fill(cvf::Color4ub(cvf::Color4f(m_defaultCellColor, m_opacityLevel)));
|
||||
}
|
||||
|
||||
cvf::ref<cvf::Texture> edgeTexture = new cvf::Texture(edgeTexImg.p());
|
||||
cvf::ref<cvf::Texture> cellTexture = new cvf::Texture(cellTexImg.p());
|
||||
cvf::ref<cvf::Texture> edgeTexture = new cvf::Texture(m_edgeTextureImage.p());
|
||||
cvf::ref<cvf::Texture> cellTexture = new cvf::Texture(modifiedCellTextImage.p());
|
||||
|
||||
cvf::ref<cvf::Sampler> sampler = new cvf::Sampler;
|
||||
sampler->setWrapMode(cvf::Sampler::CLAMP_TO_EDGE);
|
||||
|
||||
@@ -58,17 +58,18 @@ public:
|
||||
void setCullBackfaces(bool cullBackFaces) { m_cullBackfaces = cullBackFaces; }
|
||||
void setDefaultCellColor(cvf::Color3f color) { m_defaultCellColor = color; }
|
||||
|
||||
protected:
|
||||
virtual bool isEqual( const EffectGenerator* other ) const;
|
||||
virtual EffectGenerator* copy() const;
|
||||
|
||||
|
||||
protected:
|
||||
virtual void updateForShaderBasedRendering(cvf::Effect* effect) const;
|
||||
virtual void updateForFixedFunctionRendering(cvf::Effect* effect) const;
|
||||
|
||||
private:
|
||||
cvf::cref<cvf::ScalarMapper> m_edgeScalarMapper;
|
||||
cvf::cref<cvf::ScalarMapper> m_cellScalarMapper;
|
||||
cvf::cref<cvf::ScalarMapper> m_edgeScalarMapper;
|
||||
mutable cvf::ref<cvf::TextureImage> m_edgeTextureImage;
|
||||
cvf::cref<cvf::ScalarMapper> m_cellScalarMapper;
|
||||
mutable cvf::ref<cvf::TextureImage> m_cellTextureImage;
|
||||
|
||||
float m_opacityLevel;
|
||||
bool m_cullBackfaces;
|
||||
|
||||
@@ -588,16 +588,12 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis
|
||||
const double lowerBound = (*pfIt)->lowerBound();
|
||||
const double upperBound = (*pfIt)->upperBound();
|
||||
|
||||
const std::vector< std::vector<double> >& scalarResultTimeSteps = grid->mainGrid()->results()->cellScalarResults((*pfIt)->resultDefinition->gridScalarIndex());
|
||||
const std::vector< double >* scalarResult = NULL;
|
||||
size_t scalarResultIndex = (*pfIt)->resultDefinition->gridScalarIndex();
|
||||
|
||||
if ((*pfIt)->resultDefinition()->hasDynamicResult())
|
||||
// Set time step to zero for static results
|
||||
if ((*pfIt)->resultDefinition()->hasStaticResult())
|
||||
{
|
||||
scalarResult = &(scalarResultTimeSteps[timeStepIndex]);
|
||||
}
|
||||
else if ((*pfIt)->resultDefinition()->hasStaticResult())
|
||||
{
|
||||
scalarResult = &(scalarResultTimeSteps[0]);
|
||||
timeStepIndex = 0;
|
||||
}
|
||||
|
||||
const RimCellFilter::FilterModeType filterType = (*pfIt)->filterMode();
|
||||
@@ -608,15 +604,13 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis
|
||||
{
|
||||
if ( (*cellVisibility)[cellIndex] )
|
||||
{
|
||||
size_t resultIndex = cellIndex;
|
||||
size_t resultValueIndex = cellIndex;
|
||||
if (useGlobalActiveIndex)
|
||||
{
|
||||
resultIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
resultValueIndex = grid->cell(cellIndex).globalActiveIndex();
|
||||
}
|
||||
|
||||
double scalarValue = HUGE_VAL;
|
||||
if (resultIndex != cvf::UNDEFINED_SIZE_T) scalarValue = (*scalarResult)[resultIndex];
|
||||
|
||||
double scalarValue = grid->mainGrid()->results()->cellScalarResult(timeStepIndex, scalarResultIndex, resultValueIndex);
|
||||
if (lowerBound <= scalarValue && scalarValue <= upperBound)
|
||||
{
|
||||
if (filterType == RimCellFilter::EXCLUDE)
|
||||
|
||||
@@ -187,7 +187,7 @@ QList<caf::PdmOptionItemInfo> RimCellEdgeResultSlot::calculateValueOptions(const
|
||||
|
||||
}
|
||||
|
||||
optionList.push_front(caf::PdmOptionItemInfo( "None", "" ));
|
||||
optionList.push_front(caf::PdmOptionItemInfo( RimDefines::undefinedResultName(), "" ));
|
||||
|
||||
if (useOptionsOnly) *useOptionsOnly = true;
|
||||
|
||||
|
||||
@@ -33,6 +33,6 @@ public:
|
||||
REMOVED
|
||||
};
|
||||
|
||||
static QString nonSelectedResultName() { return "None"; }
|
||||
static QString undefinedResultName() { return "None"; }
|
||||
};
|
||||
|
||||
|
||||
@@ -19,17 +19,20 @@
|
||||
#include "RIStdInclude.h"
|
||||
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
#include "RifReaderMockModel.h"
|
||||
|
||||
#include "RimReservoir.h"
|
||||
#include "RimReservoirView.h"
|
||||
|
||||
#include "RigReservoir.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigReservoirCellResults.h"
|
||||
|
||||
#include "RimReservoirView.h"
|
||||
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include "cafPdmUiPushButtonEditor.h"
|
||||
|
||||
#include <QString>
|
||||
#include "RifReaderMockModel.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@@ -39,6 +42,10 @@ RimReservoir::RimReservoir()
|
||||
m_rigReservoir = NULL;
|
||||
|
||||
CAF_PDM_InitField(&caseName, "CaseName", QString(), "Case name", "", "" ,"");
|
||||
// CAF_PDM_InitField(&releaseResultMemory, "ReleaseResultMemory", true, "Release result memory", "", "" ,"");
|
||||
// releaseResultMemory.setIOReadable(false);
|
||||
// releaseResultMemory.setIOWritable(false);
|
||||
// releaseResultMemory.setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName());
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&reservoirViews, "ReservoirViews", "", "", "", "");
|
||||
}
|
||||
@@ -141,7 +148,7 @@ void RimReservoir::removeResult(const QString& resultName)
|
||||
// Set cell result variable to none if displaying
|
||||
if (result->resultVariable() == resultName)
|
||||
{
|
||||
result->resultVariable.v() = QString("None");
|
||||
result->resultVariable.v() = RimDefines::undefinedResultName();
|
||||
result->loadResult();
|
||||
|
||||
rebuildDisplayModel = true;
|
||||
@@ -154,7 +161,7 @@ void RimReservoir::removeResult(const QString& resultName)
|
||||
RimCellPropertyFilter* propertyFilter = *it;
|
||||
if (propertyFilter->resultDefinition->resultVariable.v() == resultName)
|
||||
{
|
||||
propertyFilter->resultDefinition->resultVariable.v() = QString("None");
|
||||
propertyFilter->resultDefinition->resultVariable.v() = RimDefines::undefinedResultName();
|
||||
propertyFilter->resultDefinition->loadResult();
|
||||
propertyFilter->setDefaultValues();
|
||||
|
||||
@@ -173,3 +180,43 @@ void RimReservoir::removeResult(const QString& resultName)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimReservoir::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
|
||||
{
|
||||
if (changedField == &releaseResultMemory)
|
||||
{
|
||||
if (m_rigReservoir.notNull())
|
||||
{
|
||||
for (size_t i = 0; i < reservoirViews().size(); i++)
|
||||
{
|
||||
RimReservoirView* reservoirView = reservoirViews()[i];
|
||||
CVF_ASSERT(reservoirView);
|
||||
|
||||
RimResultSlot* result = reservoirView->cellResult;
|
||||
CVF_ASSERT(result);
|
||||
|
||||
result->resultVariable.v() = RimDefines::undefinedResultName();
|
||||
result->loadResult();
|
||||
|
||||
RimCellEdgeResultSlot* cellEdgeResult = reservoirView->cellEdgeResult;
|
||||
CVF_ASSERT(cellEdgeResult);
|
||||
|
||||
cellEdgeResult->resultVariable.v() = RimDefines::undefinedResultName();
|
||||
cellEdgeResult->loadResult();
|
||||
|
||||
reservoirView->createDisplayModelAndRedraw();
|
||||
}
|
||||
|
||||
RigReservoirCellResults* results = m_rigReservoir->mainGrid()->results();
|
||||
if (results)
|
||||
{
|
||||
results->clearAllResults();
|
||||
}
|
||||
}
|
||||
|
||||
releaseResultMemory = oldValue.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
|
||||
class QString;
|
||||
|
||||
class RigReservoir;
|
||||
class RigGridBase;
|
||||
class RimReservoirView;
|
||||
@@ -55,6 +56,7 @@ public:
|
||||
|
||||
// Fields:
|
||||
caf::PdmField<QString> caseName;
|
||||
caf::PdmField<bool> releaseResultMemory;
|
||||
|
||||
caf::PdmPointersField<RimReservoirView*> reservoirViews;
|
||||
|
||||
@@ -66,6 +68,7 @@ protected:
|
||||
// Overridden methods
|
||||
virtual void initAfterRead();
|
||||
|
||||
virtual void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue );
|
||||
|
||||
protected:
|
||||
cvf::ref<RigReservoir> m_rigReservoir;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "RigGridBase.h"
|
||||
#include "RigReservoir.h"
|
||||
#include "RIApplication.h"
|
||||
#include "RIPreferences.h"
|
||||
|
||||
#include "cafEffectGenerator.h"
|
||||
#include "cafFrameAnimationControl.h"
|
||||
@@ -665,7 +666,11 @@ void RimReservoirView::loadDataAndUpdate()
|
||||
RigReservoirCellResults* results = gridCellResults();
|
||||
CVF_ASSERT(results);
|
||||
|
||||
results->loadOrComputeSOIL();
|
||||
RIApplication* app = RIApplication::instance();
|
||||
if (app->preferences()->autocomputeSOIL)
|
||||
{
|
||||
results->loadOrComputeSOIL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ RimResultDefinition::RimResultDefinition()
|
||||
CAF_PDM_InitObject("Result Definition", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&resultType, "ResultType", "Type", "", "", "");
|
||||
CAF_PDM_InitField(&resultVariable, "ResultVariable", RimDefines::nonSelectedResultName(), "Variable", "", "", "" );
|
||||
CAF_PDM_InitField(&resultVariable, "ResultVariable", RimDefines::undefinedResultName(), "Variable", "", "", "" );
|
||||
|
||||
resultVariable.setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void RimResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* changedFie
|
||||
{
|
||||
if (changedField == &resultType)
|
||||
{
|
||||
resultVariable = RimDefines::nonSelectedResultName();
|
||||
resultVariable = RimDefines::undefinedResultName();
|
||||
}
|
||||
|
||||
loadResult();
|
||||
@@ -118,7 +118,7 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
||||
{
|
||||
optionList.push_back(caf::PdmOptionItemInfo( varList[i], varList[i]));
|
||||
}
|
||||
optionList.push_front(caf::PdmOptionItemInfo( RimDefines::nonSelectedResultName(), RimDefines::nonSelectedResultName() ));
|
||||
optionList.push_front(caf::PdmOptionItemInfo( RimDefines::undefinedResultName(), RimDefines::undefinedResultName() ));
|
||||
|
||||
if (useOptionsOnly) *useOptionsOnly = true;
|
||||
|
||||
|
||||
@@ -62,7 +62,10 @@ void RimResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, co
|
||||
changeLegendConfig(this->resultVariable());
|
||||
}
|
||||
|
||||
if (newValue != "None") if (m_reservoirView) m_reservoirView->animationMode = true;
|
||||
if (newValue != RimDefines::undefinedResultName())
|
||||
{
|
||||
if (m_reservoirView) m_reservoirView->animationMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
RimResultDefinition::fieldChangedByUi(changedField, oldValue, newValue);
|
||||
|
||||
@@ -456,10 +456,7 @@ void RimUiTreeView::slotExecuteScript()
|
||||
arguments.append("-q");
|
||||
arguments << calcScript->absolutePath();
|
||||
|
||||
if (!RIApplication::instance()->launchProcess(octavePath, arguments))
|
||||
{
|
||||
QMessageBox::warning(RIMainWindow::instance(), "Script execution", "Failed to start script executable located at\n" + octavePath);
|
||||
}
|
||||
RIApplication::instance()->launchProcess(octavePath, arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,20 +250,16 @@ double RigGridBase::cellScalar(size_t timeStepIndex, size_t scalarSetIndex, size
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigGridBase::cellScalar(size_t timeStepIndex, size_t scalarSetIndex, size_t cellIndex) const
|
||||
{
|
||||
size_t resultIndex = cellIndex;
|
||||
size_t resultValueIndex = cellIndex;
|
||||
|
||||
bool useGlobalActiveIndex = m_mainGrid->results()->isUsingGlobalActiveIndex(scalarSetIndex);
|
||||
if (useGlobalActiveIndex)
|
||||
{
|
||||
resultIndex = cell(cellIndex).globalActiveIndex();
|
||||
if (resultIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL;
|
||||
resultValueIndex = cell(cellIndex).globalActiveIndex();
|
||||
if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL;
|
||||
}
|
||||
|
||||
const std::vector< std::vector<double> >& scalarResult = m_mainGrid->results()->cellScalarResults(scalarSetIndex);
|
||||
|
||||
if (!(timeStepIndex < scalarResult.size() && resultIndex < scalarResult[timeStepIndex].size())) return HUGE_VAL;
|
||||
|
||||
return scalarResult[timeStepIndex][resultIndex];
|
||||
return m_mainGrid->results()->cellScalarResult(timeStepIndex, scalarSetIndex, resultValueIndex);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -347,6 +347,12 @@ bool RigReservoirBuilderMock::dynamicResult(RigReservoir* reservoir, const QStri
|
||||
}
|
||||
}
|
||||
|
||||
// Set result size to zero for some timesteps
|
||||
if ((stepIndex + 1) % 3 == 0)
|
||||
{
|
||||
values->clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,11 +152,19 @@ std::vector< std::vector<double> > & RigReservoirCellResults::cellScalarResults(
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector< std::vector<double> >& RigReservoirCellResults::cellScalarResults( size_t scalarResultIndex ) const
|
||||
double RigReservoirCellResults::cellScalarResult(size_t timeStepIndex, size_t scalarResultIndex, size_t resultValueIndex)
|
||||
{
|
||||
CVF_TIGHT_ASSERT(scalarResultIndex < resultCount());
|
||||
|
||||
return m_cellScalarResults[scalarResultIndex];
|
||||
if (scalarResultIndex < resultCount() &&
|
||||
timeStepIndex < m_cellScalarResults[scalarResultIndex].size() &&
|
||||
resultValueIndex != cvf::UNDEFINED_SIZE_T &&
|
||||
resultValueIndex < m_cellScalarResults[scalarResultIndex][timeStepIndex].size())
|
||||
{
|
||||
return m_cellScalarResults[scalarResultIndex][timeStepIndex][resultValueIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return HUGE_VAL;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -172,8 +180,10 @@ size_t RigReservoirCellResults::findOrLoadScalarResult(RimDefines::ResultCatType
|
||||
|
||||
if (cellScalarResults(resultGridIndex).size()) return resultGridIndex;
|
||||
|
||||
// Generated and Input properties should always be loaded up front.
|
||||
CVF_ASSERT(type == RimDefines::STATIC_NATIVE || type == RimDefines::DYNAMIC_NATIVE);
|
||||
if (type == RimDefines::GENERATED)
|
||||
{
|
||||
return cvf::UNDEFINED_SIZE_T;
|
||||
}
|
||||
|
||||
if (m_readerInterface.notNull())
|
||||
{
|
||||
@@ -475,3 +485,15 @@ void RigReservoirCellResults::removeResult(const QString& resultName)
|
||||
|
||||
m_resultInfos[resultIdx].m_resultType = RimDefines::REMOVED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigReservoirCellResults::clearAllResults()
|
||||
{
|
||||
for (size_t i = 0; i < m_cellScalarResults.size(); i++)
|
||||
{
|
||||
m_cellScalarResults[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,12 +58,13 @@ public:
|
||||
QString makeResultNameUnique(const QString& resultNameProposal) const;
|
||||
|
||||
void removeResult(const QString& resultName);
|
||||
void clearAllResults();
|
||||
|
||||
void loadOrComputeSOIL();
|
||||
|
||||
// Access the results data
|
||||
std::vector< std::vector<double> > & cellScalarResults(size_t scalarResultIndex);
|
||||
const std::vector< std::vector<double> >& cellScalarResults(size_t scalarResultIndex) const;
|
||||
double cellScalarResult(size_t timeStepIndex, size_t scalarResultIndex, size_t resultValueIndex);
|
||||
|
||||
private:
|
||||
std::vector< std::vector< std::vector<double> > > m_cellScalarResults; ///< Scalar results for each timestep for each Result index (ResultVariable)
|
||||
|
||||
@@ -243,14 +243,6 @@ void RIMainWindow::createActions()
|
||||
connect(m_zoomAll, SIGNAL(triggered()), SLOT(slotZoomAll()));
|
||||
|
||||
// Debug actions
|
||||
m_debugUseShaders = new QAction("Use shaders", this);
|
||||
m_debugUseShaders->setCheckable(true);
|
||||
connect(m_debugUseShaders, SIGNAL(triggered(bool)), SLOT(slotUseShaders(bool)));
|
||||
|
||||
m_performanceHud = new QAction("Show Performance Info", this);
|
||||
m_performanceHud->setCheckable(true);
|
||||
connect(m_performanceHud, SIGNAL(triggered(bool)), SLOT(slotShowPerformanceInfo(bool)));
|
||||
|
||||
m_newPropertyView = new QAction("New Property View", this);
|
||||
connect(m_newPropertyView, SIGNAL(triggered()), SLOT(slotNewObjectPropertyView()));
|
||||
|
||||
@@ -309,8 +301,6 @@ void RIMainWindow::createMenus()
|
||||
debugMenu->addAction(m_mockLargeResultsModelAction);
|
||||
debugMenu->addAction(m_mockInputModelAction);
|
||||
debugMenu->addSeparator();
|
||||
debugMenu->addAction(m_debugUseShaders);
|
||||
debugMenu->addAction(m_performanceHud);
|
||||
debugMenu->addAction(m_newPropertyView);
|
||||
|
||||
connect(debugMenu, SIGNAL(aboutToShow()), SLOT(slotRefreshDebugActions()));
|
||||
@@ -1036,8 +1026,6 @@ void RIMainWindow::slotShowPerformanceInfo(bool enable)
|
||||
void RIMainWindow::slotRefreshDebugActions()
|
||||
{
|
||||
RIApplication* app = RIApplication::instance();
|
||||
m_debugUseShaders->setChecked(app->useShaders());
|
||||
m_performanceHud->setChecked(app->showPerformanceInfo());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -128,8 +128,6 @@ private:
|
||||
QAction* m_zoomAll;
|
||||
|
||||
// Debug actions
|
||||
QAction* m_debugUseShaders;
|
||||
QAction* m_performanceHud;
|
||||
QAction* m_newPropertyView;
|
||||
|
||||
// Help actions
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "RIProcessMonitor.h"
|
||||
#include "cafUiProcess.h"
|
||||
#include "RIApplication.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -38,6 +39,15 @@ RIProcessMonitor::RIProcessMonitor(QDockWidget* pParent)
|
||||
pTopLayout->addWidget(pLabel);
|
||||
pTopLayout->addWidget(m_labelStatus);
|
||||
|
||||
pTopLayout->addStretch();
|
||||
QPushButton* clearPushButton = new QPushButton("Clear", this);
|
||||
pTopLayout->addWidget(clearPushButton);
|
||||
connect(clearPushButton, SIGNAL(clicked()), this, SLOT(slotClearTextEdit()) );
|
||||
|
||||
m_terminatePushButton = new QPushButton("Stop", this);
|
||||
pTopLayout->addWidget(m_terminatePushButton);
|
||||
connect(m_terminatePushButton, SIGNAL(clicked()), this, SLOT(slotTerminateProcess()) );
|
||||
m_terminatePushButton->setEnabled(false);
|
||||
|
||||
m_textEdit = new QPlainTextEdit(this);
|
||||
m_textEdit->setReadOnly(true);
|
||||
@@ -72,7 +82,6 @@ RIProcessMonitor::~RIProcessMonitor()
|
||||
void RIProcessMonitor::startMonitorWorkProcess(caf::UiProcess* pProcess)
|
||||
{
|
||||
setStatusMsg("N/A", caf::PROCESS_STATE_NORMAL);
|
||||
m_textEdit->clear();
|
||||
|
||||
if (m_monitoredProcess == pProcess) return;
|
||||
|
||||
@@ -82,6 +91,11 @@ void RIProcessMonitor::startMonitorWorkProcess(caf::UiProcess* pProcess)
|
||||
connect(m_monitoredProcess, SIGNAL(signalStatusMsg(const QString&, int)), SLOT(slotShowProcStatusMsg(const QString&, int)));
|
||||
connect(m_monitoredProcess, SIGNAL(readyReadStandardError()), SLOT(slotProcReadyReadStdErr()));
|
||||
connect(m_monitoredProcess, SIGNAL(readyReadStandardOutput()), SLOT(slotProcReadyReadStdOut()));
|
||||
|
||||
m_terminatePushButton->setEnabled(true);
|
||||
|
||||
QString timeStamp = QTime::currentTime().toString("hh:mm:ss");
|
||||
addStringToLog(timeStamp + " Process starting\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +106,12 @@ void RIProcessMonitor::stopMonitorWorkProcess()
|
||||
{
|
||||
m_monitoredProcess = NULL;
|
||||
|
||||
m_terminatePushButton->setEnabled(false);
|
||||
|
||||
setStatusMsg("N/A", caf::PROCESS_STATE_NORMAL);
|
||||
|
||||
QString timeStamp = QTime::currentTime().toString("hh:mm:ss");
|
||||
addStringToLog(timeStamp + " Process finished\n\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -166,3 +185,22 @@ void RIProcessMonitor::slotProcReadyReadStdErr()
|
||||
addStringToLog(dataArray.data());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIProcessMonitor::slotTerminateProcess()
|
||||
{
|
||||
addStringToLog("Process terminated by user\n");
|
||||
|
||||
RIApplication* app = RIApplication::instance();
|
||||
app->terminateProcess();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIProcessMonitor::slotClearTextEdit()
|
||||
{
|
||||
m_textEdit->clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
class QDockWidget;
|
||||
class QLabel;
|
||||
class QPlainTextEdit;
|
||||
class QPushButton;
|
||||
|
||||
namespace caf
|
||||
{
|
||||
@@ -40,6 +41,7 @@ class RIProcessMonitor : public QWidget
|
||||
private:
|
||||
QLabel* m_labelStatus; // Shows current status string
|
||||
QPlainTextEdit* m_textEdit; // Showing the textual output from the process
|
||||
QPushButton* m_terminatePushButton;
|
||||
|
||||
caf::UiProcess* m_monitoredProcess; // Pointer to the process we're monitoring. Needed to fetch text
|
||||
|
||||
@@ -58,5 +60,7 @@ private slots:
|
||||
void slotShowProcStatusMsg(const QString& message, int messageType);
|
||||
void slotProcReadyReadStdOut();
|
||||
void slotProcReadyReadStdErr();
|
||||
void slotTerminateProcess();
|
||||
void slotClearTextEdit();
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "cafUtils.h"
|
||||
#include "cafFrameAnimationControl.h"
|
||||
#include "cafNavigationPolicy.h"
|
||||
#include "cafEffectGenerator.h"
|
||||
|
||||
using cvf::ManipulatorTrackball;
|
||||
|
||||
@@ -255,6 +256,8 @@ void RIViewer::slotEndAnimation()
|
||||
if (m_reservoirView) m_reservoirView->endAnimation();
|
||||
|
||||
caf::Viewer::slotEndAnimation();
|
||||
|
||||
caf::EffectGenerator::releaseUnreferencedEffects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user