|
|
|
|
|
#include "nmWxPebiResultViewWidget.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
#include "nmPebiResultSceneController.h"
|
|
|
|
|
|
#include "nmPebiResultSnapshot.h"
|
|
|
|
|
|
#include "nmVTKViewCommandController.h"
|
|
|
|
|
|
#include "nmWxPebiResultControlBar.h"
|
|
|
|
|
|
#include "nmWxVTKRenderContainerWidget.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QAction>
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
|
#include <QIcon>
|
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
|
#include <QMenu>
|
|
|
|
|
|
#include <QSize>
|
|
|
|
|
|
#include <QSizePolicy>
|
|
|
|
|
|
#include <QThread>
|
|
|
|
|
|
#include <QToolBar>
|
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
QString resultViewIconPath(const QString& sFileName)
|
|
|
|
|
|
{
|
|
|
|
|
|
const QString sApplicationDir = QCoreApplication::applicationDirPath();
|
|
|
|
|
|
return sApplicationDir.section('/', 0, -2) +
|
|
|
|
|
|
"/Res/Icon/" + sFileName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool isResultViewGuiThread()
|
|
|
|
|
|
{
|
|
|
|
|
|
QCoreApplication* pApplication = QCoreApplication::instance();
|
|
|
|
|
|
return pApplication == nullptr ||
|
|
|
|
|
|
pApplication->thread() == QThread::currentThread();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setActionCheckedWithoutSignal(QAction* pAction, bool bChecked)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pAction == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const bool bBlocked = pAction->blockSignals(true);
|
|
|
|
|
|
pAction->setChecked(bChecked);
|
|
|
|
|
|
pAction->blockSignals(bBlocked);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWxPebiResultViewWidget::nmWxPebiResultViewWidget(
|
|
|
|
|
|
nmDataAnalyzeManager* pDataManager,
|
|
|
|
|
|
QWidget* pParent)
|
|
|
|
|
|
: QWidget(pParent),
|
|
|
|
|
|
m_pRenderContainer(nullptr),
|
|
|
|
|
|
m_pSceneController(nullptr),
|
|
|
|
|
|
m_pControlBar(nullptr),
|
|
|
|
|
|
m_pToolBar(nullptr),
|
|
|
|
|
|
m_pStatusLabel(nullptr),
|
|
|
|
|
|
m_pScalarBarAction(nullptr),
|
|
|
|
|
|
m_pScaleGridAction(nullptr),
|
|
|
|
|
|
m_pCellEdgesAction(nullptr),
|
|
|
|
|
|
m_pWellMarkersAction(nullptr),
|
|
|
|
|
|
m_pWellNamesAction(nullptr),
|
|
|
|
|
|
m_bObservedSnapshotCurrent(false),
|
|
|
|
|
|
m_bObservedStateValid(false),
|
|
|
|
|
|
m_bSynchronizing(false),
|
|
|
|
|
|
m_bSyncPending(false)
|
|
|
|
|
|
{
|
|
|
|
|
|
createUi();
|
|
|
|
|
|
setDataManager(pDataManager);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWxPebiResultViewWidget::~nmWxPebiResultViewWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
disconnectDataManager();
|
|
|
|
|
|
if(m_pControlBar != nullptr) {
|
|
|
|
|
|
m_pControlBar->stopPlayback();
|
|
|
|
|
|
delete m_pControlBar;
|
|
|
|
|
|
m_pControlBar = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pSceneController != nullptr) {
|
|
|
|
|
|
m_pSceneController->clear();
|
|
|
|
|
|
delete m_pSceneController;
|
|
|
|
|
|
m_pSceneController = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 渲染容器、工具栏、状态栏和 QAction 最后由 QWidget 对象树统一释放。
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::setDataManager(
|
|
|
|
|
|
nmDataAnalyzeManager* pDataManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_ASSERT(isResultViewGuiThread());
|
|
|
|
|
|
Q_ASSERT(pDataManager == nullptr ||
|
|
|
|
|
|
pDataManager->thread() == QThread::currentThread());
|
|
|
|
|
|
if(!isResultViewGuiThread() ||
|
|
|
|
|
|
(pDataManager != nullptr &&
|
|
|
|
|
|
pDataManager->thread() != QThread::currentThread())) {
|
|
|
|
|
|
// 窗口会同步读取不可变快照引用,不能跨线程直接访问 Manager。
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pDataManager.data() == pDataManager) {
|
|
|
|
|
|
// 生产入口可能重复安装同一 Manager;这里只读最新状态,不能清空相机。
|
|
|
|
|
|
synchronizeFromDataManager();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
disconnectDataManager();
|
|
|
|
|
|
clearSceneAndControls(tr("No result data."));
|
|
|
|
|
|
m_pDataManager = pDataManager;
|
|
|
|
|
|
if(!m_pDataManager.isNull()) {
|
|
|
|
|
|
connect(m_pDataManager.data(), SIGNAL(sigPebiResultStateChanged()),
|
|
|
|
|
|
this, SLOT(onPebiResultStateChanged()));
|
|
|
|
|
|
connect(m_pDataManager.data(), SIGNAL(destroyed(QObject*)),
|
|
|
|
|
|
this, SLOT(onDataManagerDestroyed(QObject*)));
|
|
|
|
|
|
}
|
|
|
|
|
|
synchronizeFromDataManager();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAnalyzeManager* nmWxPebiResultViewWidget::getDataManager() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pDataManager.data();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::synchronizeFromDataManager()
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_ASSERT(isResultViewGuiThread());
|
|
|
|
|
|
Q_ASSERT(m_pDataManager.isNull() ||
|
|
|
|
|
|
m_pDataManager->thread() == QThread::currentThread());
|
|
|
|
|
|
if(!isResultViewGuiThread() ||
|
|
|
|
|
|
(!m_pDataManager.isNull() &&
|
|
|
|
|
|
m_pDataManager->thread() != QThread::currentThread())) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_bSynchronizing) {
|
|
|
|
|
|
// 同步期间只记录一次待处理请求,当前事务结束后重新读取 Manager 最新值。
|
|
|
|
|
|
m_bSyncPending = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_bSynchronizing = true;
|
|
|
|
|
|
do {
|
|
|
|
|
|
m_bSyncPending = false;
|
|
|
|
|
|
synchronizeOnce();
|
|
|
|
|
|
} while(m_bSyncPending);
|
|
|
|
|
|
m_bSynchronizing = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onPebiResultStateChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
synchronizeFromDataManager();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onDataManagerDestroyed(QObject* pObject)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(pObject);
|
|
|
|
|
|
// destroyed() 到达时 QPointer 可能已经清空,槽内绝不再读取 Manager。
|
|
|
|
|
|
m_pDataManager = nullptr;
|
|
|
|
|
|
if(m_bSynchronizing) {
|
|
|
|
|
|
// 极端嵌套事件下不得在快照提交栈内递归清场,退出当前事务后再读空状态。
|
|
|
|
|
|
m_bSyncPending = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
clearSceneAndControls(tr("No result data."));
|
|
|
|
|
|
// 记录稳定空状态,后续重复同步空 Manager 时不再清场或切换状态页。
|
|
|
|
|
|
rememberObservedState(
|
|
|
|
|
|
QSharedPointer<const nmPebiResultSnapshot>(),
|
|
|
|
|
|
QString(), false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::appendContextMenuActions(QMenu* pMenu)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pMenu == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
pMenu->addAction(m_pScalarBarAction);
|
|
|
|
|
|
pMenu->addAction(m_pScaleGridAction);
|
|
|
|
|
|
pMenu->addAction(m_pCellEdgesAction);
|
|
|
|
|
|
pMenu->addAction(m_pWellMarkersAction);
|
|
|
|
|
|
pMenu->addAction(m_pWellNamesAction);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onControlOperationFailed(
|
|
|
|
|
|
const QString& sError)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 高优先级状态存在时丢弃普通错误,避免其在过期提示解除后突然出现。
|
|
|
|
|
|
if(!m_sBindingError.isEmpty() ||
|
|
|
|
|
|
(m_bObservedStateValid && !m_bObservedSnapshotCurrent)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_sOperationError = sError;
|
|
|
|
|
|
refreshStatusBar();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onControlOperationSucceeded()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_sOperationError.isEmpty()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 这里只清除最低优先级的普通操作错误;刷新函数仍优先显示绑定失败和过期。
|
|
|
|
|
|
m_sOperationError.clear();
|
|
|
|
|
|
refreshStatusBar();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onScalarBarToggled(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pSceneController->setScalarBarVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onScaleGridToggled(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pSceneController->setScaleGridVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onCellEdgesToggled(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pSceneController->setCellEdgesVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onWellMarkersToggled(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pSceneController->setWellMarkersVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::onWellNamesToggled(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pSceneController->setWellNamesVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::createUi()
|
|
|
|
|
|
{
|
|
|
|
|
|
QVBoxLayout* pMainLayout = new QVBoxLayout(this);
|
|
|
|
|
|
pMainLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
pMainLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
QWidget* pRenderArea = new QWidget(this);
|
|
|
|
|
|
QHBoxLayout* pRenderLayout = new QHBoxLayout(pRenderArea);
|
|
|
|
|
|
pRenderLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
pRenderLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
|
|
// 通用容器是本窗口唯一创建 QVTKWidget、Renderer 和 RenderWindow 的对象。
|
|
|
|
|
|
m_pRenderContainer = new nmWxVTKRenderContainerWidget(pRenderArea);
|
|
|
|
|
|
m_pRenderContainer->setSizePolicy(
|
|
|
|
|
|
QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
|
|
|
|
m_pRenderContainer->setViewCommandCapabilities(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_ZoomIn |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_ZoomOut |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Fit |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Top |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Front |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_SetRotationCenter |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_SaveImage |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_CopyImage |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Print |
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_PrintPreview);
|
|
|
|
|
|
m_pSceneController = new nmPebiResultSceneController(m_pRenderContainer);
|
|
|
|
|
|
|
|
|
|
|
|
m_pToolBar = new QToolBar(pRenderArea);
|
|
|
|
|
|
m_pToolBar->setOrientation(Qt::Vertical);
|
|
|
|
|
|
m_pToolBar->setMovable(false);
|
|
|
|
|
|
m_pToolBar->setFloatable(false);
|
|
|
|
|
|
m_pToolBar->setIconSize(QSize(32, 32));
|
|
|
|
|
|
m_pToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
|
|
|
|
|
m_pToolBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
|
|
|
|
|
|
|
|
|
|
|
m_pScalarBarAction = new QAction(
|
|
|
|
|
|
QIcon(resultViewIconPath("NmColorScale.png")),
|
|
|
|
|
|
tr("Color Scale"), this);
|
|
|
|
|
|
m_pScaleGridAction = new QAction(
|
|
|
|
|
|
QIcon(resultViewIconPath("NmScaleGrid.png")),
|
|
|
|
|
|
tr("Scale Grid"), this);
|
|
|
|
|
|
m_pCellEdgesAction = new QAction(
|
|
|
|
|
|
QIcon(resultViewIconPath("SpecialLineVisible.png")),
|
|
|
|
|
|
tr("Cell Edges"), this);
|
|
|
|
|
|
m_pWellMarkersAction = new QAction(
|
|
|
|
|
|
QIcon(resultViewIconPath("NmWell.png")),
|
|
|
|
|
|
tr("Well Markers"), this);
|
|
|
|
|
|
m_pWellNamesAction = new QAction(
|
|
|
|
|
|
QIcon(resultViewIconPath("NmShow.png")),
|
|
|
|
|
|
tr("Well Names"), this);
|
|
|
|
|
|
|
|
|
|
|
|
QAction* const pBusinessActions[] = {
|
|
|
|
|
|
m_pScalarBarAction, m_pScaleGridAction, m_pCellEdgesAction,
|
|
|
|
|
|
m_pWellMarkersAction, m_pWellNamesAction
|
|
|
|
|
|
};
|
|
|
|
|
|
for(int nIndex = 0; nIndex < 5; ++nIndex) {
|
|
|
|
|
|
pBusinessActions[nIndex]->setCheckable(true);
|
|
|
|
|
|
pBusinessActions[nIndex]->setToolTip(
|
|
|
|
|
|
pBusinessActions[nIndex]->text());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmVTKViewCommandController* pCommandController =
|
|
|
|
|
|
m_pRenderContainer->getViewCommandController();
|
|
|
|
|
|
if(pCommandController != nullptr) {
|
|
|
|
|
|
QAction* pZoomOutAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_ZoomOut);
|
|
|
|
|
|
QAction* pFitAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Fit);
|
|
|
|
|
|
QAction* pZoomInAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_ZoomIn);
|
|
|
|
|
|
QAction* pTopAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Top);
|
|
|
|
|
|
QAction* pFrontAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_Front);
|
|
|
|
|
|
QAction* pPickCenterAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_SetRotationCenter);
|
|
|
|
|
|
QAction* pCopyAction = pCommandController->getAction(
|
|
|
|
|
|
nmVTKViewCommandController::ViewCommand_CopyImage);
|
|
|
|
|
|
|
|
|
|
|
|
if(pZoomOutAction != nullptr) m_pToolBar->addAction(pZoomOutAction);
|
|
|
|
|
|
if(pFitAction != nullptr) m_pToolBar->addAction(pFitAction);
|
|
|
|
|
|
if(pZoomInAction != nullptr) m_pToolBar->addAction(pZoomInAction);
|
|
|
|
|
|
m_pToolBar->addSeparator();
|
|
|
|
|
|
if(pTopAction != nullptr) m_pToolBar->addAction(pTopAction);
|
|
|
|
|
|
if(pFrontAction != nullptr) m_pToolBar->addAction(pFrontAction);
|
|
|
|
|
|
if(pPickCenterAction != nullptr) m_pToolBar->addAction(pPickCenterAction);
|
|
|
|
|
|
m_pToolBar->addSeparator();
|
|
|
|
|
|
for(int nIndex = 0; nIndex < 5; ++nIndex) {
|
|
|
|
|
|
m_pToolBar->addAction(pBusinessActions[nIndex]);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pToolBar->addSeparator();
|
|
|
|
|
|
if(pCopyAction != nullptr) m_pToolBar->addAction(pCopyAction);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
connect(m_pScalarBarAction, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onScalarBarToggled(bool)));
|
|
|
|
|
|
connect(m_pScaleGridAction, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onScaleGridToggled(bool)));
|
|
|
|
|
|
connect(m_pCellEdgesAction, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onCellEdgesToggled(bool)));
|
|
|
|
|
|
connect(m_pWellMarkersAction, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onWellMarkersToggled(bool)));
|
|
|
|
|
|
connect(m_pWellNamesAction, SIGNAL(toggled(bool)),
|
|
|
|
|
|
this, SLOT(onWellNamesToggled(bool)));
|
|
|
|
|
|
connect(m_pRenderContainer, SIGNAL(contextMenuAboutToShow(QMenu*)),
|
|
|
|
|
|
this, SLOT(appendContextMenuActions(QMenu*)));
|
|
|
|
|
|
|
|
|
|
|
|
pRenderLayout->addWidget(m_pRenderContainer, 1);
|
|
|
|
|
|
pRenderLayout->addWidget(m_pToolBar);
|
|
|
|
|
|
pMainLayout->addWidget(pRenderArea, 1);
|
|
|
|
|
|
|
|
|
|
|
|
m_pStatusLabel = new QLabel(this);
|
|
|
|
|
|
m_pStatusLabel->setWordWrap(true);
|
|
|
|
|
|
m_pStatusLabel->setContentsMargins(8, 4, 8, 4);
|
|
|
|
|
|
m_pStatusLabel->hide();
|
|
|
|
|
|
pMainLayout->addWidget(m_pStatusLabel);
|
|
|
|
|
|
|
|
|
|
|
|
m_pControlBar = new nmWxPebiResultControlBar(
|
|
|
|
|
|
m_pSceneController, this);
|
|
|
|
|
|
connect(m_pControlBar, SIGNAL(operationFailed(QString)),
|
|
|
|
|
|
this, SLOT(onControlOperationFailed(QString)));
|
|
|
|
|
|
connect(m_pControlBar, SIGNAL(operationSucceeded()),
|
|
|
|
|
|
this, SLOT(onControlOperationSucceeded()));
|
|
|
|
|
|
pMainLayout->addWidget(m_pControlBar);
|
|
|
|
|
|
|
|
|
|
|
|
synchronizeBusinessActions();
|
|
|
|
|
|
m_pRenderContainer->showEmptyState(tr("No result data."));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::synchronizeOnce()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pDataManager.isNull()) {
|
|
|
|
|
|
if(m_bObservedStateValid && m_pObservedSnapshot.isNull()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
clearSceneAndControls(tr("No result data."));
|
|
|
|
|
|
rememberObservedState(
|
|
|
|
|
|
QSharedPointer<const nmPebiResultSnapshot>(),
|
|
|
|
|
|
QString(), false);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const QSharedPointer<const nmPebiResultSnapshot> pSnapshot =
|
|
|
|
|
|
m_pDataManager->getPebiResultSnapshot();
|
|
|
|
|
|
const QString sSnapshotId = pSnapshot.isNull()
|
|
|
|
|
|
? QString() : pSnapshot->getSnapshotId();
|
|
|
|
|
|
const bool bCurrent = !pSnapshot.isNull() &&
|
|
|
|
|
|
m_pDataManager->isPebiResultSnapshotCurrent();
|
|
|
|
|
|
const bool bSameIdentity = m_bObservedStateValid &&
|
|
|
|
|
|
m_pObservedSnapshot.data() == pSnapshot.data() &&
|
|
|
|
|
|
m_sObservedSnapshotId == sSnapshotId;
|
|
|
|
|
|
const bool bSameState = bSameIdentity &&
|
|
|
|
|
|
m_bObservedSnapshotCurrent == bCurrent;
|
|
|
|
|
|
if(bSameState) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const bool bBecameStale = bSameIdentity &&
|
|
|
|
|
|
m_bObservedSnapshotCurrent && !bCurrent;
|
|
|
|
|
|
m_sOperationError.clear();
|
|
|
|
|
|
|
|
|
|
|
|
if(pSnapshot.isNull()) {
|
|
|
|
|
|
clearSceneAndControls(tr("No result data."));
|
|
|
|
|
|
rememberObservedState(pSnapshot, sSnapshotId, false);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!bSameIdentity) {
|
|
|
|
|
|
// 候选提交前停止本窗口 Timer;失败时旧 Scene 和最后压力帧记忆仍保留。
|
|
|
|
|
|
m_pControlBar->stopPlayback();
|
|
|
|
|
|
QString sError;
|
|
|
|
|
|
const bool bBound = m_pSceneController->setSnapshot(
|
|
|
|
|
|
pSnapshot, &sError);
|
|
|
|
|
|
rememberObservedState(pSnapshot, sSnapshotId, bCurrent);
|
|
|
|
|
|
if(bBound) {
|
|
|
|
|
|
m_pDisplayedSnapshot = pSnapshot;
|
|
|
|
|
|
m_sDisplayedSnapshotId = sSnapshotId;
|
|
|
|
|
|
m_sBindingError.clear();
|
|
|
|
|
|
// 新成功绑定序号会让 Playback 和 ControlBar 同时重置各自缓存。
|
|
|
|
|
|
m_pControlBar->synchronizeFromScene();
|
|
|
|
|
|
synchronizeBusinessActions();
|
|
|
|
|
|
refreshStatusBar();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_sBindingError = sError.isEmpty()
|
|
|
|
|
|
? tr("Unable to display the latest result.")
|
|
|
|
|
|
: tr("Unable to display the latest result: %1").arg(sError);
|
|
|
|
|
|
if(!m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
m_pDisplayedSnapshot.clear();
|
|
|
|
|
|
m_sDisplayedSnapshotId.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pControlBar->synchronizeFromScene();
|
|
|
|
|
|
synchronizeBusinessActions();
|
|
|
|
|
|
if(m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
// 旧画面保持 Ready;这里只显示红色非阻塞提示,不能追加 Render。
|
|
|
|
|
|
refreshStatusBar();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
m_pStatusLabel->hide();
|
|
|
|
|
|
m_pRenderContainer->showErrorState(m_sBindingError);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rememberObservedState(pSnapshot, sSnapshotId, bCurrent);
|
|
|
|
|
|
if(bBecameStale) {
|
|
|
|
|
|
// 只在“当前 -> 过期”的边沿暂停一次;用户之后可以手动重新播放旧结果。
|
|
|
|
|
|
m_pControlBar->stopPlayback();
|
|
|
|
|
|
}
|
|
|
|
|
|
refreshStatusBar();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::clearSceneAndControls(
|
|
|
|
|
|
const QString& sEmptyMessage)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pControlBar != nullptr) {
|
|
|
|
|
|
m_pControlBar->stopPlayback();
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pSceneController != nullptr) {
|
|
|
|
|
|
m_pSceneController->clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pObservedSnapshot.clear();
|
|
|
|
|
|
m_sObservedSnapshotId.clear();
|
|
|
|
|
|
m_bObservedSnapshotCurrent = false;
|
|
|
|
|
|
m_bObservedStateValid = false;
|
|
|
|
|
|
m_pDisplayedSnapshot.clear();
|
|
|
|
|
|
m_sDisplayedSnapshotId.clear();
|
|
|
|
|
|
m_sBindingError.clear();
|
|
|
|
|
|
m_sOperationError.clear();
|
|
|
|
|
|
if(m_pControlBar != nullptr) {
|
|
|
|
|
|
m_pControlBar->synchronizeFromScene();
|
|
|
|
|
|
}
|
|
|
|
|
|
synchronizeBusinessActions();
|
|
|
|
|
|
if(m_pStatusLabel != nullptr) {
|
|
|
|
|
|
m_pStatusLabel->hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pRenderContainer != nullptr) {
|
|
|
|
|
|
m_pRenderContainer->showEmptyState(sEmptyMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::rememberObservedState(
|
|
|
|
|
|
const QSharedPointer<const nmPebiResultSnapshot>& pSnapshot,
|
|
|
|
|
|
const QString& sSnapshotId,
|
|
|
|
|
|
bool bCurrent)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pObservedSnapshot = pSnapshot;
|
|
|
|
|
|
m_sObservedSnapshotId = sSnapshotId;
|
|
|
|
|
|
m_bObservedSnapshotCurrent = bCurrent;
|
|
|
|
|
|
m_bObservedStateValid = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::synchronizeBusinessActions()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pSceneController == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setActionCheckedWithoutSignal(
|
|
|
|
|
|
m_pScalarBarAction, m_pSceneController->isScalarBarVisible());
|
|
|
|
|
|
setActionCheckedWithoutSignal(
|
|
|
|
|
|
m_pScaleGridAction, m_pSceneController->isScaleGridVisible());
|
|
|
|
|
|
setActionCheckedWithoutSignal(
|
|
|
|
|
|
m_pCellEdgesAction, m_pSceneController->areCellEdgesVisible());
|
|
|
|
|
|
setActionCheckedWithoutSignal(
|
|
|
|
|
|
m_pWellMarkersAction, m_pSceneController->areWellMarkersVisible());
|
|
|
|
|
|
setActionCheckedWithoutSignal(
|
|
|
|
|
|
m_pWellNamesAction, m_pSceneController->areWellNamesVisible());
|
|
|
|
|
|
|
|
|
|
|
|
const bool bEnabled = m_pSceneController->hasSnapshot();
|
|
|
|
|
|
m_pScalarBarAction->setEnabled(bEnabled);
|
|
|
|
|
|
m_pScaleGridAction->setEnabled(bEnabled);
|
|
|
|
|
|
m_pCellEdgesAction->setEnabled(bEnabled);
|
|
|
|
|
|
m_pWellMarkersAction->setEnabled(bEnabled);
|
|
|
|
|
|
m_pWellNamesAction->setEnabled(bEnabled);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::refreshStatusBar()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pStatusLabel == nullptr || m_pSceneController == nullptr ||
|
|
|
|
|
|
!m_pSceneController->hasSnapshot()) {
|
|
|
|
|
|
if(m_pStatusLabel != nullptr) {
|
|
|
|
|
|
m_pStatusLabel->hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!m_sBindingError.isEmpty()) {
|
|
|
|
|
|
m_pStatusLabel->setStyleSheet(
|
|
|
|
|
|
"QLabel { color: #a32626; background: #fdecec; } ");
|
|
|
|
|
|
m_pStatusLabel->setText(m_sBindingError);
|
|
|
|
|
|
m_pStatusLabel->show();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_bObservedStateValid && !m_bObservedSnapshotCurrent) {
|
|
|
|
|
|
m_pStatusLabel->setStyleSheet(
|
|
|
|
|
|
"QLabel { color: #6b5200; background: #fff4bf; } ");
|
|
|
|
|
|
m_pStatusLabel->setText(tr(
|
|
|
|
|
|
"Current inputs have changed. Showing the last successful result."));
|
|
|
|
|
|
m_pStatusLabel->show();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(!m_sOperationError.isEmpty()) {
|
|
|
|
|
|
m_pStatusLabel->setStyleSheet(
|
|
|
|
|
|
"QLabel { color: #a32626; background: #fdecec; } ");
|
|
|
|
|
|
m_pStatusLabel->setText(m_sOperationError);
|
|
|
|
|
|
m_pStatusLabel->show();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pStatusLabel->hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmWxPebiResultViewWidget::disconnectDataManager()
|
|
|
|
|
|
{
|
|
|
|
|
|
nmDataAnalyzeManager* pDataManager = m_pDataManager.data();
|
|
|
|
|
|
if(pDataManager != nullptr) {
|
|
|
|
|
|
disconnect(pDataManager, SIGNAL(sigPebiResultStateChanged()),
|
|
|
|
|
|
this, SLOT(onPebiResultStateChanged()));
|
|
|
|
|
|
disconnect(pDataManager, SIGNAL(destroyed(QObject*)),
|
|
|
|
|
|
this, SLOT(onDataManagerDestroyed(QObject*)));
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pDataManager = nullptr;
|
|
|
|
|
|
}
|