diff --git a/ApplicationLibCode/Application/RiaApplication.cpp b/ApplicationLibCode/Application/RiaApplication.cpp index f373e31a06..c615eac49c 100644 --- a/ApplicationLibCode/Application/RiaApplication.cpp +++ b/ApplicationLibCode/Application/RiaApplication.cpp @@ -54,6 +54,8 @@ #include "RimEclipseView.h" #include "RimEnsembleWellLogsCollection.h" #include "RimFaultReactivationModelCollection.h" +#include "RimFileWellPath.h" +#include "RimFileWellPathDataLoader.h" #include "RimFormationNamesCollection.h" #include "RimFractureTemplateCollection.h" #include "RimGeoMechCase.h" @@ -63,10 +65,15 @@ #include "RimGridSummaryCase.h" #include "RimIdenticalGridCaseGroup.h" #include "RimMainPlotCollection.h" +#include "RimModeledWellPath.h" +#include "RimModeledWellPathDataLoader.h" #include "RimObservedDataCollection.h" #include "RimObservedFmuRftData.h" #include "RimObservedSummaryData.h" #include "RimOilField.h" +#include "RimOsduWellPath.h" +#include "RimOsduWellPathDataLoader.h" +#include "RimPlotWindow.h" #include "RimProject.h" #include "RimScriptCollection.h" #include "RimSeismicData.h" @@ -96,6 +103,7 @@ #include "RiuViewer.h" #include "RiuViewerCommands.h" +#include "cafDataLoadController.h" #include "cafPdmCodeGenerator.h" #include "cafPdmDataValueField.h" #include "cafPdmDefaultObjectFactory.h" @@ -1525,6 +1533,8 @@ void RiaApplication::initialize() m_project->setPlotTemplateFolders( m_preferences->plotTemplateFolders() ); caf::SelectionManager::instance()->setPdmRootObject( project() ); + + initializeDataLoadController(); } //-------------------------------------------------------------------------------------------------- @@ -1730,3 +1740,22 @@ RiaSumoConnector* RiaApplication::makeSumoConnector() return m_sumoConnector; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaApplication::initializeDataLoadController() +{ + caf::DataLoadController* dataLoadController = caf::DataLoadController::instance(); + + const QString wellPathGeometryKeyword = "WELL_PATH_GEOMETRY"; + dataLoadController->registerDataLoader( RimFileWellPath::classKeywordStatic(), + wellPathGeometryKeyword, + std::make_shared() ); + dataLoadController->registerDataLoader( RimOsduWellPath::classKeywordStatic(), + wellPathGeometryKeyword, + std::make_shared() ); + dataLoadController->registerDataLoader( RimModeledWellPath::classKeywordStatic(), + wellPathGeometryKeyword, + std::make_shared() ); +} diff --git a/ApplicationLibCode/Application/RiaApplication.h b/ApplicationLibCode/Application/RiaApplication.h index ce0feaac55..5d9d046c2e 100644 --- a/ApplicationLibCode/Application/RiaApplication.h +++ b/ApplicationLibCode/Application/RiaApplication.h @@ -227,6 +227,8 @@ protected: bool generateCode( const QString& outputPath, gsl::not_null errMsg ); protected: + void initializeDataLoadController(); + cvf::ref m_defaultSceneFont; cvf::ref m_defaultAnnotationFont; cvf::ref m_defaultWellLabelFont; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/WellPath/CMakeLists_files.cmake index ab55fcaf61..14418631df 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/WellPath/CMakeLists_files.cmake @@ -16,6 +16,9 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.h ${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.h ${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPath.h + ${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPathDataLoader.h + ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPathDataLoader.h + ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPathDataLoader.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -36,12 +39,18 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimWellIAModelData.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellIADataAccess.cpp ${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPath.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPathDataLoader.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFileWellPathDataLoader.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimModeledWellPathDataLoader.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) +list(APPEND QT_MOC_HEADERS ${CMAKE_CURRENT_LIST_DIR}/RimOsduWellPathDataLoader.h) + + source_group( "ProjectDataModel\\WellPath" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.cpp new file mode 100644 index 0000000000..d751ff4eb5 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.cpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFileWellPathDataLoader.h" + +#include "RiaLogging.h" +#include "RimFileWellPath.h" + +#include "RigWellPath.h" + +#include "cafProgressInfo.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFileWellPathDataLoader::RimFileWellPathDataLoader() + : caf::DataLoader() +{ + m_wellPathImporter = std::make_unique(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFileWellPathDataLoader::loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) +{ + auto* fWPath = dynamic_cast( &pdmObject ); + if ( fWPath && !fWPath->filePath().isEmpty() ) + { + QString errorMessage; + if ( !fWPath->readWellPathFile( &errorMessage, m_wellPathImporter.get(), false ) ) + { + RiaLogging::warning( errorMessage ); + } + } + taskDone.send( dataType, taskId ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFileWellPathDataLoader::isRunnable() const +{ + return true; +} diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.h b/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.h new file mode 100644 index 0000000000..5f9b2a2b08 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimFileWellPathDataLoader.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimFileWellPath.h" + +#include "cafDataLoader.h" +#include "cafProgressInfo.h" + +#include + +#include + +#include "RifWellPathImporter.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFileWellPathDataLoader : public caf::DataLoader +{ +public: + RimFileWellPathDataLoader(); + void loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) override; + bool isRunnable() const override; + +private: + std::unique_ptr m_wellPathImporter; +}; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.cpp new file mode 100644 index 0000000000..1520f2a8a0 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.cpp @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimModeledWellPathDataLoader.h" + +#include "RimModeledWellPath.h" + +#include "RigWellPath.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimModeledWellPathDataLoader::RimModeledWellPathDataLoader() + : caf::DataLoader() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimModeledWellPathDataLoader::loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) +{ + auto* mWPath = dynamic_cast( &pdmObject ); + + if ( mWPath ) + { + mWPath->createWellPathGeometry(); + } + + taskDone.send( dataType, taskId ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimModeledWellPathDataLoader::isRunnable() const +{ + return true; +} diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.h b/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.h new file mode 100644 index 0000000000..c17fd1deab --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimModeledWellPathDataLoader.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafDataLoader.h" +#include "cafProgressInfo.h" + +#include + +//================================================================================================== +/// +/// +//================================================================================================== +class RimModeledWellPathDataLoader : public caf::DataLoader +{ +public: + RimModeledWellPathDataLoader(); + void loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) override; + bool isRunnable() const override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.cpp new file mode 100644 index 0000000000..72f1ea04bf --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.cpp @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimOsduWellPathDataLoader.h" + +#include "Cloud/RiaOsduConnector.h" +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RimOsduWellPath.h" + +#include "RifOsduWellPathReader.h" + +#include "RigWellPath.h" + +#include "cafProgressInfo.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimOsduWellPathDataLoader::RimOsduWellPathDataLoader() + : caf::DataLoader() +{ + RiaApplication* app = RiaApplication::instance(); + RiaOsduConnector* osduConnector = app->makeOsduConnector(); + + connect( osduConnector, + SIGNAL( parquetDownloadFinished( const QByteArray&, const QString&, const QString& ) ), + this, + SLOT( parquetDownloadComplete( const QByteArray&, const QString&, const QString& ) ), + Qt::QueuedConnection ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimOsduWellPathDataLoader::loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) +{ + RiaApplication* app = RiaApplication::instance(); + RiaOsduConnector* osduConnector = app->makeOsduConnector(); + + // TODO: this is weird? + m_dataType = dataType; + + auto oWPath = dynamic_cast( &pdmObject ); + if ( oWPath ) + { + QString trajectoryId = oWPath->wellboreTrajectoryId(); + osduConnector->requestWellboreTrajectoryParquetDataById( trajectoryId ); + m_wellPaths[trajectoryId] = oWPath; + m_taskIds[trajectoryId] = taskId; + } + QApplication::processEvents(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimOsduWellPathDataLoader::isRunnable() const +{ + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimOsduWellPathDataLoader::parquetDownloadComplete( const QByteArray& contents, const QString& url, const QString& id ) +{ + RiaLogging::info( QString( "Parquet download complete. Id: %1 Size: %2" ).arg( id ).arg( contents.size() ) ); + + QMutexLocker lock( &m_mutex ); + int taskId = m_taskIds[id]; + + if ( !contents.isEmpty() ) + { + m_parquetData[id] = contents; + + auto oWPath = m_wellPaths[id]; + auto [wellPathGeometry, errorMessage] = RifOsduWellPathReader::readWellPathData( contents, oWPath->datumElevationFromOsdu() ); + if ( wellPathGeometry.notNull() ) + { + oWPath->setWellPathGeometry( wellPathGeometry.p() ); + } + else + { + RiaLogging::warning( errorMessage ); + } + } + + taskDone.send( m_dataType, taskId ); +} diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.h b/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.h new file mode 100644 index 0000000000..7387e40986 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimOsduWellPathDataLoader.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimOsduWellPath.h" + +#include "cafDataLoader.h" +#include "cafProgressInfo.h" + +#include +#include +#include + +//================================================================================================== +/// +/// +//================================================================================================== +class RimOsduWellPathDataLoader : public QObject, public caf::DataLoader +{ + Q_OBJECT +public: + RimOsduWellPathDataLoader(); + void loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) override; + bool isRunnable() const override; + +private slots: + void parquetDownloadComplete( const QByteArray& contents, const QString& url, const QString& id ); + +private: + std::map m_parquetData; + std::map m_wellPaths; + std::map m_taskIds; + QString m_dataType; + QMutex m_mutex; +}; diff --git a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPathCollection.cpp b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPathCollection.cpp index 6a6f4033be..b66067adc4 100644 --- a/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPathCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellPath/RimWellPathCollection.cpp @@ -22,6 +22,7 @@ #include "Cloud/RiaOsduConnector.h" #include "RiaColorTables.h" +#include "RiaDateStringParser.h" #include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPreferences.h" @@ -62,6 +63,8 @@ #include "Riu3DMainWindowTools.h" +#include "cafDataLoadController.h" +#include "cafDataLoader.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiEditorHandle.h" @@ -154,73 +157,47 @@ void RimWellPathCollection::loadDataAndUpdate() RiaApplication* app = RiaApplication::instance(); + caf::DataLoadController* dataLoadController = caf::DataLoadController::instance(); + + const QString wellPathGeometryKeyword = "WELL_PATH_GEOMETRY"; + for ( RimWellPath* wellPath : allWellPaths() ) { - progress.setProgressDescription( QString( "Reading file %1" ).arg( wellPath->name() ) ); + progress.setProgressDescription( QString( "Reading well %1" ).arg( wellPath->name() ) ); + dataLoadController->loadData( *wellPath, wellPathGeometryKeyword, progress ); + } - auto* fWPath = dynamic_cast( wellPath ); - auto* mWPath = dynamic_cast( wellPath ); - auto* oWPath = dynamic_cast( wellPath ); - if ( fWPath ) + dataLoadController->blockUntilDone( wellPathGeometryKeyword ); + + for ( RimWellPath* wellPath : allWellPaths() ) + { + for ( RimWellLog* wellLog : wellPath->wellLogs() ) { - if ( !fWPath->filePath().isEmpty() ) + if ( RimWellLogFile* wellLogFile = dynamic_cast( wellLog ) ) { QString errorMessage; - if ( !fWPath->readWellPathFile( &errorMessage, m_wellPathImporter.get(), false ) ) + if ( !wellLogFile->readFile( &errorMessage ) ) { RiaLogging::warning( errorMessage ); } } - } - else if ( mWPath ) - { - mWPath->createWellPathGeometry(); - } - else if ( oWPath ) - { - RiaOsduConnector* osduConnector = app->makeOsduConnector(); - auto [wellPathGeometry, errorMessage] = - loadWellPathGeometryFromOsdu( osduConnector, oWPath->wellboreTrajectoryId(), oWPath->datumElevationFromOsdu() ); - if ( wellPathGeometry.notNull() ) + else if ( RimOsduWellLog* osduWellLog = dynamic_cast( wellLog ) ) { - oWPath->setWellPathGeometry( wellPathGeometry.p() ); - } - else - { - RiaLogging::warning( errorMessage ); + RiaOsduConnector* osduConnector = app->makeOsduConnector(); + auto [wellLogData, errorMessage] = loadWellLogFromOsdu( osduConnector, osduWellLog->wellLogId() ); + if ( wellLogData.notNull() ) + { + osduWellLog->setWellLogData( wellLogData.p() ); + } } } - if ( wellPath ) + RimStimPlanModelCollection* stimPlanModelCollection = wellPath->stimPlanModelCollection(); + if ( stimPlanModelCollection ) { - for ( RimWellLog* wellLog : wellPath->wellLogs() ) + for ( RimStimPlanModel* stimPlanModel : stimPlanModelCollection->allStimPlanModels() ) { - if ( RimWellLogFile* wellLogFile = dynamic_cast( wellLog ) ) - { - QString errorMessage; - if ( !wellLogFile->readFile( &errorMessage ) ) - { - RiaLogging::warning( errorMessage ); - } - } - else if ( RimOsduWellLog* osduWellLog = dynamic_cast( wellLog ) ) - { - RiaOsduConnector* osduConnector = app->makeOsduConnector(); - auto [wellLogData, errorMessage] = loadWellLogFromOsdu( osduConnector, osduWellLog->wellLogId() ); - if ( wellLogData.notNull() ) - { - osduWellLog->setWellLogData( wellLogData.p() ); - } - } - } - - RimStimPlanModelCollection* stimPlanModelCollection = wellPath->stimPlanModelCollection(); - if ( stimPlanModelCollection ) - { - for ( RimStimPlanModel* stimPlanModel : stimPlanModelCollection->allStimPlanModels() ) - { - stimPlanModel->loadDataAndUpdate(); - } + stimPlanModel->loadDataAndUpdate(); } } progress.incrementProgress(); diff --git a/CMakeLists.txt b/CMakeLists.txt index 4600813045..f970c62e39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -805,6 +805,7 @@ add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafPdmCore) add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore) add_subdirectory(Fwk/AppFwk/cafProjectDataModel/cafPdmXml) add_subdirectory(Fwk/AppFwk/cafProjectDataModel) +add_subdirectory(Fwk/AppFwk/cafDataLoader) add_subdirectory(Fwk/AppFwk/cafCommand) add_subdirectory(Fwk/AppFwk/cafUserInterface) @@ -864,6 +865,7 @@ list( cafCommand cafPdmCvf cafTensor + cafDataLoader CommonCode cafVizExtensions cafPdmScripting diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index b7f3c7f0e0..1cedc7fb32 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -45,6 +45,7 @@ add_subdirectory(cafCommand) add_subdirectory(cafCommandFeatures) add_subdirectory(cafUserInterface) add_subdirectory(cafPdmScripting) +add_subdirectory(cafDataLoader) # executables add_subdirectory(cafTests/cafTestApplication) diff --git a/Fwk/AppFwk/cafDataLoader/CMakeLists.txt b/Fwk/AppFwk/cafDataLoader/CMakeLists.txt new file mode 100644 index 0000000000..a805077cbd --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/CMakeLists.txt @@ -0,0 +1,48 @@ +project(cafDataLoader) + +# Unity Build +if(CAF_ENABLE_UNITY_BUILD) + message("Cmake Unity build is enabled on : ${PROJECT_NAME}") + set(CMAKE_UNITY_BUILD true) +endif() + +# Qt +if(CEE_USE_QT6) + find_package( + Qt6 + COMPONENTS + REQUIRED Core Gui Widgets + ) + set(QT_LIBRARIES Qt6::Core Qt6::Gui Qt6::Widgets) + qt_standard_project_setup() +else() + find_package( + Qt5 + COMPONENTS + REQUIRED Core Gui Widgets + ) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets) +endif() + +set(PROJECT_FILES + cafDataLoader.h + cafDataLoader.cpp + cafDataLoadTask.h + cafDataLoadTask.cpp + cafDataLoadController.h + cafDataLoadController.cpp +) + +add_library(${PROJECT_NAME} ${PROJECT_FILES}) + +target_link_libraries(${PROJECT_NAME} cafProjectDataModel ${QT_LIBRARIES}) + +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if(MSVC) + set_target_properties( + ${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/W4 /wd4100 /wd4127 /wd4996" + ) +endif() + +source_group("" FILES ${PROJECT_FILES}) diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoadController.cpp b/Fwk/AppFwk/cafDataLoader/cafDataLoadController.cpp new file mode 100644 index 0000000000..5440eeeea3 --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoadController.cpp @@ -0,0 +1,136 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#include "cafDataLoadController.h" + +#include "cafDataLoadTask.h" +#include "cafDataLoader.h" +#include "cafPdmObject.h" + +#include +#include +#include + +using namespace caf; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +DataLoadController::DataLoadController() + : m_taskId( 0 ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +DataLoadController* DataLoadController::instance() +{ + static DataLoadController* singleton = new DataLoadController; + return singleton; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void DataLoadController::registerDataLoader( const QString& objectType, + const QString& dataType, + std::shared_ptr dataLoader ) +{ + std::pair key = { objectType, dataType }; + m_dataLoaders[key] = dataLoader; + + dataLoader->taskDone.connect( this, &DataLoadController::onTaskFinished ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void DataLoadController::loadData( caf::PdmObject& object, const QString& dataType, ProgressInfo& progressInfo ) +{ + std::pair key = { object.classKeyword(), dataType }; + auto it = m_dataLoaders.find( key ); + if ( it != m_dataLoaders.end() ) + { + std::shared_ptr dataLoader = it->second; + + QMutexLocker locker( &m_mutex ); + m_pendingTasksByType[dataType]++; + locker.unlock(); + + if ( dataLoader->isRunnable() ) + { + DataLoadTask* task = new DataLoadTask( *this, *dataLoader.get(), object, dataType, m_taskId++, progressInfo ); + task->setAutoDelete( true ); + QThreadPool::globalInstance()->start( task ); + } + else + { + dataLoader->loadData( object, dataType, m_taskId++, progressInfo ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void DataLoadController::blockUntilDone( const QString& dataType ) +{ + int numPending = 0; + { + QMutexLocker locker( &m_mutex ); + numPending = m_pendingTasksByType[dataType]; + } + while ( numPending > 0 ) + { + { + QMutexLocker locker( &m_mutex ); + numPending = m_pendingTasksByType[dataType]; + } + + QApplication::processEvents(); + QThread::msleep( 100 ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void DataLoadController::onTaskFinished( const caf::SignalEmitter* emitter, QString dataType, int taskId ) +{ + QMutexLocker locker( &m_mutex ); + m_pendingTasksByType[dataType]--; +} diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoadController.h b/Fwk/AppFwk/cafDataLoader/cafDataLoadController.h new file mode 100644 index 0000000000..ea40f7b44e --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoadController.h @@ -0,0 +1,86 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cafDataLoader.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace caf +{ + +class ProgressInfo; +class PdmObject; + +//================================================================================================== +/// +//================================================================================================== +class DataLoadController : public caf::SignalObserver +{ +public: + static DataLoadController* instance(); + + DataLoadController( const DataLoadController& ) = delete; + DataLoadController& operator=( const DataLoadController& ) = delete; + + void registerDataLoader( const QString& objectType, const QString& dataType, std::shared_ptr dataLoader ); + + void loadData( caf::PdmObject& object, const QString& dateType, ProgressInfo& progressInfo ); + + void blockUntilDone( const QString& dataType ); + + void onTaskFinished( const caf::SignalEmitter* emitter, QString dataType, int taskId ); + +private: + DataLoadController(); + + std::map, std::shared_ptr> m_dataLoaders; + std::map m_pendingTasksByType; + int m_taskId; + + QMutex m_mutex; + QWaitCondition m_waitCondition; +}; + +} // end namespace caf diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.cpp b/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.cpp new file mode 100644 index 0000000000..8162b45ad9 --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.cpp @@ -0,0 +1,67 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#include "cafDataLoadTask.h" + +#include "cafDataLoader.h" +#include "cafPdmObject.h" + +using namespace caf; + +DataLoadTask::DataLoadTask( DataLoadController& controller, + DataLoader& loader, + caf::PdmObject& object, + const QString& dataType, + int taskId, + ProgressInfo& progressInfo ) + : QRunnable() + , m_dataLoadController( controller ) + , m_loader( loader ) + , m_object( object ) + , m_dataType( dataType ) + , m_taskId( taskId ) + , m_progressInfo( progressInfo ) +{ +} + +DataLoadTask::~DataLoadTask() +{ +} + +void DataLoadTask::run() +{ + m_loader.loadData( m_object, m_dataType, m_taskId, m_progressInfo ); +} diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.h b/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.h new file mode 100644 index 0000000000..0e13816dbd --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoadTask.h @@ -0,0 +1,75 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cafDataLoadController.h" +#include "cafDataLoader.h" + +#include +#include + +namespace caf +{ + +class ProgressInfo; +class PdmObject; +class DataLoadController; + +class DataLoadTask : public QRunnable +{ +public: + DataLoadTask( DataLoadController& controller, + DataLoader& loader, + caf::PdmObject& object, + const QString& dataType, + int taskId, + ProgressInfo& progressInfo ); + + ~DataLoadTask() override; + + void run() override; + +private: + DataLoadController& m_dataLoadController; + DataLoader& m_loader; + caf::PdmObject& m_object; + QString m_dataType; + int m_taskId; + ProgressInfo& m_progressInfo; +}; + +} // end namespace caf diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoader.cpp b/Fwk/AppFwk/cafDataLoader/cafDataLoader.cpp new file mode 100644 index 0000000000..0f05a0d850 --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoader.cpp @@ -0,0 +1,47 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#include "cafDataLoader.h" + +using namespace caf; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +DataLoader::DataLoader() + : taskDone( this ) +{ +} diff --git a/Fwk/AppFwk/cafDataLoader/cafDataLoader.h b/Fwk/AppFwk/cafDataLoader/cafDataLoader.h new file mode 100644 index 0000000000..737d426f01 --- /dev/null +++ b/Fwk/AppFwk/cafDataLoader/cafDataLoader.h @@ -0,0 +1,65 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron AS +// +// This library may be used under the terms of either the GNU General Public License or +// the GNU Lesser General Public License as follows: +// +// GNU General Public License Usage +// This library 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. +// +// This library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at <> +// for more details. +// +// GNU Lesser General Public License Usage +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 Lesser General Public License at <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include + +#include + +#include "cafSignal.h" + +namespace caf +{ +class ProgressInfo; +class PdmObject; + +//================================================================================================== +/// +//================================================================================================== +class DataLoader : public SignalEmitter +{ +public: + DataLoader(); + + virtual void loadData( PdmObject& pdmObject, const QString& dataType, int taskId, ProgressInfo& progressInfo ) = 0; + + virtual bool isRunnable() const = 0; + + caf::Signal taskDone; +}; + +} // end namespace caf diff --git a/Fwk/CMakeLists.txt b/Fwk/CMakeLists.txt index 14cf32a91e..bb17d9c9ea 100644 --- a/Fwk/CMakeLists.txt +++ b/Fwk/CMakeLists.txt @@ -58,6 +58,7 @@ add_subdirectory(AppFwk/cafCommand) add_subdirectory(AppFwk/cafCommandFeatures) add_subdirectory(AppFwk/cafUserInterface) add_subdirectory(AppFwk/cafPdmScripting) +add_subdirectory(AppFwk/cafDataLoader) # Unit Tests add_subdirectory(AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests)