Add support for well paths from OSDU.

This commit is contained in:
Kristian Bendiksen
2024-02-28 08:10:52 +01:00
parent d02dd2dfed
commit 577ef1e154
33 changed files with 2003 additions and 1268 deletions

View File

@@ -9,6 +9,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSummary.h ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSummary.h
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesGeoMech.h ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesGeoMech.h
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSystem.h ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSystem.h
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesOsdu.h
${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.h ${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.h
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.h ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.h
${CMAKE_CURRENT_LIST_DIR}/RiaCurveSetDefinition.h ${CMAKE_CURRENT_LIST_DIR}/RiaCurveSetDefinition.h
@@ -35,6 +36,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaLasDefines.h ${CMAKE_CURRENT_LIST_DIR}/RiaLasDefines.h
${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.h ${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.h
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAddress.h ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAddress.h
${CMAKE_CURRENT_LIST_DIR}/RiaFileDownloader.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@@ -48,6 +50,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSummary.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSummary.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesGeoMech.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesGeoMech.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSystem.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesSystem.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaPreferencesOsdu.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaPorosityModel.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveDefinition.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCurveSetDefinition.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaCurveSetDefinition.cpp
@@ -74,6 +77,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaLasDefines.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaLasDefines.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAddress.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAddress.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaFileDownloader.cpp
) )
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -87,6 +91,7 @@ set(QT_MOC_HEADERS
${CMAKE_CURRENT_LIST_DIR}/RiaCompletionTypeCalculationScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaCompletionTypeCalculationScheduler.h
${CMAKE_CURRENT_LIST_DIR}/RiaPlotWindowRedrawScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaPlotWindowRedrawScheduler.h
${CMAKE_CURRENT_LIST_DIR}/RiaScheduler.h ${CMAKE_CURRENT_LIST_DIR}/RiaScheduler.h
${CMAKE_CURRENT_LIST_DIR}/RiaFileDownloader.h
) )
source_group( source_group(

View File

@@ -0,0 +1,54 @@
#include "RiaFileDownloader.h"
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include "RiaLogging.h"
RiaFileDownloader::RiaFileDownloader( QObject* parent )
: QObject( parent )
{
}
void RiaFileDownloader::downloadFile( const QUrl& url, const QString& filePath )
{
QNetworkAccessManager* manager = new QNetworkAccessManager( this );
QNetworkRequest request( url );
RiaLogging::debug( "Downloading from: " + url.toString() );
QNetworkReply* reply = manager->get( request );
connect( reply,
&QNetworkReply::finished,
[=]()
{
if ( reply->error() )
{
RiaLogging::error( "Download failed:" + reply->errorString() );
emit done();
}
else
{
QFile file( filePath );
if ( file.open( QIODevice::WriteOnly ) )
{
file.write( reply->readAll() );
file.close();
RiaLogging::info( "Download succeeded. File saved to " + filePath );
emit done();
}
else
{
RiaLogging::info( "Failed to save file to " + filePath );
emit done();
}
}
reply->deleteLater();
manager->deleteLater();
} );
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <QObject>
#include <QString>
#include <QUrl>
class RiaFileDownloader : public QObject
{
Q_OBJECT
public:
explicit RiaFileDownloader( QObject* parent = nullptr );
void downloadFile( const QUrl& url, const QString& filePath );
signals:
void done();
};

View File

@@ -279,6 +279,9 @@ RiaPreferences::RiaPreferences()
CAF_PDM_InitFieldNoDefault( &m_systemPreferences, "systemPreferences", "systemPreferences" ); CAF_PDM_InitFieldNoDefault( &m_systemPreferences, "systemPreferences", "systemPreferences" );
m_systemPreferences = new RiaPreferencesSystem; m_systemPreferences = new RiaPreferencesSystem;
CAF_PDM_InitFieldNoDefault( &m_osduPreferences, "osduPreferences", "osduPreferences" );
m_osduPreferences = new RiaPreferencesOsdu;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -487,6 +490,10 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
m_loggerTrapSignalAndFlush.uiCapability()->setUiReadOnly( !m_loggerFilename().first ); m_loggerTrapSignalAndFlush.uiCapability()->setUiReadOnly( !m_loggerFilename().first );
m_loggerFlushInterval.uiCapability()->setUiReadOnly( !m_loggerFilename().first ); m_loggerFlushInterval.uiCapability()->setUiReadOnly( !m_loggerFilename().first );
} }
else if ( uiConfigName == RiaPreferences::tabNameOsdu() )
{
m_osduPreferences()->uiOrdering( uiConfigName, uiOrdering );
}
else if ( RiaApplication::enableDevelopmentFeatures() && uiConfigName == RiaPreferences::tabNameSystem() ) else if ( RiaApplication::enableDevelopmentFeatures() && uiConfigName == RiaPreferences::tabNameSystem() )
{ {
m_systemPreferences()->uiOrdering( uiConfigName, uiOrdering ); m_systemPreferences()->uiOrdering( uiConfigName, uiOrdering );
@@ -614,6 +621,14 @@ QString RiaPreferences::tabNameSystem()
return "System"; return "System";
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferences::tabNameOsdu()
{
return "Osdu";
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -654,6 +669,7 @@ QStringList RiaPreferences::tabNames()
names << tabNameGeomech(); names << tabNameGeomech();
#endif #endif
names << tabNameImportExport(); names << tabNameImportExport();
names << tabNameOsdu();
if ( RiaApplication::enableDevelopmentFeatures() ) if ( RiaApplication::enableDevelopmentFeatures() )
{ {
@@ -1018,6 +1034,14 @@ RiaPreferencesGeoMech* RiaPreferences::geoMechPreferences() const
return m_geoMechPreferences(); return m_geoMechPreferences();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaPreferencesOsdu* RiaPreferences::osduPreferences() const
{
return m_osduPreferences();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -24,6 +24,7 @@
#include "RiaDateTimeDefines.h" #include "RiaDateTimeDefines.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaFontCache.h" #include "RiaFontCache.h"
#include "RiaPreferencesOsdu.h"
#include "cafAppEnum.h" #include "cafAppEnum.h"
#include "cafPdmChildField.h" #include "cafPdmChildField.h"
@@ -43,6 +44,7 @@ class RifReaderSettings;
class RiaPreferencesSummary; class RiaPreferencesSummary;
class RiaPreferencesGeoMech; class RiaPreferencesGeoMech;
class RiaPreferencesSystem; class RiaPreferencesSystem;
class RiaPreferencesOsdu;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
@@ -125,6 +127,7 @@ public:
RiaPreferencesGeoMech* geoMechPreferences() const; RiaPreferencesGeoMech* geoMechPreferences() const;
RiaPreferencesSummary* summaryPreferences() const; RiaPreferencesSummary* summaryPreferences() const;
RiaPreferencesSystem* systemPreferences() const; RiaPreferencesSystem* systemPreferences() const;
RiaPreferencesOsdu* osduPreferences() const;
public: public:
caf::PdmField<bool> enableGrpcServer; caf::PdmField<bool> enableGrpcServer;
@@ -170,6 +173,7 @@ private:
static QString tabNamePlotting(); static QString tabNamePlotting();
static QString tabNameScripting(); static QString tabNameScripting();
static QString tabNameSystem(); static QString tabNameSystem();
static QString tabNameOsdu();
static QString tabNameImportExport(); static QString tabNameImportExport();
static double defaultMarginSize( QPageSize::PageSizeId pageSizeId ); static double defaultMarginSize( QPageSize::PageSizeId pageSizeId );
@@ -230,6 +234,9 @@ private:
// System settings // System settings
caf::PdmChildField<RiaPreferencesSystem*> m_systemPreferences; caf::PdmChildField<RiaPreferencesSystem*> m_systemPreferences;
// Osdu settings
caf::PdmChildField<RiaPreferencesOsdu*> m_osduPreferences;
// 3d view // 3d view
caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType; caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType;
caf::PdmField<caf::AppEnum<RiaDefines::RINavigationPolicy>> m_navigationPolicy; caf::PdmField<caf::AppEnum<RiaDefines::RINavigationPolicy>> m_navigationPolicy;

View File

@@ -0,0 +1,84 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 Equinor 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 "RiaApplication.h"
#include "RiaPreferences.h"
#include "RiaPreferencesOsdu.h"
CAF_PDM_SOURCE_INIT( RiaPreferencesOsdu, "RiaPreferencesOsdu" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaPreferencesOsdu::RiaPreferencesOsdu()
{
CAF_PDM_InitFieldNoDefault( &m_server, "server", "Server" );
CAF_PDM_InitFieldNoDefault( &m_dataPartitionId, "dataPartitionId", "Data Partition Id" );
CAF_PDM_InitFieldNoDefault( &m_authority, "authority", "Authority" );
CAF_PDM_InitFieldNoDefault( &m_scopes, "scopes", "Scopes" );
CAF_PDM_InitFieldNoDefault( &m_clientId, "clientId", "Client Id" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaPreferencesOsdu* RiaPreferencesOsdu::current()
{
return RiaApplication::instance()->preferences()->osduPreferences();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferencesOsdu::server() const
{
return m_server;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferencesOsdu::dataPartitionId() const
{
return m_dataPartitionId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferencesOsdu::authority() const
{
return m_authority;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferencesOsdu::scopes() const
{
return m_scopes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaPreferencesOsdu::clientId() const
{
return m_clientId;
}

View File

@@ -0,0 +1,48 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmField.h"
#include "cafPdmObject.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiaPreferencesOsdu : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RiaPreferencesOsdu();
static RiaPreferencesOsdu* current();
QString server() const;
QString dataPartitionId() const;
QString authority() const;
QString scopes() const;
QString clientId() const;
private:
caf::PdmField<QString> m_server;
caf::PdmField<QString> m_dataPartitionId;
caf::PdmField<QString> m_authority;
caf::PdmField<QString> m_scopes;
caf::PdmField<QString> m_clientId;
};

View File

@@ -32,6 +32,7 @@ if(Qt5Core_FOUND)
Gui Gui
OpenGL OpenGL
Network Network
NetworkAuth
Widgets Widgets
Xml Xml
Concurrent Concurrent
@@ -44,6 +45,7 @@ if(Qt5Core_FOUND)
Qt5::Core Qt5::Core
Qt5::Gui Qt5::Gui
Qt5::Network Qt5::Network
Qt5::NetworkAuth
Qt5::OpenGL Qt5::OpenGL
Qt5::Widgets Qt5::Widgets
Qt5::Xml Qt5::Xml

View File

@@ -5,6 +5,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.h ${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.h
${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.h ${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h
${CMAKE_CURRENT_LIST_DIR}/RiaOsduOAuthHttpServerReplyHandler.h
${CMAKE_CURRENT_LIST_DIR}/RiaOsduConnector.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@@ -14,14 +16,17 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathImport.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellsEntry.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaOsduOAuthHttpServerReplyHandler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaOsduConnector.cpp
) )
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
list(APPEND COMMAND_CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) list(APPEND COMMAND_CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
list(APPEND COMMAND_QT_MOC_HEADERS list(APPEND COMMAND_QT_MOC_HEADERS ${CMAKE_CURRENT_LIST_DIR}/RiaOsduConnector.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellImportWizard.h
${CMAKE_CURRENT_LIST_DIR}/RiaOsduOAuthHttpServerReplyHandler.h
) )
source_group( source_group(

View File

@@ -0,0 +1,652 @@
#include "RiaOsduConnector.h"
#include "RiaFileDownloader.h"
#include "RiaLogging.h"
#include "RiaOsduOAuthHttpServerReplyHandler.h"
#include <QAbstractOAuth>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QOAuth2AuthorizationCodeFlow>
#include <QOAuthHttpServerReplyHandler>
#include <QObject>
#include <QString>
#include <QTimer>
#include <QUrl>
#include <QUrlQuery>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaOsduConnector::RiaOsduConnector( QObject* parent,
const QString& server,
const QString& dataPartitionId,
const QString& authority,
const QString& scopes,
const QString& clientId )
: QObject( parent )
, m_server( server )
, m_dataPartitionId( dataPartitionId )
, m_authority( authority )
, m_scopes( scopes )
, m_clientId( clientId )
{
m_networkAccessManager = new QNetworkAccessManager( this );
m_osdu = new QOAuth2AuthorizationCodeFlow( this );
RiaLogging::debug( "SSL BUILD VERSION: " + QSslSocket::sslLibraryBuildVersionString() );
RiaLogging::debug( "SSL VERSION STRING: " + QSslSocket::sslLibraryVersionString() );
int port = 35327;
connect( m_osdu,
&QOAuth2AuthorizationCodeFlow::authorizeWithBrowser,
[]( QUrl url )
{
RiaLogging::info( "Authorize with url: " + url.toString() );
QUrlQuery query( url );
url.setQuery( query );
QDesktopServices::openUrl( url );
} );
QString authUrl = constructAuthUrl( m_authority );
m_osdu->setAuthorizationUrl( QUrl( authUrl ) );
QString tokenUrl = constructTokenUrl( m_authority );
m_osdu->setAccessTokenUrl( QUrl( tokenUrl ) );
// App key
m_osdu->setClientIdentifier( m_clientId );
m_osdu->setScope( m_scopes );
auto replyHandler = new RiaOsduOAuthHttpServerReplyHandler( port, this );
m_osdu->setReplyHandler( replyHandler );
connect( m_osdu, SIGNAL( granted() ), this, SLOT( accessGranted() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::accessGranted()
{
m_token = m_osdu->token();
emit tokenReady( m_token );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestToken()
{
RiaLogging::debug( "Requesting token." );
m_osdu->grant();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaOsduConnector::~RiaOsduConnector()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestFieldsByName( const QString& token, const QString& fieldName )
{
requestFieldsByName( m_server, m_dataPartitionId, token, fieldName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestFieldsByName( const QString& fieldName )
{
requestFieldsByName( m_token, fieldName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestFieldsByName( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fieldName )
{
std::map<QString, QString> params;
params["kind"] = FIELD_KIND;
params["limit"] = "10000";
params["query"] = "data.FieldName:" + fieldName;
auto reply = makeRequest( params, server, dataPartitionId, token );
connect( reply,
&QNetworkReply::finished,
[this, reply]()
{
if ( reply->error() == QNetworkReply::NoError )
{
parseFields( reply );
}
} );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellsByFieldId( const QString& fieldId )
{
requestWellsByFieldId( m_server, m_dataPartitionId, m_token, fieldId );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellsByFieldId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fieldId )
{
std::map<QString, QString> params;
params["kind"] = WELL_KIND;
params["limit"] = "10000";
params["query"] = QString( "nested(data.GeoContexts, (FieldID:\"%1\"))" ).arg( fieldId );
auto reply = makeRequest( params, server, dataPartitionId, token );
connect( reply,
&QNetworkReply::finished,
[this, reply, fieldId]()
{
if ( reply->error() == QNetworkReply::NoError )
{
parseWells( reply );
}
} );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellboresByWellId( const QString& wellId )
{
requestWellboresByWellId( m_server, m_dataPartitionId, m_token, wellId );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellboresByWellId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& wellId )
{
std::map<QString, QString> params;
params["kind"] = WELLBORE_KIND;
params["limit"] = "10000";
params["query"] = "data.WellID: \"" + wellId + "\"";
auto reply = makeRequest( params, server, dataPartitionId, token );
connect( reply,
&QNetworkReply::finished,
[this, reply, wellId]()
{
if ( reply->error() == QNetworkReply::NoError )
{
parseWellbores( reply, wellId );
}
} );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellboreTrajectoryByWellboreId( const QString& wellboreId )
{
requestWellboreTrajectoryByWellboreId( m_server, m_dataPartitionId, m_token, wellboreId );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestFileDownloadByFileId( const QString& fileId )
{
requestFileDownloadByFileId( m_server, m_dataPartitionId, m_token, fileId );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestWellboreTrajectoryByWellboreId( const QString& server,
const QString& dataPartitionId,
const QString& token,
const QString& wellboreId )
{
std::map<QString, QString> params;
params["kind"] = WELLBORE_TRAJECTORY_KIND;
params["limit"] = "10000";
params["query"] = "data.WellboreID: \"" + wellboreId + "\"";
auto reply = makeRequest( params, server, dataPartitionId, token );
connect( reply,
&QNetworkReply::finished,
[this, reply, wellboreId]()
{
if ( reply->error() == QNetworkReply::NoError )
{
parseWellTrajectory( reply, wellboreId );
}
} );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::requestFileDownloadByFileId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fileId )
{
RiaLogging::info( "Requesting download of file id: " + fileId );
auto reply = makeDownloadRequest( server, dataPartitionId, fileId, token );
connect( reply,
&QNetworkReply::finished,
[this, reply, fileId]()
{
if ( reply->error() == QNetworkReply::NoError )
{
saveFile( reply, fileId );
}
else
{
RiaLogging::error( "File request for id " + fileId + " failed." + reply->errorString() );
}
} );
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::constructSearchUrl( const QString& server )
{
return server + "/api/search/v2/query";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::constructDownloadUrl( const QString& server, const QString& fileId )
{
return server + "/api/file/v2/files/" + fileId + "/downloadURL";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::constructAuthUrl( const QString& authority )
{
return authority + "/oauth2/v2.0/authorize";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::constructTokenUrl( const QString& authority )
{
return authority + "/oauth2/v2.0/token";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QNetworkReply* RiaOsduConnector::makeRequest( const std::map<QString, QString>& parameters,
const QString& server,
const QString& dataPartitionId,
const QString& token )
{
QNetworkRequest m_networkRequest;
m_networkRequest.setUrl( QUrl( constructSearchUrl( server ) ) );
addStandardHeader( m_networkRequest, token, dataPartitionId );
QJsonObject obj;
for ( auto [key, value] : parameters )
{
obj.insert( key, value );
}
QJsonDocument doc( obj );
QString strJson( doc.toJson( QJsonDocument::Compact ) );
auto reply = m_networkAccessManager->post( m_networkRequest, strJson.toUtf8() );
return reply;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::parseFields( QNetworkReply* reply )
{
QByteArray result = reply->readAll();
reply->deleteLater();
if ( reply->error() == QNetworkReply::NoError )
{
QJsonDocument doc = QJsonDocument::fromJson( result );
QJsonObject jsonObj = doc.object();
QJsonArray resultsArray = jsonObj["results"].toArray();
m_fields.clear();
foreach ( const QJsonValue& value, resultsArray )
{
QJsonObject resultObj = value.toObject();
QString id = resultObj["id"].toString();
QString kind = resultObj["kind"].toString();
QString fieldName = resultObj["data"].toObject()["FieldName"].toString();
m_fields.push_back( OsduField{ id, kind, fieldName } );
}
emit fieldsFinished();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::parseWells( QNetworkReply* reply )
{
QByteArray result = reply->readAll();
reply->deleteLater();
if ( reply->error() == QNetworkReply::NoError )
{
QJsonDocument doc = QJsonDocument::fromJson( result );
QJsonObject jsonObj = doc.object();
QJsonArray resultsArray = jsonObj["results"].toArray();
RiaLogging::info( QString( "Found %1 wells." ).arg( +resultsArray.size() ) );
m_wells.clear();
foreach ( const QJsonValue& value, resultsArray )
{
QJsonObject resultObj = value.toObject();
QString id = resultObj["id"].toString();
QString kind = resultObj["kind"].toString();
QString name = resultObj["data"].toObject()["FacilityName"].toString();
m_wells.push_back( OsduWell{ id, kind, name } );
}
emit wellsFinished();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::parseWellbores( QNetworkReply* reply, const QString& wellId )
{
QByteArray result = reply->readAll();
reply->deleteLater();
if ( reply->error() == QNetworkReply::NoError )
{
QJsonDocument doc = QJsonDocument::fromJson( result );
QJsonObject jsonObj = doc.object();
QJsonArray resultsArray = jsonObj["results"].toArray();
RiaLogging::info( QString( "Found %1 wellbores." ).arg( resultsArray.size() ) );
m_wellbores[wellId].clear();
foreach ( const QJsonValue& value, resultsArray )
{
QJsonObject resultObj = value.toObject();
QString id = resultObj["id"].toString();
QString kind = resultObj["kind"].toString();
QString name = resultObj["data"].toObject()["FacilityName"].toString();
m_wellbores[wellId].push_back( OsduWellbore{ id, kind, name, wellId } );
}
emit wellboresFinished( wellId );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::parseWellTrajectory( QNetworkReply* reply, const QString& wellboreId )
{
QByteArray result = reply->readAll();
reply->deleteLater();
if ( reply->error() == QNetworkReply::NoError )
{
QJsonDocument doc = QJsonDocument::fromJson( result );
QJsonObject jsonObj = doc.object();
QJsonArray resultsArray = jsonObj["results"].toArray();
m_wellboreTrajectories.clear();
foreach ( const QJsonValue& value, resultsArray )
{
QJsonObject resultObj = value.toObject();
QJsonObject dataObj = resultObj["data"].toObject();
QJsonArray dataSets = dataObj["Datasets"].toArray();
if ( dataSets.size() == 1 )
{
QString id = resultObj["id"].toString();
QString kind = resultObj["kind"].toString();
QString dataSetId = dataSets[0].toString();
QString description = dataObj["Description"].toString();
m_wellboreTrajectories[wellboreId].push_back( OsduWellboreTrajectory{ id, kind, description, dataSetId, wellboreId } );
}
else if ( dataSets.size() > 1 )
{
RiaLogging::error( "Encountered dataset with more than on file: currently not supported." );
}
}
emit wellboreTrajectoryFinished( wellboreId );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::saveFile( QNetworkReply* reply, const QString& fileId )
{
QByteArray result = reply->readAll();
reply->deleteLater();
if ( reply->error() == QNetworkReply::NoError )
{
QEventLoop loop;
QJsonDocument doc = QJsonDocument::fromJson( result );
QJsonObject jsonObj = doc.object();
QString signedUrl = jsonObj["SignedUrl"].toString();
RiaFileDownloader* downloader = new RiaFileDownloader;
QUrl url( signedUrl );
QString filePath = "/tmp/" + generateRandomString( 30 ) + ".txt";
QString formattedJsonString = doc.toJson( QJsonDocument::Indented );
RiaLogging::info( QString( "File download: %1 => %2" ).arg( signedUrl ).arg( filePath ) );
connect( this, SIGNAL( fileDownloadFinished( const QString&, const QString& ) ), &loop, SLOT( quit() ) );
connect( downloader,
&RiaFileDownloader::done,
[this, fileId, filePath]()
{
RiaLogging::info( QString( "Download complete %1 => %2" ).arg( fileId ).arg( filePath ) );
emit( fileDownloadFinished( fileId, filePath ) );
} );
RiaLogging::info( "Starting download" );
downloader->downloadFile( url, filePath );
downloader->deleteLater();
loop.exec();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::addStandardHeader( QNetworkRequest& networkRequest, const QString& token, const QString& dataPartitionId )
{
networkRequest.setHeader( QNetworkRequest::ContentTypeHeader, "application/json" );
networkRequest.setRawHeader( "Authorization", "Bearer " + token.toUtf8() );
networkRequest.setRawHeader( QByteArray( "Data-Partition-Id" ), dataPartitionId.toUtf8() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QNetworkReply*
RiaOsduConnector::makeDownloadRequest( const QString& server, const QString& dataPartitionId, const QString& id, const QString& token )
{
QNetworkRequest m_networkRequest;
QString url = constructDownloadUrl( server, id );
m_networkRequest.setUrl( QUrl( url ) );
addStandardHeader( m_networkRequest, token, dataPartitionId );
auto reply = m_networkAccessManager->get( m_networkRequest );
return reply;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::generateRandomString( int randomStringLength )
{
const QString possibleCharacters( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" );
QString randomString;
for ( int i = 0; i < randomStringLength; ++i )
{
quint32 value = QRandomGenerator::global()->generate();
int index = value % possibleCharacters.length();
QChar nextChar = possibleCharacters.at( index );
randomString.append( nextChar );
}
return randomString;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::server() const
{
return m_server;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::dataPartition() const
{
return m_dataPartitionId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<OsduField> RiaOsduConnector::fields() const
{
return m_fields;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<OsduWell> RiaOsduConnector::wells() const
{
return m_wells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<OsduWellbore> RiaOsduConnector::wellbores( const QString& wellId ) const
{
auto it = m_wellbores.find( wellId );
if ( it != m_wellbores.end() )
return it->second;
else
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduConnector::wellIdForWellboreId( const QString& wellboreId ) const
{
auto findWellIdForWellboreId = []( const std::vector<OsduWellbore>& wellbores, const QString& wellboreId )
{
auto it = std::find_if( wellbores.begin(), wellbores.end(), [wellboreId]( const OsduWellbore& w ) { return w.id == wellboreId; } );
if ( it != wellbores.end() )
return it->wellId;
else
return QString();
};
for ( auto [wellId, wellbores] : m_wellbores )
{
if ( auto res = findWellIdForWellboreId( wellbores, wellboreId ); !res.isEmpty() )
{
return wellId;
}
}
return QString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<OsduWellboreTrajectory> RiaOsduConnector::wellboreTrajectories( const QString& wellboreId ) const
{
auto it = m_wellboreTrajectories.find( wellboreId );
if ( it != m_wellboreTrajectories.end() )
return it->second;
else
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::fileDownloadComplete( const QString& fileId, const QString& filePath )
{
m_filePath = filePath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<QString, QString> RiaOsduConnector::requestFileContentsById( const QString& fileId )
{
if ( m_token.isEmpty() )
{
// TODO: improve this..
QEventLoop loop;
connect( this, SIGNAL( tokenReady( const QString& ) ), &loop, SLOT( quit() ) );
requestToken();
loop.exec();
}
QEventLoop loop2;
connect( this,
SIGNAL( fileDownloadFinished( const QString&, const QString& ) ),
this,
SLOT( fileDownloadComplete( const QString&, const QString& ) ) );
connect( this, SIGNAL( fileDownloadFinished( const QString&, const QString& ) ), &loop2, SLOT( quit() ) );
requestFileDownloadByFileId( m_server, m_dataPartitionId, m_token, fileId );
loop2.exec();
QFile dataFile( m_filePath );
if ( !dataFile.open( QFile::ReadOnly ) )
{
return { "", "Unable to open file: " + m_filePath };
}
QTextStream stream( &dataFile );
auto fileContent = stream.readAll();
return { fileContent, "" };
}

View File

@@ -0,0 +1,136 @@
#pragma once
#include <QtCore>
#include <QNetworkAccessManager>
#include <QOAuth2AuthorizationCodeFlow>
#include <map>
struct OsduField
{
QString id;
QString kind;
QString name;
};
struct OsduWell
{
QString id;
QString kind;
QString name;
};
struct OsduWellbore
{
QString id;
QString kind;
QString name;
QString wellId;
};
struct OsduWellboreTrajectory
{
QString id;
QString kind;
QString description;
QString dataSetId;
QString wellboreId;
};
//==================================================================================================
///
//==================================================================================================
class RiaOsduConnector : public QObject
{
Q_OBJECT
public:
RiaOsduConnector( QObject* parent,
const QString& server,
const QString& dataParitionId,
const QString& authority,
const QString& scopes,
const QString& clientId );
~RiaOsduConnector() override;
void requestFieldsByName( const QString& token, const QString& fieldName );
void requestFieldsByName( const QString& fieldName );
void requestWellsByFieldId( const QString& fieldId );
void requestWellboresByWellId( const QString& wellId );
void requestWellboreTrajectoryByWellboreId( const QString& wellboreId );
void requestFileDownloadByFileId( const QString& fileId );
std::pair<QString, QString> requestFileContentsById( const QString& fileId );
QString wellIdForWellboreId( const QString& wellboreId ) const;
QString server() const;
QString dataPartition() const;
std::vector<OsduField> fields() const;
std::vector<OsduWell> wells() const;
std::vector<OsduWellbore> wellbores( const QString& wellId ) const;
std::vector<OsduWellboreTrajectory> wellboreTrajectories( const QString& wellboreId ) const;
public slots:
void requestToken();
void parseFields( QNetworkReply* reply );
void parseWells( QNetworkReply* reply );
void parseWellbores( QNetworkReply* reply, const QString& wellId );
void parseWellTrajectory( QNetworkReply* reply, const QString& wellboreId );
void saveFile( QNetworkReply* reply, const QString& fileId );
void accessGranted();
void fileDownloadComplete( const QString& fileId, const QString& filePath );
signals:
void fileDownloadFinished( const QString& fileId, const QString& filePath );
void fieldsFinished();
void wellsFinished();
void wellboresFinished( const QString& wellId );
void wellboreTrajectoryFinished( const QString& wellboreId );
void tokenReady( const QString& token );
private:
void addStandardHeader( QNetworkRequest& networkRequest, const QString& token, const QString& dataPartitionId );
QNetworkReply*
makeRequest( const std::map<QString, QString>& parameters, const QString& server, const QString& dataPartitionId, const QString& token );
QNetworkReply* makeDownloadRequest( const QString& server, const QString& dataPartitionId, const QString& id, const QString& token );
void requestFieldsByName( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fieldName );
void requestWellsByFieldId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fieldId );
void requestWellboresByWellId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& wellId );
void requestWellboreTrajectoryByWellboreId( const QString& server,
const QString& dataPartitionId,
const QString& token,
const QString& wellboreId );
void requestFileDownloadByFileId( const QString& server, const QString& dataPartitionId, const QString& token, const QString& fileId );
static QString generateRandomString( int length = 20 );
static QString constructSearchUrl( const QString& server );
static QString constructDownloadUrl( const QString& server, const QString& fileId );
static QString constructAuthUrl( const QString& authority );
static QString constructTokenUrl( const QString& authority );
QOAuth2AuthorizationCodeFlow* m_osdu;
QNetworkAccessManager* m_networkAccessManager;
const QString m_server;
const QString m_dataPartitionId;
const QString m_authority;
const QString m_scopes;
const QString m_clientId;
QString m_token;
std::vector<OsduField> m_fields;
std::vector<OsduWell> m_wells;
std::map<QString, std::vector<OsduWellbore>> m_wellbores;
std::map<QString, std::vector<OsduWellboreTrajectory>> m_wellboreTrajectories;
QString m_filePath;
static inline const QString FIELD_KIND = "osdu:wks:master-data--Field:1.0.0";
static inline const QString WELL_KIND = "osdu:wks:master-data--Well:1.2.0";
static inline const QString WELLBORE_KIND = "osdu:wks:master-data--Wellbore:1.1.0";
static inline const QString WELLBORE_TRAJECTORY_KIND = "osdu:wks:work-product-component--WellboreTrajectory:1.1.0";
};

View File

@@ -0,0 +1,24 @@
#include "RiaOsduOAuthHttpServerReplyHandler.h"
#include <QAbstractOAuth>
#include <QOAuthHttpServerReplyHandler>
#include <QString>
#include <QUrl>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaOsduOAuthHttpServerReplyHandler::RiaOsduOAuthHttpServerReplyHandler( quint16 port, QObject* parent )
: QOAuthHttpServerReplyHandler( port, parent )
, m_port( port )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiaOsduOAuthHttpServerReplyHandler::callback() const
{
const QUrl url( QString::fromLatin1( "http://localhost:%1/" ).arg( m_port ) );
return url.toString( QUrl::EncodeDelimiters );
}

View File

@@ -0,0 +1,38 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QOAuthHttpServerReplyHandler>
#include <QObject>
#include <QString>
//==================================================================================================
///
//==================================================================================================
class RiaOsduOAuthHttpServerReplyHandler : public QOAuthHttpServerReplyHandler
{
Q_OBJECT
public:
RiaOsduOAuthHttpServerReplyHandler( quint16 port, QObject* parent );
QString callback() const override;
private:
quint16 m_port;
};

View File

@@ -1,7 +1,6 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2015- Statoil ASA // Copyright (C) 2024- Equinor ASA
// Copyright (C) 2015- Ceetron Solutions AS
// //
// ResInsight is free software: you can redistribute it and/or modify // ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@@ -21,63 +20,43 @@
#include "RiaApplication.h" #include "RiaApplication.h"
#include "RiaGuiApplication.h" #include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RiaOsduConnector.h"
#include "RiaPreferences.h" #include "RiaPreferences.h"
#include "RiaPreferencesOsdu.h"
#include "RigWellPath.h"
#include "RimFileWellPath.h" #include "RimFileWellPath.h"
#include "RimOilField.h"
#include "RimOsduWellPath.h"
#include "RimProject.h" #include "RimProject.h"
#include "RimTools.h" #include "RimTools.h"
#include "RimWellPathCollection.h"
#include "RimWellPathImport.h" #include "RimWellPathImport.h"
#include "RiuMainWindow.h" #include "RiuMainWindow.h"
#include "RiuWellImportWizard.h" #include "RiuWellImportWizard.h"
#include "cvfObject.h"
#include <QAction> #include <QAction>
#include <QDir> #include <QDir>
#include <QFile>
#include <QMessageBox>
CAF_CMD_SOURCE_INIT( RicWellPathsImportSsihubFeature, "RicWellPathsImportSsihubFeature" ); CAF_CMD_SOURCE_INIT( RicWellPathsImportOsduFeature, "RicWellPathsImportOsduFeature" );
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicWellPathsImportSsihubFeature::onActionTriggered( bool isChecked ) void RicWellPathsImportOsduFeature::onActionTriggered( bool isChecked )
{ {
RiaApplication* app = RiaApplication::instance(); RiaApplication* app = RiaApplication::instance();
if ( !app->project() ) return; if ( !app->project() ) return;
if ( !app->isProjectSavedToDisc() )
{
RiaGuiApplication* guiApp = RiaGuiApplication::instance();
if ( guiApp )
{
QMessageBox msgBox( guiApp->mainWindow() );
msgBox.setIcon( QMessageBox::Question );
QString questionText = QString( "Import of well paths will be stored as a part of a ResInsight project file. Please "
"save the project to file before importing well paths." );
msgBox.setText( questionText );
msgBox.setInformativeText( "Do you want to save the project?" );
msgBox.setStandardButtons( QMessageBox::Yes | QMessageBox::No );
int ret = msgBox.exec();
if ( ret == QMessageBox::Yes )
{
guiApp->saveProject();
}
}
if ( !app->isProjectSavedToDisc() )
{
return;
}
}
// Update the UTM bounding box from the reservoir // Update the UTM bounding box from the reservoir
app->project()->computeUtmAreaOfInterest(); app->project()->computeUtmAreaOfInterest();
QString wellPathsFolderPath = RimFileWellPath::getCacheDirectoryPath(); QString wellPathsFolderPath = QStandardPaths::writableLocation( QStandardPaths::CacheLocation ) + QString( "/wellpaths/" );
QDir::root().mkpath( wellPathsFolderPath ); QDir::root().mkpath( wellPathsFolderPath );
if ( !app->project()->wellPathImport() ) return; if ( !app->project()->wellPathImport() ) return;
@@ -86,35 +65,56 @@ void RicWellPathsImportSsihubFeature::onActionTriggered( bool isChecked )
QString copyOfOriginalObject = app->project()->wellPathImport()->writeObjectToXmlString(); QString copyOfOriginalObject = app->project()->wellPathImport()->writeObjectToXmlString();
if ( !app->preferences() ) return; if ( !app->preferences() ) return;
RiuWellImportWizard wellImportwizard( app->preferences()->ssihubAddress,
wellPathsFolderPath,
app->project()->wellPathImport(),
RiuMainWindow::instance() );
// Get password/username from application cache RimProject* project = RimProject::current();
{ if ( !project ) return;
#ifdef _DEBUG
// Valid credentials for ssihubfake received in mail from H<>kon if ( project->oilFields.empty() ) return;
QString ssihubUsername = "admin";
QString ssihubPassword = "resinsight"; RimOilField* oilField = project->activeOilField();
#else if ( !oilField ) return;
QString ssihubUsername = app->cacheDataObject( "ssihub_username" ).toString();
QString ssihubPassword; RiaPreferencesOsdu* osduPreferences = app->preferences()->osduPreferences();
#endif
wellImportwizard.setCredentials( ssihubUsername, ssihubPassword ); const QString server = osduPreferences->server();
} const QString dataParitionId = osduPreferences->dataPartitionId();
const QString authority = osduPreferences->authority();
const QString scopes = osduPreferences->scopes();
const QString clientId = osduPreferences->clientId();
RiaOsduConnector osduConnector( RiuMainWindow::instance(), server, dataParitionId, authority, scopes, clientId );
RiuWellImportWizard wellImportwizard( wellPathsFolderPath, &osduConnector, app->project()->wellPathImport(), RiuMainWindow::instance() );
if ( QDialog::Accepted == wellImportwizard.exec() ) if ( QDialog::Accepted == wellImportwizard.exec() )
{ {
QStringList wellPaths = wellImportwizard.absoluteFilePathsToWellPaths(); std::vector<RiuWellImportWizard::WellInfo> importedWells = wellImportwizard.importedWells();
if ( !wellPaths.empty() ) for ( auto w : importedWells )
{ {
QStringList errorMessages; auto wellPath = new RimOsduWellPath;
app->addWellPathsToModel( wellPaths, &errorMessages ); wellPath->setName( w.name );
app->project()->scheduleCreateDisplayModelAndRedrawAllViews(); wellPath->setWellId( w.wellId );
wellPath->setWellboreId( w.wellboreId );
wellPath->setWellboreTrajectoryId( w.wellboreTrajectoryId );
wellPath->setFileId( w.fileId );
oilField->wellPathCollection->addWellPath( wellPath );
auto [wellPathGeometry, errorMessage] = RimWellPathCollection::loadWellPathGeometryFromOsdu( &osduConnector, w.fileId );
if ( wellPathGeometry.notNull() )
{
wellPath->setWellPathGeometry( wellPathGeometry.p() );
}
else
{
RiaLogging::error( "Importing OSDU well failed: " + errorMessage );
}
oilField->wellPathCollection->updateConnectedEditors();
} }
app->setCacheDataObject( "ssihub_username", wellImportwizard.field( "username" ) ); project->updateConnectedEditors();
app->project()->scheduleCreateDisplayModelAndRedrawAllViews();
} }
else else
{ {
@@ -125,8 +125,8 @@ void RicWellPathsImportSsihubFeature::onActionTriggered( bool isChecked )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicWellPathsImportSsihubFeature::setupActionLook( QAction* actionToSetup ) void RicWellPathsImportOsduFeature::setupActionLook( QAction* actionToSetup )
{ {
actionToSetup->setText( "Import Well Paths from &SSI-hub" ); actionToSetup->setText( "Import Well Paths from &OSDU" );
actionToSetup->setIcon( QIcon( ":/WellCollection.png" ) ); actionToSetup->setIcon( QIcon( ":/WellCollection.png" ) );
} }

View File

@@ -24,7 +24,7 @@
//================================================================================================== //==================================================================================================
/// ///
//================================================================================================== //==================================================================================================
class RicWellPathsImportSsihubFeature : public caf::CmdFeature class RicWellPathsImportOsduFeature : public caf::CmdFeature
{ {
CAF_CMD_HEADER_INIT; CAF_CMD_HEADER_INIT;

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS // Copyright (C) 2024 Equinor ASA
// //
// ResInsight is free software: you can redistribute it and/or modify // ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@@ -53,12 +53,6 @@ RimWellPathImport::RimWellPathImport()
{ {
CAF_PDM_InitObject( "RimWellPathImport" ); CAF_PDM_InitObject( "RimWellPathImport" );
CAF_PDM_InitField( &wellTypeSurvey, "WellTypeSurvey", true, "Survey" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &wellTypeSurvey );
CAF_PDM_InitField( &wellTypePlans, "WellTypePlans", true, "Plans" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &wellTypePlans );
caf::AppEnum<RimWellPathImport::UtmFilterEnum> defaultUtmMode = UTM_FILTER_OFF; caf::AppEnum<RimWellPathImport::UtmFilterEnum> defaultUtmMode = UTM_FILTER_OFF;
CAF_PDM_InitField( &utmFilterMode, "UtmMode", defaultUtmMode, "Utm Filter" ); CAF_PDM_InitField( &utmFilterMode, "UtmMode", defaultUtmMode, "Utm Filter" );
@@ -67,95 +61,7 @@ RimWellPathImport::RimWellPathImport()
CAF_PDM_InitField( &east, "UtmEast", 0.0, "East" ); CAF_PDM_InitField( &east, "UtmEast", 0.0, "East" );
CAF_PDM_InitField( &west, "UtmWest", 0.0, "West" ); CAF_PDM_InitField( &west, "UtmWest", 0.0, "West" );
CAF_PDM_InitFieldNoDefault( &regions, "Regions", "" ); CAF_PDM_InitFieldNoDefault( &regions_OBSOLETE, "Regions", "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathImport::updateRegions( const QStringList& regionStrings, const QStringList& fieldStrings, const QStringList& edmIds )
{
assert( regionStrings.size() == fieldStrings.size() && regionStrings.size() == edmIds.size() );
std::vector<RimOilRegionEntry*> regionsToRemove;
// Remove regions and fields not present in last request
for ( size_t regionIdx = 0; regionIdx < regions.size(); regionIdx++ )
{
if ( !regionStrings.contains( regions[regionIdx]->name ) )
{
regionsToRemove.push_back( regions[regionIdx] );
}
else
{
std::vector<RimOilFieldEntry*> fieldsToRemove;
for ( size_t fIdx = 0; fIdx < regions[regionIdx]->fields.size(); fIdx++ )
{
if ( !fieldStrings.contains( regions[regionIdx]->fields[fIdx]->name ) )
{
fieldsToRemove.push_back( regions[regionIdx]->fields[fIdx] );
}
}
for ( size_t i = 0; i < fieldsToRemove.size(); i++ )
{
regions[regionIdx]->fields.removeChild( fieldsToRemove[i] );
delete fieldsToRemove[i];
}
}
}
for ( size_t i = 0; i < regionsToRemove.size(); i++ )
{
regions.removeChild( regionsToRemove[i] );
delete regionsToRemove[i];
}
for ( int i = 0; i < regionStrings.size(); i++ )
{
RimOilRegionEntry* oilRegionEntry = nullptr;
RimOilFieldEntry* oilFieldEntry = nullptr;
for ( size_t regionIdx = 0; regionIdx < regions.size(); regionIdx++ )
{
if ( regions[regionIdx]->name == regionStrings[i] )
{
oilRegionEntry = regions[regionIdx];
for ( size_t fIdx = 0; fIdx < regions[regionIdx]->fields.size(); fIdx++ )
{
if ( regions[regionIdx]->fields[fIdx]->edmId == edmIds[i] )
{
oilFieldEntry = regions[regionIdx]->fields[fIdx];
}
}
}
}
if ( !oilRegionEntry )
{
oilRegionEntry = new RimOilRegionEntry;
oilRegionEntry->name = regionStrings[i];
regions.push_back( oilRegionEntry );
}
assert( oilRegionEntry );
if ( !oilFieldEntry )
{
oilFieldEntry = new RimOilFieldEntry;
oilFieldEntry->name = fieldStrings[i];
oilFieldEntry->edmId = edmIds[i];
oilRegionEntry->fields.push_back( oilFieldEntry );
}
}
updateFieldVisibility();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -198,71 +104,10 @@ void RimWellPathImport::fieldChangedByUi( const caf::PdmFieldHandle* changedFiel
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathImport::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
caf::PdmUiTreeViewEditorAttribute* myAttr = dynamic_cast<caf::PdmUiTreeViewEditorAttribute*>( attribute );
if ( myAttr )
{
QStringList colHeaders;
colHeaders << "Region";
myAttr->columnHeaders = colHeaders;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathImport::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
// NOTE: If the default uiOrdering is used, the first checkbox is not possible to interact with using the mouse
// (only keyboard). This is a workaround to make the first checkbox work.
//
// Related issue, but with an opposite fix
// https://github.com/OPM/ResInsight/commit/51443d7aa33abebfaa179e645c729fde19a64666
//
auto group = uiOrdering.addNewGroup( "Well Types" );
group->add( &wellTypeSurvey );
group->add( &wellTypePlans );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RimWellPathImport::~RimWellPathImport() RimWellPathImport::~RimWellPathImport()
{ {
regions.deleteChildren(); regions_OBSOLETE.deleteChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathImport::updateFilePaths()
{
QString wellPathsFolderPath = RimFileWellPath::getCacheDirectoryPath();
for ( size_t regionIdx = 0; regionIdx < regions.size(); regionIdx++ )
{
for ( size_t fIdx = 0; fIdx < regions[regionIdx]->fields.size(); fIdx++ )
{
RimOilFieldEntry* oilField = regions[regionIdx]->fields[fIdx];
QFileInfo fi( oilField->wellsFilePath );
QString newWellsFilePath = wellPathsFolderPath + "/" + fi.fileName();
oilField->wellsFilePath = newWellsFilePath;
for ( size_t wIdx = 0; wIdx < oilField->wells.size(); wIdx++ )
{
RimWellPathEntry* rimWellPathEntry = oilField->wells[wIdx];
QFileInfo fiWell( rimWellPathEntry->wellPathFilePath );
QString newFilePath = wellPathsFolderPath + "/" + fiWell.fileName();
rimWellPathEntry->wellPathFilePath = newFilePath;
}
}
}
} }

View File

@@ -41,25 +41,17 @@ public:
RimWellPathImport(); RimWellPathImport();
~RimWellPathImport() override; ~RimWellPathImport() override;
caf::PdmField<bool> wellTypeSurvey;
caf::PdmField<bool> wellTypePlans;
caf::PdmField<caf::AppEnum<UtmFilterEnum>> utmFilterMode; caf::PdmField<caf::AppEnum<UtmFilterEnum>> utmFilterMode;
caf::PdmField<double> north; caf::PdmField<double> north;
caf::PdmField<double> south; caf::PdmField<double> south;
caf::PdmField<double> east; caf::PdmField<double> east;
caf::PdmField<double> west; caf::PdmField<double> west;
caf::PdmChildArrayField<RimOilRegionEntry*> regions; protected:
void updateRegions( const QStringList& regions, const QStringList& fields, const QStringList& edmIds );
void initAfterRead() override; void initAfterRead() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void updateFieldVisibility(); void updateFieldVisibility();
void updateFilePaths(); caf::PdmChildArrayField<RimOilRegionEntry*> regions_OBSOLETE;
}; };

View File

@@ -18,10 +18,6 @@
#pragma once #pragma once
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <QItemSelection> #include <QItemSelection>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
@@ -29,23 +25,190 @@
#include <QUrl> #include <QUrl>
#include <QWizard> #include <QWizard>
#include "RiaOsduConnector.h"
class QFile; class QFile;
class QProgressDialog;
class QLabel; class QLabel;
class QTextEdit; class QTextEdit;
class QTableView;
class RimWellPathImport; class RimWellPathImport;
class RimOilFieldEntry;
class RimWellPathEntry;
namespace caf namespace caf
{ {
class PdmUiTreeView; class PdmUiTreeView;
class PdmUiListView; class PdmUiListView;
class PdmUiPropertyView; class PdmUiPropertyView;
class PdmObjectCollection;
} // namespace caf } // namespace caf
class OsduFieldTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit OsduFieldTableModel( QObject* parent = nullptr )
: QAbstractTableModel( parent )
{
}
int rowCount( const QModelIndex& parent = QModelIndex() ) const override
{
Q_UNUSED( parent );
return static_cast<int>( m_osduFields.size() );
}
int columnCount( const QModelIndex& parent = QModelIndex() ) const override
{
Q_UNUSED( parent );
// Assuming you have three fields: id, kind, and name
return 3;
}
QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override
{
if ( !index.isValid() ) return QVariant();
if ( index.row() >= static_cast<int>( m_osduFields.size() ) || index.row() < 0 ) return QVariant();
if ( role == Qt::DisplayRole )
{
const OsduField& field = m_osduFields.at( index.row() );
switch ( index.column() )
{
case 0:
return field.id;
case 1:
return field.kind;
case 2:
return field.name;
default:
return QVariant();
}
}
return QVariant();
}
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override
{
if ( role != Qt::DisplayRole ) return QVariant();
if ( orientation == Qt::Horizontal )
{
switch ( section )
{
case 0:
return tr( "ID" );
case 1:
return tr( "Kind" );
case 2:
return tr( "Name" );
default:
return QVariant();
}
}
return QVariant();
}
void setOsduFields( const std::vector<OsduField>& osduFields )
{
beginInsertRows( QModelIndex(), 0, static_cast<int>( osduFields.size() ) );
m_osduFields = osduFields;
endInsertRows();
}
private:
std::vector<OsduField> m_osduFields;
};
class OsduWellboreTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit OsduWellboreTableModel( QObject* parent = nullptr )
: QAbstractTableModel( parent )
{
}
int rowCount( const QModelIndex& parent = QModelIndex() ) const override
{
Q_UNUSED( parent );
return static_cast<int>( m_osduWellbores.size() );
}
int columnCount( const QModelIndex& parent = QModelIndex() ) const override
{
Q_UNUSED( parent );
// Assuming you have three fields: id, kind, and name
return 3;
}
QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override
{
if ( !index.isValid() ) return QVariant();
if ( index.row() >= static_cast<int>( m_osduWellbores.size() ) || index.row() < 0 ) return QVariant();
if ( role == Qt::DisplayRole )
{
const OsduWellbore& field = m_osduWellbores.at( index.row() );
switch ( index.column() )
{
case 0:
return field.id;
case 1:
return field.kind;
case 2:
return field.name;
default:
return QVariant();
}
}
return QVariant();
}
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override
{
if ( role != Qt::DisplayRole ) return QVariant();
if ( orientation == Qt::Horizontal )
{
switch ( section )
{
case 0:
return tr( "ID" );
case 1:
return tr( "Kind" );
case 2:
return tr( "Name" );
default:
return QVariant();
}
}
return QVariant();
}
void setOsduWellbores( const QString& wellId, const std::vector<OsduWellbore>& osduWellbores )
{
m_map[wellId] = osduWellbores;
m_osduWellbores.clear();
for ( auto [name, values] : m_map )
{
for ( auto v : values )
m_osduWellbores.push_back( v );
}
beginInsertRows( QModelIndex(), 0, static_cast<int>( m_osduWellbores.size() ) );
endInsertRows();
}
private:
std::vector<OsduWellbore> m_osduWellbores;
std::map<QString, std::vector<OsduWellbore>> m_map;
};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -54,9 +217,16 @@ class AuthenticationPage : public QWizardPage
Q_OBJECT Q_OBJECT
public: public:
AuthenticationPage( const QString& webServiceAddress, QWidget* parent = nullptr ); AuthenticationPage( RiaOsduConnector* osduConnector, QWidget* parent = nullptr );
void initializePage() override; void initializePage() override;
bool isComplete() const override;
private slots:
void accessOk();
private:
bool m_accessOk;
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -67,67 +237,20 @@ class FieldSelectionPage : public QWizardPage
Q_OBJECT Q_OBJECT
public: public:
FieldSelectionPage( RimWellPathImport* wellPathImport, QWidget* parent = nullptr ); FieldSelectionPage( RimWellPathImport* wellPathImport, RiaOsduConnector* m_osduConnector, QWidget* parent = nullptr );
~FieldSelectionPage() override; ~FieldSelectionPage() override;
void initializePage() override; void initializePage() override;
bool isComplete() const override;
private slots:
void fieldsFinished();
void selectField( const QItemSelection& newSelection, const QItemSelection& oldSelection );
private: private:
caf::PdmUiPropertyView* m_propertyView; // caf::PdmUiPropertyView* m_propertyView;
}; RiaOsduConnector* m_osduConnector;
QTableView* m_tableView;
//-------------------------------------------------------------------------------------------------- OsduFieldTableModel* m_osduFieldsModel;
/// Container class used to define column headers
//--------------------------------------------------------------------------------------------------
class ObjectGroupWithHeaders : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
ObjectGroupWithHeaders()
{
CAF_PDM_InitFieldNoDefault( &objects, "PdmObjects", "" );
CAF_PDM_InitField( &m_isChecked, "IsChecked", true, "Active" );
m_isChecked.uiCapability()->setUiHidden( true );
};
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
public:
caf::PdmChildArrayField<PdmObjectHandle*> objects;
protected:
caf::PdmFieldHandle* objectToggleField() override { return &m_isChecked; }
protected:
caf::PdmField<bool> m_isChecked;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class DownloadEntity
{
public:
QString name;
QString requestUrl;
QString responseFilename;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class SummaryPageDownloadEntity : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
SummaryPageDownloadEntity();
caf::PdmField<QString> name;
caf::PdmField<QString> requestUrl;
caf::PdmField<QString> responseFilename;
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -138,24 +261,22 @@ class WellSelectionPage : public QWizardPage
Q_OBJECT Q_OBJECT
public: public:
WellSelectionPage( RimWellPathImport* wellPathImport, QWidget* parent = nullptr ); WellSelectionPage( RimWellPathImport* wellPathImport, RiaOsduConnector* m_osduConnector, QWidget* parent = nullptr );
~WellSelectionPage() override; ~WellSelectionPage() override;
void initializePage() override; void initializePage() override;
void buildWellTreeView(); bool isComplete() const override;
void selectedWellPathEntries( std::vector<DownloadEntity>& downloadEntities, caf::PdmObjectHandle* objHandle );
private:
void sortObjectsByDescription( caf::PdmObjectCollection* objects );
private slots: private slots:
void customMenuRequested( const QPoint& pos ); void wellboresFinished( const QString& wellId );
void wellsFinished();
void selectWellbore( const QItemSelection& newSelection, const QItemSelection& oldSelection );
private: private:
ObjectGroupWithHeaders* m_regionsWithVisibleWells;
RimWellPathImport* m_wellPathImportObject; RimWellPathImport* m_wellPathImportObject;
caf::PdmUiTreeView* m_wellSelectionTreeView; RiaOsduConnector* m_osduConnector;
QTableView* m_tableView;
OsduWellboreTableModel* m_osduWellboresModel;
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -166,20 +287,18 @@ class WellSummaryPage : public QWizardPage
Q_OBJECT Q_OBJECT
public: public:
WellSummaryPage( RimWellPathImport* wellPathImport, QWidget* parent = nullptr ); WellSummaryPage( RimWellPathImport* wellPathImport, RiaOsduConnector* osduConnector, QWidget* parent = nullptr );
void initializePage() override; void initializePage() override;
void updateSummaryPage();
private slots: private slots:
void slotShowDetails(); void wellboreTrajectoryFinished( const QString& wellId );
void fileDownloadFinished( const QString& fileId, const QString& filePath );
private: private:
RimWellPathImport* m_wellPathImportObject; RimWellPathImport* m_wellPathImportObject;
QTextEdit* m_textEdit; RiaOsduConnector* m_osduConnector;
caf::PdmUiListView* m_listView; QTextEdit* m_textEdit;
caf::PdmObjectCollection* m_objectGroup;
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -190,88 +309,50 @@ class RiuWellImportWizard : public QWizard
Q_OBJECT Q_OBJECT
public: public:
enum DownloadState struct WellInfo
{ {
DOWNLOAD_FIELDS, QString name;
DOWNLOAD_WELLS, QString wellId;
DOWNLOAD_WELL_PATH, QString wellboreId;
DOWNLOAD_UNDEFINED QString wellboreTrajectoryId;
QString fileId;
}; };
public: RiuWellImportWizard( const QString& downloadFolder,
RiuWellImportWizard( const QString& webServiceAddress, RiaOsduConnector* osduConnector,
const QString& downloadFolder,
RimWellPathImport* wellPathImportObject, RimWellPathImport* wellPathImportObject,
QWidget* parent = nullptr ); QWidget* parent = nullptr );
~RiuWellImportWizard() override; ~RiuWellImportWizard() override;
void setCredentials( const QString& username, const QString& password );
QStringList absoluteFilePathsToWellPaths() const;
// Methods used from the wizard pages // Methods used from the wizard pages
void resetAuthenticationCount(); void resetAuthenticationCount();
void setSelectedFieldId( const QString& fieldId );
QString selectedFieldId() const;
void setSelectedWellboreId( const QString& wellboreId );
QString selectedWellboreId() const;
void addWellInfo( RiuWellImportWizard::WellInfo wellInfo );
std::vector<RiuWellImportWizard::WellInfo> importedWells() const;
public slots: public slots:
void downloadWellPaths(); void downloadWellPaths( const QString& wellboreId );
void downloadWells(); void downloadWells( const QString& fieldId );
void downloadFields(); void downloadFields();
void checkDownloadQueueAndIssueRequests();
void issueHttpRequestToFile( QString completeUrlText, QString destinationFileName );
void cancelDownload();
void httpFinished();
void httpReadyRead();
void slotAuthenticationRequired( QNetworkReply* networkReply, QAuthenticator* authenticator ); void slotAuthenticationRequired( QNetworkReply* networkReply, QAuthenticator* authenticator );
int wellSelectionPageId();
#if !defined( QT_NO_OPENSSL ) && !defined( CVF_OSX )
void sslErrors( QNetworkReply*, const QList<QSslError>& errors );
#endif
private slots:
void slotCurrentIdChanged( int currentId );
private: private:
void startRequest( QUrl url ); RiaOsduConnector* m_osduConnector;
void setUrl( const QString& httpAddress ); QString m_selectedFieldId;
QString m_selectedWellboreId;
QString jsonFieldsFilePath();
QString jsonWellsFilePath();
void updateFieldsModel();
void parseWellsResponse( RimOilFieldEntry* oilFieldEntry );
QString getValue( const QString& key, const QString& stringContent );
QProgressDialog* progressDialog();
void hideProgressDialog();
private:
QString m_webServiceAddress;
QString m_destinationFolder; QString m_destinationFolder;
RimWellPathImport* m_wellPathImportObject; RimWellPathImport* m_wellPathImportObject;
caf::PdmUiTreeView* m_pdmTreeView; caf::PdmUiTreeView* m_pdmTreeView;
QProgressDialog* m_myProgressDialog;
QUrl m_url;
QNetworkAccessManager m_networkAccessManager;
QNetworkReply* m_reply;
QFile* m_file;
bool m_httpRequestAborted;
bool m_firstTimeRequestingAuthentication; bool m_firstTimeRequestingAuthentication;
QList<DownloadEntity> m_wellRequestQueue; std::vector<RiuWellImportWizard::WellInfo> m_wellInfos;
DownloadState m_currentDownloadState;
int m_fieldSelectionPageId;
int m_wellSelectionPageId;
int m_wellSummaryPageId;
}; };

View File

@@ -96,6 +96,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.h ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.h
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.h ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.h ${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.h
${CMAKE_CURRENT_LIST_DIR}/RifOsduWellPathReader.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@@ -191,6 +192,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationImporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCalculationExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOsduWellPathReader.cpp
) )
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -0,0 +1,92 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 Equinor 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 "RifOsduWellPathReader.h"
#include "RiaTextStringTools.h"
#include "SummaryPlotCommands/RicPasteAsciiDataToSummaryPlotFeatureUi.h"
#include "RifCsvUserDataParser.h"
#include "RigWellPath.h"
#include "cvfObject.h"
#include "cvfVector3.h"
#include <QFileInfo>
#include <QTextStream>
std::pair<cvf::ref<RigWellPath>, QString> RifOsduWellPathReader::parseCsv( const QString& content )
{
QString errorMessage;
RifCsvUserDataPastedTextParser parser( content, &errorMessage );
AsciiDataParseOptions parseOptions;
parseOptions.cellSeparator = ",";
parseOptions.decimalSeparator = ".";
std::vector<std::pair<QString, std::vector<double>>> readValues;
if ( parser.parse( parseOptions ) )
{
for ( auto s : parser.tableData().columnInfos() )
{
if ( s.dataType != Column::NUMERIC ) continue;
QString columnName = QString::fromStdString( s.columnName() );
bool isNumber = false;
auto value = columnName.toDouble( &isNumber );
std::vector<double> values = s.values;
if ( isNumber )
{
values.insert( values.begin(), value );
}
readValues.push_back( { columnName, values } );
}
}
const int MD_INDEX = 0;
const int TVD_INDEX = 1;
const int X_INDEX = 4;
const int Y_INDEX = 5;
if ( readValues.size() == 10 )
{
const size_t firstSize = readValues[MD_INDEX].second.size();
if ( ( firstSize == readValues[TVD_INDEX].second.size() ) && ( firstSize == readValues[X_INDEX].second.size() ) &&
( firstSize == readValues[Y_INDEX].second.size() ) )
{
std::vector<cvf::Vec3d> wellPathPoints;
std::vector<double> measuredDepths;
for ( size_t i = 0; i < firstSize; i++ )
{
cvf::Vec3d point( readValues[X_INDEX].second[i], readValues[Y_INDEX].second[i], -readValues[TVD_INDEX].second[i] );
double md = readValues[MD_INDEX].second[i];
wellPathPoints.push_back( point );
measuredDepths.push_back( md );
}
return { new RigWellPath( wellPathPoints, measuredDepths ), "" };
}
}
return { nullptr, "Oh no!" };
}

View File

@@ -0,0 +1,35 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QString>
#include "cvfObject.h"
class RigWellPath;
//==================================================================================================
//
//
//==================================================================================================
class RifOsduWellPathReader
{
public:
static std::pair<cvf::ref<RigWellPath>, QString> parseCsv( const QString& content );
};

View File

@@ -370,7 +370,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder.addSeparator(); menuBuilder.addSeparator();
menuBuilder.subMenuStart( "Import" ); menuBuilder.subMenuStart( "Import" );
menuBuilder << "RicWellPathsImportFileFeature"; menuBuilder << "RicWellPathsImportFileFeature";
menuBuilder << "RicWellPathsImportSsihubFeature"; menuBuilder << "RicWellPathsImportOsduFeature";
menuBuilder << "RicWellPathFormationsImportFileFeature"; menuBuilder << "RicWellPathFormationsImportFileFeature";
menuBuilder << "RicWellLogsImportFileFeature"; menuBuilder << "RicWellLogsImportFileFeature";
menuBuilder << "RicReloadWellPathFormationNamesFeature"; menuBuilder << "RicReloadWellPathFormationNamesFeature";

View File

@@ -270,8 +270,6 @@ void RimProject::close()
casesObsolete.deleteChildren(); casesObsolete.deleteChildren();
caseGroupsObsolete.deleteChildren(); caseGroupsObsolete.deleteChildren();
wellPathImport->regions().deleteChildren();
commandObjects.deleteChildren(); commandObjects.deleteChildren();
multiSnapshotDefinitions.deleteChildren(); multiSnapshotDefinitions.deleteChildren();
@@ -512,7 +510,6 @@ void RimProject::setProjectFileNameAndUpdateDependencies( const QString& project
filePath->setPath( newFilePath ); filePath->setPath( newFilePath );
} }
wellPathImport->updateFilePaths();
auto* wellPathColl = RimTools::wellPathCollection(); auto* wellPathColl = RimTools::wellPathCollection();
if ( wellPathColl ) if ( wellPathColl )
{ {

View File

@@ -15,6 +15,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelBox.h ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelBox.h
${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.h ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.h
${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.h ${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.h
${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPath.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@@ -34,6 +35,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelBox.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelBox.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.cpp
${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPath.cpp
) )
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -0,0 +1,110 @@
#include "RimOsduWellPath.h"
#include "cafPdmObjectScriptingCapability.h"
CAF_PDM_SOURCE_INIT( RimOsduWellPath, "OsduWellPath" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimOsduWellPath::RimOsduWellPath()
{
CAF_PDM_InitScriptableObjectWithNameAndComment( "Osdu Well Path", ":/Well.svg", "", "", "OsduWellPath", "Well Path Loaded From Osdu" );
CAF_PDM_InitFieldNoDefault( &m_wellId, "WellId", "Well Id" );
m_wellId.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_wellboreId, "WellboreId", "Wellbore Id" );
m_wellboreId.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_wellboreTrajectoryId, "WellboreTrajectoryId", "Wellbore Trajectory Id" );
m_wellboreTrajectoryId.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_fileId, "FileId", "File Id" );
m_fileId.uiCapability()->setUiReadOnly( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimOsduWellPath::~RimOsduWellPath()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPath::setWellId( const QString& wellId )
{
m_wellId = wellId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimOsduWellPath::wellId() const
{
return m_wellId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPath::setWellboreId( const QString& wellboreId )
{
m_wellboreId = wellboreId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimOsduWellPath::wellboreId() const
{
return m_wellboreId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPath::setWellboreTrajectoryId( const QString& wellboreTrajectoryId )
{
m_wellboreTrajectoryId = wellboreTrajectoryId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimOsduWellPath::wellboreTrajectoryId() const
{
return m_wellboreTrajectoryId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPath::setFileId( const QString& fileId )
{
m_fileId = fileId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimOsduWellPath::fileId() const
{
return m_fileId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* osduGroup = uiOrdering.addNewGroup( "OSDU" );
osduGroup->add( &m_wellId );
osduGroup->add( &m_wellboreId );
osduGroup->add( &m_wellboreTrajectoryId );
osduGroup->add( &m_fileId );
RimWellPath::defineUiOrdering( uiConfigName, uiOrdering );
}

View File

@@ -0,0 +1,50 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- Equinor 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimWellPath.h"
class RimOsduWellPath : public RimWellPath
{
CAF_PDM_HEADER_INIT;
public:
RimOsduWellPath();
~RimOsduWellPath() override;
void setWellId( const QString& wellId );
QString wellId() const;
void setWellboreId( const QString& wellboreId );
QString wellboreId() const;
void setWellboreTrajectoryId( const QString& wellboreTrajectoryId );
QString wellboreTrajectoryId() const;
void setFileId( const QString& fileId );
QString fileId() const;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
private:
caf::PdmField<QString> m_wellId;
caf::PdmField<QString> m_wellboreId;
caf::PdmField<QString> m_wellboreTrajectoryId;
caf::PdmField<QString> m_fileId;
};

View File

@@ -20,6 +20,7 @@
#include "RimWellPathCollection.h" #include "RimWellPathCollection.h"
#include "OsduImportCommands/RiaOsduConnector.h"
#include "RiaColorTables.h" #include "RiaColorTables.h"
#include "RiaGuiApplication.h" #include "RiaGuiApplication.h"
#include "RiaLogging.h" #include "RiaLogging.h"
@@ -27,6 +28,7 @@
#include "RiaTextStringTools.h" #include "RiaTextStringTools.h"
#include "RiaWellNameComparer.h" #include "RiaWellNameComparer.h"
#include "RifOsduWellPathReader.h"
#include "RifWellPathFormationsImporter.h" #include "RifWellPathFormationsImporter.h"
#include "RifWellPathImporter.h" #include "RifWellPathImporter.h"
@@ -40,6 +42,7 @@
#include "RimFileWellPath.h" #include "RimFileWellPath.h"
#include "RimModeledWellPath.h" #include "RimModeledWellPath.h"
#include "RimOilField.h" #include "RimOilField.h"
#include "RimOsduWellPath.h"
#include "RimPerforationCollection.h" #include "RimPerforationCollection.h"
#include "RimProject.h" #include "RimProject.h"
#include "RimStimPlanModel.h" #include "RimStimPlanModel.h"
@@ -50,6 +53,8 @@
#include "RimWellPathCompletionSettings.h" #include "RimWellPathCompletionSettings.h"
#include "RimWellPathTieIn.h" #include "RimWellPathTieIn.h"
#include "RiuMainWindow.h"
#include "cafTreeNode.h" // TODO: Move to caf #include "cafTreeNode.h" // TODO: Move to caf
#include "Riu3DMainWindowTools.h" #include "Riu3DMainWindowTools.h"
@@ -67,6 +72,7 @@
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <memory>
namespace caf namespace caf
{ {
@@ -149,6 +155,7 @@ void RimWellPathCollection::loadDataAndUpdate()
auto* fWPath = dynamic_cast<RimFileWellPath*>( wellPath ); auto* fWPath = dynamic_cast<RimFileWellPath*>( wellPath );
auto* mWPath = dynamic_cast<RimModeledWellPath*>( wellPath ); auto* mWPath = dynamic_cast<RimModeledWellPath*>( wellPath );
auto* oWPath = dynamic_cast<RimOsduWellPath*>( wellPath );
if ( fWPath ) if ( fWPath )
{ {
if ( !fWPath->filePath().isEmpty() ) if ( !fWPath->filePath().isEmpty() )
@@ -164,6 +171,31 @@ void RimWellPathCollection::loadDataAndUpdate()
{ {
mWPath->createWellPathGeometry(); mWPath->createWellPathGeometry();
} }
else if ( oWPath )
{
RiaApplication* app = RiaApplication::instance();
RiaPreferencesOsdu* osduPreferences = app->preferences()->osduPreferences();
const QString server = osduPreferences->server();
const QString dataParitionId = osduPreferences->dataPartitionId();
const QString authority = osduPreferences->authority();
const QString scopes = osduPreferences->scopes();
const QString clientId = osduPreferences->clientId();
auto osduConnector =
std::make_unique<RiaOsduConnector>( RiuMainWindow::instance(), server, dataParitionId, authority, scopes, clientId );
auto [wellPathGeometry, errorMessage] = loadWellPathGeometryFromOsdu( osduConnector.get(), oWPath->fileId() );
if ( wellPathGeometry.notNull() )
{
oWPath->setWellPathGeometry( wellPathGeometry.p() );
}
else
{
RiaLogging::warning( errorMessage );
}
}
if ( wellPath ) if ( wellPath )
{ {
@@ -1013,3 +1045,18 @@ void RimWellPathCollection::onChildAdded( caf::PdmFieldHandle* containerForNewOb
scheduleRedrawAffectedViews(); scheduleRedrawAffectedViews();
uiCapability()->updateConnectedEditors(); uiCapability()->updateConnectedEditors();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<cvf::ref<RigWellPath>, QString> RimWellPathCollection::loadWellPathGeometryFromOsdu( RiaOsduConnector* osduConnector,
const QString& fileId )
{
auto [fileContents, errorMessage] = osduConnector->requestFileContentsById( fileId );
if ( !errorMessage.isEmpty() )
{
return { nullptr, errorMessage };
}
return RifOsduWellPathReader::parseCsv( fileContents );
}

View File

@@ -38,6 +38,7 @@
#include <memory> #include <memory>
class RiaOsduConnector;
class RifWellPathImporter; class RifWellPathImporter;
class RigWellPath; class RigWellPath;
class RimFileWellPath; class RimFileWellPath;
@@ -131,6 +132,8 @@ public:
void onChildAdded( caf::PdmFieldHandle* containerForNewObject ) override; void onChildAdded( caf::PdmFieldHandle* containerForNewObject ) override;
static std::pair<cvf::ref<RigWellPath>, QString> loadWellPathGeometryFromOsdu( RiaOsduConnector* osduConnector, const QString& fileId );
protected: protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;

View File

@@ -103,6 +103,7 @@ set(SOURCE_UNITTEST_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEmReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEmReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPolygonReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifParquetReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifParquetReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOsduWellPathReader-Test.cpp
) )
if(RESINSIGHT_ENABLE_GRPC) if(RESINSIGHT_ENABLE_GRPC)

View File

@@ -0,0 +1,59 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024- Equinor 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 "gtest/gtest.h"
#include "RifOsduWellPathReader.h"
#include "RigWellPath.h"
#include "cvfObject.h"
TEST( RifOsduWellPathReader, ParseCsv )
{
std::string fileContent = R"(
MD,TVD,AZIMUTH,INCLINATION,X,Y,GODLEG_SEVERITY,DX,DY,UWI,WELLBORE,CRS,EPSG_CODE
0.0,0.0,1e-10,0.0,68.8767382,33.1345775,0.0,0.0,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
271.49,271.49,1e-10,0.0,68.8767382,33.1345775,0.0,0.0,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
306.29,306.29,272.01823962,0.08968724,68.8767375,33.1345774,0.24,-0.06,-0.01,WELL NAME #1,WELL NAME #1,WGS84,4326
336.29,336.29,274.30140794,0.15846019,68.8767368,33.1345775,0.22,-0.12,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
366.29,366.29,278.8234303,0.09299958,68.8767359,33.1345775,0.23,-0.2,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
396.29,396.29,272.75661039,0.10458399,68.8767352,33.1345775,0.11,-0.26,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
426.56,426.29,268.84493373,0.12982945,68.8767347,33.1345775,0.24,-0.3,0.0,WELL NAME #1,WELL NAME #1,WGS84,4326
456.29,456.29,247.08294017,0.24449049,68.8767336,33.1345774,0.58,-0.39,-0.01,WELL NAME #1,WELL NAME #1,WGS84,4326
486.29,486.28,228.45433687,1.77934187,68.876729,33.1345746,1.0,-0.78,-0.33,WELL NAME #1,WELL NAME #1,WGS84,4326
516.29,516.25,234.24032672,3.25969626,68.8767165,33.1345672,1.41,-1.85,-1.15,WELL NAME #1,WELL NAME #1,WGS84,4326
546.29,546.17,235.37605057,5.34499442,68.8766954,33.1345561,3.39,-3.64,-2.39,WELL NAME #1,WELL NAME #1,WGS84,4326
576.29,575.97,233.86086873,7.54998951,68.8766625,33.1345381,1.98,-6.44,-4.4,WELL NAME #1,WELL NAME #1,WGS84,4326
)";
QString fileContentAsQString = QString::fromStdString( fileContent );
auto [wellPath, errorMessage] = RifOsduWellPathReader::parseCsv( fileContentAsQString );
EXPECT_TRUE( wellPath.notNull() );
EXPECT_EQ( 12u, wellPath->wellPathPoints().size() );
EXPECT_EQ( 12u, wellPath->measuredDepths().size() );
cvf::Vec3d point = wellPath->wellPathPoints()[6];
EXPECT_DOUBLE_EQ( 68.8767347, point.x() );
EXPECT_DOUBLE_EQ( 33.1345775, point.y() );
EXPECT_DOUBLE_EQ( -426.29, point.z() );
EXPECT_DOUBLE_EQ( 426.56, wellPath->measuredDepths()[6] );
}

View File

@@ -138,7 +138,7 @@ void RiuMenuBarBuildTools::addImportMenuWithActions( QObject* parent, QMenu* men
importMenu->addSeparator(); importMenu->addSeparator();
QMenu* importWellMenu = importMenu->addMenu( QIcon( ":/Well.svg" ), "Well Data" ); QMenu* importWellMenu = importMenu->addMenu( QIcon( ":/Well.svg" ), "Well Data" );
importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathsImportFileFeature" ) ); importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathsImportFileFeature" ) );
importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathsImportSsihubFeature" ) ); importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathsImportOsduFeature" ) );
importWellMenu->addAction( cmdFeatureMgr->action( "RicWellLogsImportFileFeature" ) ); importWellMenu->addAction( cmdFeatureMgr->action( "RicWellLogsImportFileFeature" ) );
importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathFormationsImportFileFeature" ) ); importWellMenu->addAction( cmdFeatureMgr->action( "RicWellPathFormationsImportFileFeature" ) );
importWellMenu->addAction( cmdFeatureMgr->action( "RicImportWellMeasurementsFeature" ) ); importWellMenu->addAction( cmdFeatureMgr->action( "RicImportWellMeasurementsFeature" ) );

View File

@@ -508,7 +508,8 @@ endif()
set(RI_QT_MINIMUM_VERSION 5.12) set(RI_QT_MINIMUM_VERSION 5.12)
find_package( find_package(
Qt5 ${RI_QT_MINIMUM_VERSION} COMPONENTS Core Gui OpenGL Network Widgets Qt5 ${RI_QT_MINIMUM_VERSION} COMPONENTS Core Gui OpenGL Network NetworkAuth
Widgets
) )
# Open GL # Open GL