2017-08-11 04:20:40 -05:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
# include "RicPasteAsciiDataToSummaryPlotFeature.h"
# include "OperationsUsingObjReferences/RicPasteFeatureImpl.h"
# include "RicNewSummaryPlotFeature.h"
2017-08-11 06:56:27 -05:00
# include "RicPasteAsciiDataToSummaryPlotFeatureUi.h"
2017-08-11 04:20:40 -05:00
# include "RiaLogging.h"
# include "RimSummaryPlot.h"
# include "RimSummaryPlotCollection.h"
# include "RimAsciiDataCurve.h"
# include "RimSummaryCurveAppearanceCalculator.h"
# include "cafPdmDefaultObjectFactory.h"
# include "cafPdmDocument.h"
# include "cafPdmObjectGroup.h"
# include "cafSelectionManager.h"
2017-08-11 06:56:27 -05:00
# include "cafPdmUiPropertyViewDialog.h"
# include "cafPdmSettings.h"
2017-08-11 04:20:40 -05:00
# include "cvfAssert.h"
# include "cvfColor3.h"
# include <QApplication>
# include <QAction>
# include <QClipboard>
# include <QMimeData>
2017-08-21 04:18:21 -05:00
CAF_CMD_SOURCE_INIT ( RicPasteAsciiDataToSummaryPlotFeature , " RicPasteAsciiDataToSummaryPlotFeature " ) ;
2017-08-11 04:20:40 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicPasteAsciiDataToSummaryPlotFeature : : isCommandEnabled ( )
{
caf : : PdmObjectHandle * destinationObject = dynamic_cast < caf : : PdmObjectHandle * > ( caf : : SelectionManager : : instance ( ) - > selectedItem ( ) ) ;
RimSummaryPlot * summaryPlot = nullptr ;
destinationObject - > firstAncestorOrThisOfType ( summaryPlot ) ;
if ( ! summaryPlot )
{
RimSummaryPlotCollection * summaryPlotCollection = nullptr ;
destinationObject - > firstAncestorOrThisOfType ( summaryPlotCollection ) ;
if ( ! summaryPlotCollection )
{
return false ;
}
}
return hasPastedText ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicPasteAsciiDataToSummaryPlotFeature : : onActionTriggered ( bool isChecked )
{
2017-08-18 02:42:04 -05:00
caf : : PdmObjectHandle * destinationObject = dynamic_cast < caf : : PdmObjectHandle * > ( caf : : SelectionManager : : instance ( ) - > selectedItem ( ) ) ;
2017-08-11 04:20:40 -05:00
RimSummaryPlot * summaryPlot = nullptr ;
destinationObject - > firstAncestorOrThisOfType ( summaryPlot ) ;
2017-08-18 02:42:04 -05:00
RicPasteAsciiDataToSummaryPlotFeatureUi pasteOptions ;
if ( ! summaryPlot ) pasteOptions . createNewPlot ( ) ;
caf : : PdmSettings : : readFieldsFromApplicationStore ( & pasteOptions ) ;
caf : : PdmUiPropertyViewDialog propertyDialog ( NULL , & pasteOptions , " Set Paste Options " , " " ) ;
if ( propertyDialog . exec ( ) ! = QDialog : : Accepted ) return ;
2017-08-11 04:20:40 -05:00
if ( ! summaryPlot )
{
RimSummaryPlotCollection * summaryPlotCollection = nullptr ;
destinationObject - > firstAncestorOrThisOfType ( summaryPlotCollection ) ;
if ( ! summaryPlotCollection )
{
return ;
}
summaryPlot = RicNewSummaryPlotFeature : : createNewSummaryPlot ( summaryPlotCollection , nullptr ) ;
if ( ! summaryPlot )
{
return ;
}
2017-08-18 02:42:04 -05:00
summaryPlot - > setDescription ( pasteOptions . plotTitle ( ) ) ;
2017-08-11 04:20:40 -05:00
}
2017-08-11 06:56:27 -05:00
caf : : PdmSettings : : writeFieldsToApplicationStore ( & pasteOptions ) ;
2017-08-11 04:20:40 -05:00
QString text = getPastedData ( ) ;
2017-08-11 06:56:27 -05:00
std : : vector < RimAsciiDataCurve * > curves = parseCurves ( text , pasteOptions ) ;
2017-08-11 04:20:40 -05:00
for ( RimAsciiDataCurve * curve : curves )
{
summaryPlot - > addAsciiDataCruve ( curve ) ;
}
summaryPlot - > updateConnectedEditors ( ) ;
summaryPlot - > loadDataAndUpdate ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicPasteAsciiDataToSummaryPlotFeature : : setupActionLook ( QAction * actionToSetup )
{
actionToSetup - > setText ( " Paste Excel Data to Summary Curve " ) ;
RicPasteFeatureImpl : : setIconAndShortcuts ( actionToSetup ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicPasteAsciiDataToSummaryPlotFeature : : getPastedData ( )
{
if ( hasPastedText ( ) )
{
QClipboard * clipboard = QApplication : : clipboard ( ) ;
return clipboard - > text ( ) ;
}
return QString ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicPasteAsciiDataToSummaryPlotFeature : : hasPastedText ( )
{
QClipboard * clipboard = QApplication : : clipboard ( ) ;
const QMimeData * mimeData = clipboard - > mimeData ( ) ;
return mimeData - > hasText ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-08-11 06:56:27 -05:00
std : : vector < RimAsciiDataCurve * > RicPasteAsciiDataToSummaryPlotFeature : : parseCurves ( QString & data , const RicPasteAsciiDataToSummaryPlotFeatureUi & settings )
2017-08-11 04:20:40 -05:00
{
std : : vector < RimAsciiDataCurve * > curves ;
std : : vector < QString > headers ;
QTextStream tableData ( & data ) ;
{
QString header ;
do {
header = tableData . readLine ( ) ;
} while ( header . isEmpty ( ) & & ! tableData . atEnd ( ) ) ;
// No header row found
if ( header . isEmpty ( ) ) return curves ;
QStringList columnHeaders = header . split ( ' \t ' ) ;
for ( size_t i = 1 ; i < columnHeaders . size ( ) ; + + i )
{
headers . push_back ( columnHeaders [ static_cast < int > ( i ) ] ) ;
}
// No columns found
if ( headers . empty ( ) ) return curves ;
}
size_t numColumns = headers . size ( ) ;
std : : vector < QDateTime > timeSteps ;
std : : vector < std : : vector < double > > values ;
values . resize ( numColumns ) ;
size_t row = 0 ;
while ( ! tableData . atEnd ( ) )
{
+ + row ;
QString line = tableData . readLine ( ) ;
// Skip empty lines
if ( line . isEmpty ( ) ) continue ;
2017-08-11 06:56:27 -05:00
QStringList columns = line . split ( settings . cellSeparator ( ) ) ;
2017-08-11 04:20:40 -05:00
if ( columns . size ( ) ! = numColumns + 1 )
{
RiaLogging : : warning ( QString ( " Invalid number of columns in row %1 " ) . arg ( row ) ) ;
continue ;
}
2017-08-11 06:56:27 -05:00
QDateTime date = QDateTime : : fromString ( columns [ 0 ] , settings . dateFormat ( ) ) ;
2017-08-11 04:20:40 -05:00
if ( ! date . isValid ( ) )
{
RiaLogging : : warning ( QString ( " First column of row %1 could not be parsed as a date: %2 " ) . arg ( row ) . arg ( columns [ 0 ] ) ) ;
continue ;
}
timeSteps . push_back ( date ) ;
for ( size_t col = 1 ; col < columns . size ( ) ; + + col )
{
bool ok ;
2017-08-11 06:56:27 -05:00
values [ col - 1 ] . push_back ( settings . decimalLocale ( ) . toDouble ( columns [ static_cast < int > ( col ) ] , & ok ) ) ;
2017-08-11 04:20:40 -05:00
if ( ! ok )
{
RiaLogging : : warning ( QString ( " Could not parse value at row %1 column %2 as double: %3. Defaulting to 0.0 " ) . arg ( row ) . arg ( col ) . arg ( columns [ static_cast < int > ( col ) ] ) ) ;
}
}
}
std : : map < CurveType , std : : vector < RimAsciiDataCurve * > > curveToTypeMap ;
2017-08-18 02:59:00 -05:00
QString curvePrefix = settings . curvePrefix ( ) ;
2017-08-11 04:20:40 -05:00
for ( size_t i = 0 ; i < values . size ( ) ; + + i )
{
RimAsciiDataCurve * curve = new RimAsciiDataCurve ( ) ;
curve - > setTimeSteps ( timeSteps ) ;
curve - > setValues ( values [ i ] ) ;
2017-08-18 02:59:00 -05:00
if ( curvePrefix . isEmpty ( ) )
{
curve - > setTitle ( headers [ i ] ) ;
}
else
{
curve - > setTitle ( QString ( " %1: %2 " ) . arg ( curvePrefix ) . arg ( headers [ i ] ) ) ;
}
2017-08-21 03:11:15 -05:00
// Appearance
curve - > setSymbol ( settings . pointSymbol ( ) ) ;
curve - > setLineStyle ( settings . lineStyle ( ) ) ;
curve - > setSymbolSkipDinstance ( settings . symbolSkipDinstance ( ) ) ;
2017-08-11 04:20:40 -05:00
curveToTypeMap [ guessCurveType ( headers [ i ] ) ] . push_back ( curve ) ;
curves . push_back ( curve ) ;
}
for ( auto & it : curveToTypeMap )
{
for ( int i = 0 ; i < it . second . size ( ) ; + + i )
{
cvf : : Color3f color ;
switch ( it . first )
{
case CURVE_GAS :
2017-08-11 06:56:27 -05:00
color = RimSummaryCurveAppearanceCalculator : : cycledGreenColor ( i ) ;
2017-08-11 04:20:40 -05:00
break ;
case CURVE_OIL :
2017-08-11 06:56:27 -05:00
color = RimSummaryCurveAppearanceCalculator : : cycledRedColor ( i ) ;
2017-08-11 04:20:40 -05:00
break ;
case CURVE_WAT :
color = RimSummaryCurveAppearanceCalculator : : cycledBlueColor ( i ) ;
break ;
default :
color = RimSummaryCurveAppearanceCalculator : : cycledNoneRGBBrColor ( i ) ;
break ;
}
it . second [ i ] - > setColor ( color ) ;
}
}
return curves ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicPasteAsciiDataToSummaryPlotFeature : : CurveType RicPasteAsciiDataToSummaryPlotFeature : : guessCurveType ( const QString & curveName )
{
if ( curveName . contains ( " SW " ) | | curveName . contains ( " water " , Qt : : CaseInsensitive ) )
{
return CURVE_WAT ;
}
else if ( curveName . contains ( " oil " , Qt : : CaseInsensitive ) )
{
return CURVE_OIL ;
}
else if ( curveName . contains ( " gas " , Qt : : CaseInsensitive ) )
{
return CURVE_GAS ;
}
return CURVE_UNKNOWN ;
}