diff --git a/Modules/Core/Common/include/otbUtils.h b/Modules/Core/Common/include/otbUtils.h index da2ecc286ed4abf8e175a700b69f9e14a8483fb4..ec8ed5475928066f74af913491931433b1a4d6da 100644 --- a/Modules/Core/Common/include/otbUtils.h +++ b/Modules/Core/Common/include/otbUtils.h @@ -51,6 +51,9 @@ namespace Utils /** Function that prints nothing (useful to disable libsvm logs)*/ void OTBCommon_EXPORT PrintNothing(const char *s); + extern OTBCommon_EXPORT bool const TrueConstant; + + extern OTBCommon_EXPORT bool const FalseConstant; } } // namespace otb diff --git a/Modules/Core/Common/src/otbUtils.cxx b/Modules/Core/Common/src/otbUtils.cxx index f837789ba6ee406bb6739f527dc2ef103f780f9a..7bdf9edb7121801353360e316d8c15ac4836fe6b 100644 --- a/Modules/Core/Common/src/otbUtils.cxx +++ b/Modules/Core/Common/src/otbUtils.cxx @@ -41,6 +41,10 @@ void PrintNothing(const char * /* s */) { } +bool const TrueConstant = true; + +bool const FalseConstant = false; + } } diff --git a/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.h b/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.h index 998ba4c287f98991973e8c15d96448124ad21058..29fafc6bf528190377325ff63be8fb2e5b67664b 100644 --- a/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.h +++ b/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.h @@ -24,6 +24,7 @@ #include "itkMacro.h" #include "itkImageToImageFilter.h" #include "otbStreamingManager.h" +#include "itkFastMutexLock.h" namespace otb { @@ -142,6 +143,11 @@ public: * This filter does not produce an output */ void Update() override; + /** This override doesn't return a const ref on the actual boolean */ + const bool & GetAbortGenerateData() const override; + + void SetAbortGenerateData(const bool val) override; + protected: StreamingImageVirtualWriter(); @@ -186,6 +192,9 @@ private: bool m_IsObserving; unsigned long m_ObserverID; + + /** Lock to ensure thread-safety (added for the AbortGenerateData flag) */ + itk::SimpleFastMutexLock m_Lock; }; } // end namespace otb diff --git a/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.txx b/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.txx index 008b6c0eaafe7d39dfc3febf6889be7471d1cf0c..ec0ae5ae6d760b11ca6238deb582174752bb7f21 100644 --- a/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.txx +++ b/Modules/Core/Streaming/include/otbStreamingImageVirtualWriter.txx @@ -32,6 +32,7 @@ #include "otbTileDimensionTiledStreamingManager.h" #include "otbRAMDrivenTiledStreamingManager.h" #include "otbRAMDrivenAdaptativeStreamingManager.h" +#include "otbUtils.h" namespace otb { @@ -258,6 +259,13 @@ StreamingImageVirtualWriter<TInputImage> { this->UpdateProgress(1.0); } + else + { + itk::ProcessAborted e(__FILE__, __LINE__); + e.SetLocation(ITK_LOCATION); + e.SetDescription("Image streaming has been aborted"); + throw e; + } // Notify end event observers this->InvokeEvent(itk::EndEvent()); @@ -285,6 +293,27 @@ StreamingImageVirtualWriter<TInputImage> this->ReleaseInputs(); } +template <class TInputImage> +const bool & +StreamingImageVirtualWriter<TInputImage> +::GetAbortGenerateData() const +{ + m_Lock.Lock(); + bool ret = Superclass::GetAbortGenerateData(); + m_Lock.Unlock(); + if (ret) return otb::Utils::TrueConstant; + return otb::Utils::FalseConstant; +} + +template <class TInputImage> +void +StreamingImageVirtualWriter<TInputImage> +::SetAbortGenerateData(bool val) +{ + m_Lock.Lock(); + Superclass::SetAbortGenerateData(val); + m_Lock.Unlock(); +} } // end namespace otb diff --git a/Modules/IO/ImageIO/include/otbImageFileWriter.h b/Modules/IO/ImageIO/include/otbImageFileWriter.h index 2851c8b03d3372f6353bba967aeaf0f99a1c9ba5..cbc4c6c4e9a7fb49c3cdfe8821fec27ca84ea189 100644 --- a/Modules/IO/ImageIO/include/otbImageFileWriter.h +++ b/Modules/IO/ImageIO/include/otbImageFileWriter.h @@ -25,6 +25,7 @@ #include "itkProcessObject.h" #include "otbStreamingManager.h" #include "otbExtendedFilenameToWriterOptions.h" +#include "itkFastMutexLock.h" namespace otb { @@ -199,6 +200,11 @@ public: itkGetObjectMacro(ImageIO, otb::ImageIOBase); itkGetConstObjectMacro(ImageIO, otb::ImageIOBase); + /** This override doesn't return a const ref on the actual boolean */ + const bool & GetAbortGenerateData() const override; + + void SetAbortGenerateData(const bool val) override; + protected: ImageFileWriter(); ~ImageFileWriter() override; @@ -270,6 +276,9 @@ private: * This variable can be the number of components in m_ImageIO or the * number of components in the m_BandList (if used) */ unsigned int m_IOComponents; + + /** Lock to ensure thread-safety (added for the AbortGenerateData flag) */ + itk::SimpleFastMutexLock m_Lock; }; } // end namespace otb diff --git a/Modules/IO/ImageIO/include/otbImageFileWriter.txx b/Modules/IO/ImageIO/include/otbImageFileWriter.txx index 677ea22b4bab59d04121735bd58990ca0b516ec4..2ddaf018bf89a48109c86a902d2c6fa57c88089b 100644 --- a/Modules/IO/ImageIO/include/otbImageFileWriter.txx +++ b/Modules/IO/ImageIO/include/otbImageFileWriter.txx @@ -48,6 +48,7 @@ #include "otb_boost_tokenizer_header.h" #include "otbStringUtils.h" +#include "otbUtils.h" namespace otb { @@ -645,6 +646,13 @@ ImageFileWriter<TInputImage> { this->UpdateProgress(1.0); } + else + { + itk::ProcessAborted e(__FILE__, __LINE__); + e.SetLocation(ITK_LOCATION); + e.SetDescription("Image writing has been aborted"); + throw e; + } // Notify end event observers this->InvokeEvent(itk::EndEvent()); @@ -833,6 +841,29 @@ ImageFileWriter<TInputImage> return this->m_FilenameHelper->GetSimpleFileName(); } +template <class TInputImage> +const bool & +ImageFileWriter<TInputImage> +::GetAbortGenerateData() const +{ + m_Lock.Lock(); + // protected read here + bool ret = Superclass::GetAbortGenerateData(); + m_Lock.Unlock(); + if (ret) return otb::Utils::TrueConstant; + return otb::Utils::FalseConstant; +} + +template <class TInputImage> +void +ImageFileWriter<TInputImage> +::SetAbortGenerateData(bool val) +{ + m_Lock.Lock(); + Superclass::SetAbortGenerateData(val); + m_Lock.Unlock(); +} + } // end namespace otb #endif diff --git a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h index f008e22bbb46c34eb77b2c8fafb464a68f5bb4dd..a7c413064a46a9afdd5f07ae2ca614ebc37b09d2 100644 --- a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h +++ b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.h @@ -31,6 +31,7 @@ #include "itkImageFileWriter.h" #include "itkObjectFactoryBase.h" +#include "itkFastMutexLock.h" #include "itkImageRegionMultidimensionalSplitter.h" #include "otbImageIOFactory.h" @@ -252,6 +253,11 @@ public: itkSetMacro(TiffTiledMode, bool); itkGetMacro(TiffTiledMode, bool); + /** This override doesn't return a const ref on the actual boolean */ + const bool & GetAbortGenerateData() const override; + + void SetAbortGenerateData(bool val) override; + protected: SimpleParallelTiffWriter(); virtual ~SimpleParallelTiffWriter(); @@ -325,6 +331,9 @@ private: bool m_Verbose; bool m_VirtualMode; bool m_TiffTiledMode; + + /** Lock to ensure thread-safety (added for the AbortGenerateData flag) */ + itk::SimpleFastMutexLock m_Lock; }; diff --git a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.txx b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.txx index 9a3790c872e8f11dc6f0dc65ef0c565e26794cde..4292ad0f8460c3811e541e25a793711f59caec43 100644 --- a/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.txx +++ b/Modules/MPI/MPITiffWriter/include/otbSimpleParallelTiffWriter.txx @@ -23,6 +23,7 @@ #include "otbSimpleParallelTiffWriter.h" #include "otbStopwatch.h" +#include "otbUtils.h" using std::vector; @@ -729,6 +730,16 @@ SimpleParallelTiffWriter<TInputImage> } } + // abort case + if (this->GetAbortGenerateData()) + { + itk::ProcessAborted e(__FILE__, __LINE__); + e.SetLocation(ITK_LOCATION); + e.SetDescription("Image writing has been aborted"); + throw e; + otb::MPIConfig::Instance()->abort(EXIT_FAILURE); + } + // Clean up close_raster(output_raster); output_raster = NULL; @@ -837,5 +848,27 @@ SimpleParallelTiffWriter<TInputImage> return this->m_FilenameHelper->GetSimpleFileName(); } +template <class TInputImage> +const bool & +SimpleParallelTiffWriter<TInputImage> +::GetAbortGenerateData() const +{ + m_Lock.Lock(); + bool ret = Superclass::GetAbortGenerateData(); + m_Lock.Unlock(); + if (ret) return otb::Utils::TrueConstant; + return otb::Utils::FalseConstant; +} + +template <class TInputImage> +void +SimpleParallelTiffWriter<TInputImage> +::SetAbortGenerateData(bool val) +{ + m_Lock.Lock(); + Superclass::SetAbortGenerateData(val); + m_Lock.Unlock(); +} + } #endif diff --git a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx index 6b1d92cf582d251cb2a3c6a7936f8842d73ee0a4..9420452e321f19bb13b9ba6521c5b79ae9415280 100644 --- a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx +++ b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx @@ -1431,11 +1431,11 @@ MainWindow if( !( *it )->IsClosable() ) { - assert( !( *it )->GetApplication().IsNull() ); + assert( ( *it )->GetModel()->GetApplication() ); // qDebug() << "OTB-application:" << ( *it )->GetApplication()->GetDocName(); - names.push_back( ( *it )->GetApplication()->GetDocName() ); + names.push_back( ( *it )->GetModel()->GetApplication()->GetDocName() ); } } diff --git a/Modules/Visualization/MonteverdiGui/include/mvdQtWidgetView.h b/Modules/Visualization/MonteverdiGui/include/mvdQtWidgetView.h index c55664e2dcbf8871e6510a930f564b1372afd8e9..08ead75886afef2b4b57f26e5359f1df37895dda 100644 --- a/Modules/Visualization/MonteverdiGui/include/mvdQtWidgetView.h +++ b/Modules/Visualization/MonteverdiGui/include/mvdQtWidgetView.h @@ -37,16 +37,10 @@ #include <QtGui> #include <QShortcut> -// -// System includes (sorted by alphabetic order) - -// -// ITK includes (sorted by alphabetic order) - // // OTB includes (sorted by alphabetic order) #ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829 //tag=QT4-boost-compatibility -#include "otbWrapperApplication.h" +#include "otbWrapperQtWidgetView.h" #include "otbWrapperQtWidgetModel.h" #endif //tag=QT4-boost-compatibility #include "OTBMonteverdiGUIExport.h" @@ -57,18 +51,8 @@ #include "mvdTypes.h" #endif //tag=QT4-boost-compatibility -/*****************************************************************************/ -/* PRE-DECLARATION SECTION */ - -// -// External classes pre-declaration. -namespace -{ -} - namespace mvd { - namespace Wrapper { @@ -84,16 +68,12 @@ namespace Wrapper */ class OTBMonteverdiGUI_EXPORT QtWidgetView : - public QWidget + public otb::Wrapper::QtWidgetView { /*-[ QOBJECT SECTION ]-----------------------------------------------------*/ Q_OBJECT - Q_PROPERTY( bool isClosable - READ IsClosable - WRITE SetClosable ); - /*-[ PUBLIC SECTION ]------------------------------------------------------*/ // @@ -112,29 +92,6 @@ public: /** \brief Destructor. */ ~QtWidgetView() override; - /** \brief Gui Creation. */ - void CreateGui(); - - /** \brief Model Accessor */ - inline otb::Wrapper::QtWidgetModel* GetModel() - { - return m_Model; - } - - /** - * \return The OTB-application pointer of this view. - */ - otb::Wrapper::Application::ConstPointer GetApplication() const - { - return otb::ConstCast< otb::Wrapper::Application >( - m_Application - ); - } - - /** - */ - inline bool IsClosable() const; - /*-[ PUBLIC SLOTS SECTION ]------------------------------------------------*/ // @@ -146,12 +103,9 @@ public slots: // // Signals. signals: - void QuitSignal(); void OTBApplicationOutputImageChanged( const QString &, const QString &); - void ExecuteAndWriteOutput(); - void ExecutionDone( int nbOutputs ); /*-[ PROTECTED SECTION ]---------------------------------------------------*/ @@ -160,14 +114,16 @@ signals: // Protected methods. protected: - // - // QWidget overloads. + QWidget* CreateInputWidgets() override; - void closeEvent( QCloseEvent * event ) override; +protected slots: -// -// Protected attributes. -protected: + /** extend the behaviour of base class OnExecButtonClicked */ + void OnExecButtonClicked(); + + /** modify the behaviour of base class OnExceptionRaised + */ + void OnExceptionRaised( QString what ); /*-[ PRIVATE SECTION ]-----------------------------------------------------*/ @@ -178,12 +134,6 @@ private: QtWidgetView(const QtWidgetView&); //purposely not implemented void operator=(const QtWidgetView&); //purposely not implemented - QWidget* CreateFooter(); - - QWidget* CreateInputWidgets(); - - QWidget* CreateDoc(); - /** */ void SetupParameterWidgets( QWidget* widget ); @@ -192,21 +142,6 @@ private: */ void SetupFileSelectionWidget( QWidget * ); -// -// Private attributes. - -private: - - otb::Wrapper::Application::Pointer m_Application; - otb::Wrapper::QtWidgetModel* m_Model; - - QPushButton* m_ExecButton; - QPushButton* m_QuitButton; - QShortcut* m_QuitShortcut; - QLabel* m_Message; - - bool m_IsClosable : 1; - /*-[ PRIVATE SLOTS SECTION ]-----------------------------------------------*/ // @@ -218,30 +153,6 @@ private slots: // image filename{s} set by the user in this OTB application (if any). void OnApplicationExecutionDone( int ); - void UpdateMessageAfterApplicationReady(bool val); - - void UpdateMessageAfterExecution(int status); - - /** - */ - void OnExecButtonClicked(); - - /** - */ - inline void OnProgressReportBegin(); - - /** - */ - inline void OnProgressReportEnd( int status ); - - /** - */ - void OnExceptionRaised( QString what ); - - /** - */ - inline void SetClosable( bool ); - /** */ inline void OnFileSelectionWidgetAdded0( QWidget * ); @@ -264,47 +175,6 @@ namespace mvd namespace Wrapper { -/*****************************************************************************/ -inline -bool -QtWidgetView -::IsClosable() const -{ - return m_IsClosable; -} - -/*****************************************************************************/ -inline -void -QtWidgetView -::SetClosable( bool enabled ) -{ - m_IsClosable = enabled; - - setEnabled( true ); - - if( m_QuitButton!=NULL ) - m_QuitButton->setEnabled( m_IsClosable ); -} - -/*******************************************************************************/ -inline -void -QtWidgetView -::OnProgressReportBegin() -{ - SetClosable( false ); -} - -/*******************************************************************************/ -inline -void -QtWidgetView -::OnProgressReportEnd( int ) -{ - SetClosable( true ); -} - /*******************************************************************************/ inline void diff --git a/Modules/Visualization/MonteverdiGui/src/mvdApplicationLauncher.cxx b/Modules/Visualization/MonteverdiGui/src/mvdApplicationLauncher.cxx index 7d571ff73bccdfba11819ccd01eafeb6e258439d..b3a28a432f839bb8e67921f440449a9ff9bee71e 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdApplicationLauncher.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdApplicationLauncher.cxx @@ -217,13 +217,13 @@ ApplicationLauncher ApplicationLauncher::NewOtbApplicationWidget( appName, isStandalone ); assert( appWidget!=NULL ); - assert( appWidget->GetApplication() ); + assert( appWidget->GetModel()->GetApplication() ); QMainWindow * mainWindow = new QMainWindow( p, flags ); mainWindow->setWindowTitle( QString( "%1 (OTB-" OTB_VERSION_STRING ")" ) - .arg( appWidget->GetApplication()->GetDocName() ) + .arg( appWidget->GetModel()->GetApplication()->GetDocName() ) ); mainWindow->setWindowIcon( QIcon( ":/otb_small.png" ) ); @@ -251,11 +251,11 @@ ApplicationLauncher ); assert( appWidget!=NULL ); - assert( appWidget->GetApplication() ); + assert( appWidget->GetModel()->GetApplication() ); appWidget->setWindowTitle( QString( "%1 (OTB-" OTB_VERSION_STRING ")" ) - .arg( appWidget->GetApplication()->GetDocName() ) + .arg( appWidget->GetModel()->GetApplication()->GetDocName() ) ); appWidget->setWindowIcon( QIcon( ":/icons/process" ) ); diff --git a/Modules/Visualization/MonteverdiGui/src/mvdQtWidgetView.cxx b/Modules/Visualization/MonteverdiGui/src/mvdQtWidgetView.cxx index 3c33015a5bde59b586340e7fc5155ed3166c4c84..252c6043797f53d43bfa40cbf5c8dde1abc3421c 100644 --- a/Modules/Visualization/MonteverdiGui/src/mvdQtWidgetView.cxx +++ b/Modules/Visualization/MonteverdiGui/src/mvdQtWidgetView.cxx @@ -23,28 +23,16 @@ /*****************************************************************************/ /* INCLUDE SECTION */ -// -// Qt includes (sorted by alphabetic order) -//// Must be included before system/custom includes. - // // System includes (sorted by alphabetic order) #include <functional> -// -// ITK includes (sorted by alphabetic order) - // // OTB includes (sorted by alphabetic order) #include "otbWrapperApplicationHtmlDocGenerator.h" -// #include "otbWrapperComplexOutputImageParameter.h" #include "otbWrapperOutputFilenameParameter.h" -// #include "otbWrapperOutputImageParameter.h" #include "otbWrapperOutputVectorDataParameter.h" -// #include "otbWrapperQtWidgetOutputImageParameter.h" -// #include "otbWrapperQtWidgetProgressReport.h" #include "otbWrapperQtWidgetSimpleProgressReport.h" -// #include "otbWrapperTypes.h" // // Monteverdi includes (sorted by alphabetic order) @@ -140,208 +128,43 @@ QtWidgetView ::QtWidgetView( const otb::Wrapper::Application::Pointer & otbApp, QWidget* p, Qt::WindowFlags flags ) : - QWidget( p, flags ), - m_Application( otbApp ), - m_Model( NULL ), - m_ExecButton( NULL ), - m_QuitButton( NULL ), - m_Message( NULL ), - m_IsClosable( true ) + otb::Wrapper::QtWidgetView( otbApp, p, flags ) { setObjectName( QtWidgetView::OBJECT_NAME ); - m_Model = new otb::Wrapper::QtWidgetModel( otbApp ); - m_QuitShortcut = new QShortcut(QKeySequence("Ctrl+Q"), this); - - QObject::connect( - m_Model, SIGNAL( SetProgressReportBegin() ), - this, SLOT( OnProgressReportBegin() ) - ); - - QObject::connect( - m_Model, SIGNAL( SetProgressReportDone( int ) ), - this, SLOT( OnProgressReportEnd( int ) ) - ); - - QObject::connect( - m_Model, SIGNAL( ExceptionRaised( QString ) ), - this, SLOT( OnExceptionRaised( QString ) ) - ); -} - -/*******************************************************************************/ -QtWidgetView -::~QtWidgetView() -{ - // m_Application is smart-pointed and will be automatically deleted. - - delete m_Model; - m_Model = NULL; -} - -/*******************************************************************************/ -void -QtWidgetView -::CreateGui() -{ - // Create a VBoxLayout with the header, the input widgets, and the footer - QVBoxLayout *mainLayout = new QVBoxLayout(); - QTabWidget *tab = new QTabWidget(); - tab->addTab(CreateInputWidgets(), tr("Parameters")); - - //otb::Wrapper::QtWidgetProgressReport* prog = new otb::Wrapper::QtWidgetProgressReport(m_Model); - //prog->SetApplication(m_Application); - //tab->addTab(prog, "Progress"); - tab->addTab(CreateDoc(), tr("Documentation")); - mainLayout->addWidget(tab); - - QTextEdit *log = new QTextEdit(); - connect( m_Model->GetLogOutput(), SIGNAL(NewContentLog(QString)), log, SLOT(append(QString) ) ); - tab->addTab(log, tr("Logs")); - - m_Message = new QLabel("<center><font color=\"#FF0000\">"+tr("Select parameters")+"</font></center>"); - connect( - m_Model, - SIGNAL( SetApplicationReady( bool ) ), - this, SLOT( UpdateMessageAfterApplicationReady( bool ) ) - ); - connect( - m_Model, - SIGNAL(SetProgressReportDone(int)), - this, SLOT(UpdateMessageAfterExecution(int)) ); - mainLayout->addWidget(m_Message); - - otb::Wrapper::QtWidgetSimpleProgressReport* progressReport = - new otb::Wrapper::QtWidgetSimpleProgressReport(m_Model); - progressReport->SetApplication(m_Application); - - QWidget* footer = CreateFooter(); - - QHBoxLayout *footLayout = new QHBoxLayout; - footLayout->addWidget(progressReport); - footLayout->addWidget(footer); - mainLayout->addLayout(footLayout); - - footLayout->setAlignment(footer, Qt::AlignBottom); - - QGroupBox *mainGroup = new QGroupBox(); - mainGroup->setLayout(mainLayout); - - QVBoxLayout *finalLayout = new QVBoxLayout(); - finalLayout->addWidget(mainGroup); - - // Make the final layout to the widget - this->setLayout(finalLayout); -} - -/*******************************************************************************/ -QWidget* -QtWidgetView -::CreateInputWidgets() -{ - QScrollArea *scrollArea = new QScrollArea; - - QWidget * widget = - otb::Wrapper::QtWidgetParameterFactory::CreateQtWidget( - m_Model->GetApplication()->GetParameterList(), - m_Model - ); - - scrollArea->setWidget( widget ); - scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - scrollArea->setWidgetResizable(true); + m_IconPathDone = std::string("<img src=\":/icons/done\" width=\"16\" height=\"16\" />"); + m_IconPathFailed = std::string("<img src=\":/icons/failed\" width=\"16\" height=\"16\" />"); // // need to be connected to the end of a process QObject::connect( - m_Model, + GetModel(), SIGNAL( SetProgressReportDone( int ) ), // to: this, SLOT ( OnApplicationExecutionDone( int ) ) ); - - SetupParameterWidgets( widget ); - - return scrollArea; } /*******************************************************************************/ -QWidget* QtWidgetView -::CreateFooter() +::~QtWidgetView() { - // an HLayout with two buttons : Execute and Quit - QGroupBox *footerGroup = new QGroupBox; - QHBoxLayout *footerLayout = new QHBoxLayout; - - footerGroup->setFixedHeight(40); - footerGroup->setContentsMargins(0, 0, 0, 0); - footerLayout->setContentsMargins(5, 5, 5, 5); - - m_ExecButton = new QPushButton(footerGroup); - m_ExecButton->setDefault(true); - m_ExecButton->setEnabled(false); - m_ExecButton->setText(QObject::tr("Execute")); - connect( - m_Model, SIGNAL( SetApplicationReady( bool ) ), - m_ExecButton, SLOT( setEnabled( bool ) ) - ); - - QObject::connect( - m_ExecButton, SIGNAL( clicked() ), - // to: - this, SLOT( OnExecButtonClicked() ) - ); - QObject::connect( - this, SIGNAL( ExecuteAndWriteOutput() ), - // to: - m_Model, SLOT( ExecuteAndWriteOutputSlot() ) - ); - - m_QuitButton = new QPushButton(footerGroup); - m_QuitButton->setText(QObject::tr("Quit")); - connect( - m_QuitButton, - SIGNAL( clicked() ), - // to: - this, - SLOT( close() ) - ); - - // Add Ctrl-Q shortcut to quit - connect( m_QuitShortcut, SIGNAL(activated()), this, SLOT(close()) ); - - - // Put the buttons on the right - footerLayout->addStretch(); - footerLayout->addWidget(m_ExecButton); - footerLayout->addWidget(m_QuitButton); - - footerGroup->setLayout(footerLayout); - - return footerGroup; } /*******************************************************************************/ QWidget* QtWidgetView -::CreateDoc() +::CreateInputWidgets() { - QTextEdit *text = new QTextEdit; - text->setReadOnly(true); - - QTextDocument * doc = new QTextDocument(); + QWidget * widget = otb::Wrapper::QtWidgetView::CreateInputWidgets(); - std::string docContain; - otb::Wrapper::ApplicationHtmlDocGenerator::GenerateDoc( m_Application, docContain); + otb::Wrapper::QtWidgetParameterBase *paramWidget = + widget->findChild<otb::Wrapper::QtWidgetParameterBase*>(); - doc->setHtml(docContain.c_str()); + SetupParameterWidgets(paramWidget); - text->setDocument(doc); - - return text; + return widget; } /*******************************************************************************/ @@ -369,11 +192,11 @@ QtWidgetView SetupWidget( widget, - OutputImageInitializer( m_Application->GetName() ) + OutputImageInitializer( GetModel()->GetApplication()->GetName() ) ); SetupWidget( widget, - ComplexOutputImageInitializer( m_Application->GetName() ) + ComplexOutputImageInitializer( GetModel()->GetApplication()->GetName() ) ); SetupWidget( widget, OutputVectorDataInitializer() ); @@ -394,36 +217,6 @@ QtWidgetView initialize( qobject_cast< FileSelectionInitializer::argument_type >( widget ) ); } -/*******************************************************************************/ -void -QtWidgetView -::closeEvent( QCloseEvent * e ) -{ - assert( e!=NULL ); - - if( !IsClosable() ) - { - assert( !m_Application.IsNull() ); - - QMessageBox::warning( - this, - tr( "Warning!" ), - tr( "OTB-Application '%1' cannot be closed while running!") - .arg( m_Application->GetDocName() ) - ); - - e->ignore(); - - return; - } - - QWidget::closeEvent( e ); - - emit QuitSignal(); - - deleteLater(); -} - /*******************************************************************************/ /* SLOTS */ /*******************************************************************************/ @@ -431,226 +224,180 @@ void QtWidgetView ::OnExecButtonClicked() { - assert( m_Model!=NULL ); - assert( m_Model->GetApplication()!=NULL ); - - - assert( I18nCoreApplication::Instance()!=NULL ); - - // - // Get layer-stack, if any. - StackedLayerModel * layerStack = - I18nCoreApplication::Instance()->GetModel< StackedLayerModel >(); - - otb::Wrapper::Application::Pointer otbApp( m_Model->GetApplication() ); - - // - // Check output parameters of OTB-application. - StringVector paramKeys( otbApp->GetParametersKeys() ); - QStringList filenames1; - - KeyLayerAccumulator::KeyLayerPairList layers; - QStringList filenames2; - - for( StringVector::const_iterator it( paramKeys.begin() ); - it!=paramKeys.end(); - ++it ) + if ( !IsRunning() ) { - if( otbApp->IsParameterEnabled( *it, true ) && - otbApp->HasValue( *it ) ) + assert( GetModel()!=NULL ); + assert( GetModel()->GetApplication()!=NULL ); + + + assert( I18nCoreApplication::Instance()!=NULL ); + + // + // Get layer-stack, if any. + StackedLayerModel * layerStack = + I18nCoreApplication::Instance()->GetModel< StackedLayerModel >(); + + otb::Wrapper::Application::Pointer otbApp( GetModel()->GetApplication() ); + + // + // Check output parameters of OTB-application. + StringVector paramKeys( otbApp->GetParametersKeys() ); + QStringList filenames1; + + KeyLayerAccumulator::KeyLayerPairList layers; + QStringList filenames2; + + for( StringVector::const_iterator it( paramKeys.begin() ); + it!=paramKeys.end(); + ++it ) { - otb::Wrapper::Parameter::Pointer param( otbApp->GetParameterByKey( *it ) ); - assert( !param.IsNull() ); - - // qDebug() - // << it->c_str() << ": type" << otbApp->GetParameterType( *it ); - - // const char* filename = NULL; - std::string filename; - - switch( otbApp->GetParameterType( *it ) ) - { - case otb::Wrapper::ParameterType_OutputFilename: - filename = - otb::DynamicCast< otb::Wrapper::OutputFilenameParameter >( param ) - ->GetValue(); - break; - // - // FILENAME. - // - // IMAGE. - case otb::Wrapper::ParameterType_OutputImage: - filename = - otb::DynamicCast< otb::Wrapper::OutputImageParameter >( param ) - ->GetFileName(); - break; - // - // VECTOR-DATA. - case otb::Wrapper::ParameterType_OutputVectorData: - filename = - otb::DynamicCast< otb::Wrapper::OutputVectorDataParameter >( param ) - ->GetFileName(); - break; - // - // COMPLEX IMAGE. - case otb::Wrapper::ParameterType_ComplexOutputImage: - filename = - otb::DynamicCast< otb::Wrapper::ComplexOutputImageParameter >( param ) - ->GetFileName(); - break; - // - // NONE. - default: - break; - } - - if( QFileInfo( filename.c_str() ).exists() ) - filenames1.push_back( filename.c_str() ); - - if( layerStack!=NULL ) - { - KeyLayerAccumulator accumulator( - std::for_each( - layerStack->Begin(), - layerStack->End(), KeyLayerAccumulator( filename, layers ) - ) - ); - - if( accumulator.GetCount()>0 ) - filenames2.push_back( filename.c_str() ); - } - } - } - - { - QString message; - - if( filenames1.size()==1 ) - { - // qDebug() - // << it->c_str() << ":" << QString( filename.c_str() ); - - message = - tr( "Are you sure you want to overwrite file '%1'?" ) - .arg( filenames1.front() ); - } - else if( filenames1.size()>1 ) - { - message = - tr( "Following files will be overwritten. Are you sure you want to continue?\n- %1" ) - .arg( filenames1.join( "\n- " ) ); - } - - if( !message.isEmpty() ) + if( otbApp->IsParameterEnabled( *it, true ) && + otbApp->HasValue( *it ) ) + { + otb::Wrapper::Parameter::Pointer param( otbApp->GetParameterByKey( *it ) ); + assert( !param.IsNull() ); + + // qDebug() + // << it->c_str() << ": type" << otbApp->GetParameterType( *it ); + + // const char* filename = NULL; + std::string filename; + + switch( otbApp->GetParameterType( *it ) ) { - QMessageBox::StandardButton button = - QMessageBox::question( - this, - PROJECT_NAME, - message, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No - ); - - if( button==QMessageBox::No ) - return; + case otb::Wrapper::ParameterType_OutputFilename: + filename = + otb::DynamicCast< otb::Wrapper::OutputFilenameParameter >( param ) + ->GetValue(); + break; + // + // FILENAME. + // + // IMAGE. + case otb::Wrapper::ParameterType_OutputImage: + filename = + otb::DynamicCast< otb::Wrapper::OutputImageParameter >( param ) + ->GetFileName(); + break; + // + // VECTOR-DATA. + case otb::Wrapper::ParameterType_OutputVectorData: + filename = + otb::DynamicCast< otb::Wrapper::OutputVectorDataParameter >( param ) + ->GetFileName(); + break; + // + // COMPLEX IMAGE. + case otb::Wrapper::ParameterType_ComplexOutputImage: + filename = + otb::DynamicCast< otb::Wrapper::ComplexOutputImageParameter >( param ) + ->GetFileName(); + break; + // + // NONE. + default: + break; } - } - - { - QString message; - - if( filenames2.size()==1 ) + + if( QFileInfo( filename.c_str() ).exists() ) + filenames1.push_back( filename.c_str() ); + + if( layerStack!=NULL ) { - // qDebug() - // << it->c_str() << ":" << QString( filename.c_str() ); - - message = - tr( "File '%1' is being viewed in " PROJECT_NAME " and will be concurrently overwritten by running this %2. File will be removed from layer-stack before running %2 and reloaded after.\n\nDo you want to continue?" ) - .arg( filenames2.front() ) - .arg( otbApp->GetDocName() ); + KeyLayerAccumulator accumulator( + std::for_each( + layerStack->Begin(), + layerStack->End(), KeyLayerAccumulator( filename, layers ) + ) + ); + + if( accumulator.GetCount()>0 ) + filenames2.push_back( filename.c_str() ); } - else if( filenames2.size()>1 ) + } + } + { - message = - tr( "Following files are being viewed in " PROJECT_NAME " and will be concurrently overwritter by running %2. Files will be removed from layer-stack before running %2. Do you want to continue?\n- %1" ) - .arg( filenames2.join( "\n- " ) ) - .arg( otbApp->GetDocName() ); + QString message; + + if( filenames1.size()==1 ) + { + // qDebug() + // << it->c_str() << ":" << QString( filename.c_str() ); + + message = + tr( "Are you sure you want to overwrite file '%1'?" ) + .arg( filenames1.front() ); + } + else if( filenames1.size()>1 ) + { + message = + tr( "Following files will be overwritten. Are you sure you want to continue?\n- %1" ) + .arg( filenames1.join( "\n- " ) ); + } + + if( !message.isEmpty() ) + { + QMessageBox::StandardButton button = + QMessageBox::question( + this, + PROJECT_NAME, + message, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No + ); + + if( button==QMessageBox::No ) + return; + } } - - if( !message.isEmpty() ) + { - QMessageBox::StandardButton button = - QMessageBox::question( - this, - PROJECT_NAME, - message, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No - ); - - if( button==QMessageBox::No ) - return; - - while( !layers.empty() ) + QString message; + + if( filenames2.size()==1 ) { - layerStack->Delete( layers.front().first ); - - layers.pop_front(); + // qDebug() + // << it->c_str() << ":" << QString( filename.c_str() ); + + message = + tr( "File '%1' is being viewed in " PROJECT_NAME " and will be concurrently overwritten by running this %2. File will be removed from layer-stack before running %2 and reloaded after.\n\nDo you want to continue?" ) + .arg( filenames2.front() ) + .arg( otbApp->GetDocName() ); + } + else if( filenames2.size()>1 ) + { + message = + tr( "Following files are being viewed in " PROJECT_NAME " and will be concurrently overwritter by running %2. Files will be removed from layer-stack before running %2. Do you want to continue?\n- %1" ) + .arg( filenames2.join( "\n- " ) ) + .arg( otbApp->GetDocName() ); + } + + if( !message.isEmpty() ) + { + QMessageBox::StandardButton button = + QMessageBox::question( + this, + PROJECT_NAME, + message, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No + ); + + if( button==QMessageBox::No ) + return; + + while( !layers.empty() ) + { + layerStack->Delete( layers.front().first ); + + layers.pop_front(); + } } } } - - /* U N S A F E - // BUGFIX: Mantis-750 - // - // Remove files which will be overwritten in order to use - // file-existence to check whether to emit the OutputImageChanged - // signal (see ::OnApplicationExecutionDone()). - for( FileInfoVector::const_iterator it( fileInfos.begin() ); - it!=fileInfos.end(); - ++it ) - { - qDebug() << "Removing:" << it->filePath(); - - it->dir().remove( it->fileName() ); - } - */ - - emit ExecuteAndWriteOutput(); - - m_Message->setText("<center><font color=\"#FF0000\">"+tr("Running")+"</font></center>"); -} - -/******************************************************************************/ -void -QtWidgetView -::UpdateMessageAfterExecution(int status) -{ - if (status >= 0) - { - m_Message->setText("<center>" - "<img src=\":/icons/done\" width=\"16\" height=\"16\" />" - "<font color=\"#00A000\">"+tr("Done")+"</font></center>"); - } - else - { - m_Message->setText("<center>" - "<img src=\":/icons/failed\" width=\"16\" height=\"16\" />" - "<font color=\"#FF0000\">"+tr("Failed")+"</font></center>"); - } -} - -/*******************************************************************************/ -void -QtWidgetView -::UpdateMessageAfterApplicationReady( bool val ) -{ - if(val == true) - m_Message->setText("<center><font color=\"#00A000\">"+tr("Ready to run")+"</font></center>"); - else - m_Message->setText("<center><font color=\"#FF0000\">"+tr("Select parameters")+"</font></center>"); + otb::Wrapper::QtWidgetView::OnExecButtonClicked(); } /*******************************************************************************/ @@ -675,7 +422,7 @@ void QtWidgetView ::OnApplicationExecutionDone( int status ) { - otb::Wrapper::Application::Pointer otbApp( m_Model->GetApplication() ); + otb::Wrapper::Application::Pointer otbApp( GetModel()->GetApplication() ); if( status!=0 ) { @@ -765,6 +512,5 @@ QtWidgetView emit ExecutionDone( status ); } -} - -} +} // end of namespace Wrapper +} // end of namespace mvd diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index ed7e125ac97b601b4cc3396a84238fedb3b23059..4748ab0c5ddc71a9a1ffff72b8ba89585d86bc8d 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -155,6 +155,9 @@ public: */ int ExecuteAndWriteOutput(); + /** Request the application to stop its processing */ + void Stop(); + /* Get the internal application parameters * * WARNING: this method may disappear from the API */ diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 3d469f239bca60696be13e10350282bc3b682670..7aec4f87620aa6917040ee282d4c5e0110848d53 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -757,6 +757,12 @@ int Application::ExecuteAndWriteOutput() return status; } +void +Application::Stop() +{ + m_ProgressSource->SetAbortGenerateData(true); +} + /* Enable the use of an optional parameter. Returns the previous state */ void Application::EnableParameter(std::string paramKey) { diff --git a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h index 2fefeda56e012736bd3f0d13ca782ddf39aa5b38..09d040a4dcd35f5ef17f1e820c30f8d8f55f3471 100644 --- a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h +++ b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetModel.h @@ -68,6 +68,13 @@ signals: */ void ExceptionRaised( QString what ); +public slots: + /** Ask the running application to stop */ + void Stop() + { + m_Application->Stop(); + } + protected: void run() override; @@ -139,6 +146,8 @@ signals: void UpdateGui(); + void Stop(); + protected slots: /** * \brief Slot called when execution is requested (e.g. by diff --git a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h index 5a004af2dc56df5e5a94d8510df22b60d7e822a2..0f1ac8a3455cd5487c7af6b2dfd45b3c25069984 100644 --- a/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h +++ b/Modules/Wrappers/QtWidget/include/otbWrapperQtWidgetView.h @@ -22,75 +22,244 @@ #define otbWrapperQtWidgetView_h #include <QtGui> -#include <QObject> #include <QShortcut> + +// +// OTB includes (sorted by alphabetic order) #ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829 //tag=QT4-boost-compatibility +#include "otbWrapperApplication.h" #include "otbWrapperQtWidgetModel.h" #endif //tag=QT4-boost-compatibility +#include "OTBQtWidgetExport.h" namespace otb { namespace Wrapper { -/** \class QtWidgetView - * \brief +/*****************************************************************************/ +/* CLASS DEFINITION SECTION */ + +/** + * \class QtWidgetView * * \ingroup OTBQtWidget + * + * \brief WIP. */ -class OTBQtWidget_EXPORT QtWidgetView : public QWidget + +class OTBQtWidget_EXPORT QtWidgetView : + public QWidget { + /*-[ QOBJECT SECTION ]-----------------------------------------------------*/ + Q_OBJECT + + Q_PROPERTY( bool isClosable + READ IsClosable + WRITE SetClosable ); + + /*-[ PUBLIC SECTION ]------------------------------------------------------*/ + +// +// Public methods. public: - QtWidgetView(Application* app); + + /** + */ + static char const * const OBJECT_NAME; + + /** \brief Constructor. */ + QtWidgetView( const otb::Wrapper::Application::Pointer & otbApp, + QWidget* p =0, + Qt::WindowFlags flags =0 ); + + /** \brief Destructor. */ ~QtWidgetView() override; + /** \brief Gui Creation. */ void CreateGui(); - QtWidgetModel* GetModel() + /** \brief Model Accessor */ + inline otb::Wrapper::QtWidgetModel* GetModel() { return m_Model; } + /** + * \return The OTB-application pointer of this view. + */ + //~ otb::Wrapper::Application::ConstPointer GetApplication() const + //~ { + //~ return otb::ConstCast< otb::Wrapper::Application >( + //~ m_Application + //~ ); + //~ } + + /** + */ + inline bool IsClosable() const; + + /*-[ PUBLIC SLOTS SECTION ]------------------------------------------------*/ + +// +// Public SLOTS. public slots: - void CloseSlot(); - void UnhandledException(QString message); - void OnExceptionRaised(QString message); -private slots: - void UpdateMessageAfterExecuteClicked(); - void UpdateMessageAfterExecution(int status); - void UpdateMessageAfterApplicationReady(bool val); + /*-[ SIGNALS SECTION ]-----------------------------------------------------*/ +// +// Signals. signals: void QuitSignal(); + void ExecuteAndWriteOutput(); + void Stop(); + /*-[ PROTECTED SECTION ]---------------------------------------------------*/ + +// +// Protected methods. +protected: + + bool IsRunning(); + + virtual QWidget* CreateInputWidgets(); + + // + // QWidget overloads. + + void closeEvent( QCloseEvent * event ) override; + +// +// Protected attributes. +protected: + + /** Html section for 'Done' icon */ + std::string m_IconPathDone; + + /** Html section for 'Failed' icon */ + std::string m_IconPathFailed; + +protected slots: + + /** + */ + void OnExecButtonClicked(); + + void UnhandledException(QString message); + void OnExceptionRaised( QString what ); + + /*-[ PRIVATE SECTION ]-----------------------------------------------------*/ + +// +// Private methods. private: + QtWidgetView(const QtWidgetView&); //purposely not implemented void operator=(const QtWidgetView&); //purposely not implemented QWidget* CreateFooter(); - QWidget* CreateInputWidgets(); - QWidget* CreateDoc(); - Application::Pointer m_Application; - QtWidgetModel* m_Model; +// +// Private attributes. - QTextEdit *m_LogText; - QTabWidget *m_TabWidget; +private: + + otb::Wrapper::QtWidgetModel* m_Model; QPushButton* m_ExecButton; QPushButton* m_QuitButton; QShortcut* m_QuitShortcut; QLabel* m_Message; + QTextEdit *m_LogText; + QTabWidget *m_TabWidget; + + bool m_IsClosable : 1; + + bool m_IsRunning; + + /*-[ PRIVATE SLOTS SECTION ]-----------------------------------------------*/ + +// +// Slots. +private slots: + void UpdateMessageAfterExecution(int status); + void UpdateMessageAfterApplicationReady(bool val); + + /** + */ + inline void OnProgressReportBegin(); + + /** + */ + inline void OnProgressReportEnd( int status ); + + /** + */ + inline void SetClosable( bool ); + }; +} // end namespace 'Wrapper' +} // end namespace 'otb' + +/*****************************************************************************/ +/* INLINE SECTION */ + +namespace otb +{ + +namespace Wrapper +{ + +/*****************************************************************************/ +inline +bool +QtWidgetView +::IsClosable() const +{ + return m_IsClosable; } + +/*****************************************************************************/ +inline +void +QtWidgetView +::SetClosable( bool enabled ) +{ + m_IsClosable = enabled; + + setEnabled( true ); + + if( m_QuitButton!=NULL ) + m_QuitButton->setEnabled( m_IsClosable ); } +/*******************************************************************************/ +inline +void +QtWidgetView +::OnProgressReportBegin() +{ + SetClosable( false ); +} + +/*******************************************************************************/ +inline +void +QtWidgetView +::OnProgressReportEnd( int ) +{ + SetClosable( true ); +} + +} // end namespace 'Wrapper' + +} // end namespace 'otb' + #endif diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx index a0d61138d72e424fd282b89c1daeb9da67bb9fe6..5d458d0f15109f9b5cf77b55b96cdea240e1ca6d 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetModel.cxx @@ -200,7 +200,7 @@ QtWidgetModel } // launch the output image writing - AppliThread * taskAppli = new AppliThread( m_Application ); + AppliThread *taskAppli = new AppliThread( m_Application ); QObject::connect( taskAppli, @@ -225,10 +225,19 @@ QtWidgetModel SLOT( deleteLater() ) ); + QObject::connect( + this, + SIGNAL( Stop() ), + taskAppli, + SLOT( Stop() ) + ); + // Tell the Progress Reporter to begin emit SetProgressReportBegin(); taskAppli->Execute(); + + emit SetApplicationReady(true); } void @@ -322,6 +331,10 @@ AppliThread m_Application->GetLogger()->Fatal(string("Cannot open image ") + err.m_Filename + string(". ") + err.GetDescription() + string("\n")); emit ExceptionRaised( err.what() ); } + catch(itk::ProcessAborted& err) + { + m_Application->GetLogger()->Info("Processing aborted\n"); + } catch(itk::ExceptionObject& err) { m_Application->GetLogger()->Debug("Caught itk::ExceptionObject during application execution:\n"); diff --git a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx index 39c9d80bd4f84283c9878a6c985404ad9e37dfaa..f689d59d81183f5c54173b29afdd2307403c1bbe 100644 --- a/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx +++ b/Modules/Wrappers/QtWidget/src/otbWrapperQtWidgetView.cxx @@ -20,31 +20,77 @@ #include "otbWrapperQtWidgetView.h" +#include <functional> + #include "otbWrapperQtWidgetParameterGroup.h" #include "otbWrapperQtWidgetParameterFactory.h" -#include "otbWrapperQtWidgetProgressReport.h" -#include "otbWrapperOutputImageParameter.h" -#include "otbWrapperChoiceParameter.h" -#include "otbWrapperQtWidgetSimpleProgressReport.h" #include "otbWrapperApplicationHtmlDocGenerator.h" - -#include "itksys/SystemTools.hxx" - +#include "otbWrapperOutputFilenameParameter.h" +#include "otbWrapperOutputVectorDataParameter.h" +#include "otbWrapperQtWidgetSimpleProgressReport.h" namespace otb { namespace Wrapper { - -QtWidgetView::QtWidgetView(Application* app) +/* + TRANSLATOR mvd::Wrapper::QtWidgetView + + Necessary for lupdate to be aware of C++ namespaces. + + Context comment for translator. +*/ + +/*****************************************************************************/ +/* CONSTANTS */ + +char const * const +QtWidgetView +::OBJECT_NAME = "otb::Wrapper::QtWidgetView"; + +/*****************************************************************************/ +/* CLASS IMPLEMENTATION SECTION */ +/*****************************************************************************/ +QtWidgetView::QtWidgetView( const otb::Wrapper::Application::Pointer & otbApp, + QWidget* p, + Qt::WindowFlags flags ) : + QWidget( p, flags ), + m_IconPathDone(""), + m_IconPathFailed(""), + m_Model( NULL ), + m_ExecButton( NULL ), + m_QuitButton( NULL ), + m_Message( NULL ), + m_LogText( NULL ), + m_TabWidget( NULL ), + m_IsClosable( true ), + m_IsRunning(false) { - m_Model = new QtWidgetModel(app); - m_Application = app; + setObjectName( QtWidgetView::OBJECT_NAME ); + + m_Model = new otb::Wrapper::QtWidgetModel( otbApp ); + m_QuitShortcut = new QShortcut(QKeySequence("Ctrl+Q"), this); + + QObject::connect( + m_Model, SIGNAL( SetProgressReportBegin() ), + this, SLOT( OnProgressReportBegin() ) + ); + + QObject::connect( + m_Model, SIGNAL( SetProgressReportDone( int ) ), + this, SLOT( OnProgressReportEnd( int ) ) + ); + + QObject::connect( + m_Model, SIGNAL( ExceptionRaised( QString ) ), + this, SLOT( OnExceptionRaised( QString ) ) + ); } QtWidgetView::~QtWidgetView() { delete m_Model; + m_Model = NULL; } void QtWidgetView::CreateGui() @@ -53,71 +99,74 @@ void QtWidgetView::CreateGui() QVBoxLayout *mainLayout = new QVBoxLayout(); m_TabWidget = new QTabWidget(); - m_TabWidget->addTab(CreateInputWidgets(), "Parameters"); + m_TabWidget->addTab(CreateInputWidgets(), tr("Parameters")); m_LogText = new QTextEdit(); connect( m_Model->GetLogOutput(), SIGNAL(NewContentLog(QString)), m_LogText, SLOT(append(QString) ) ); - m_TabWidget->addTab(m_LogText, "Logs"); - QtWidgetProgressReport* prog = new QtWidgetProgressReport(m_Model); - prog->SetApplication(m_Application); - m_TabWidget->addTab(prog, "Progress"); - m_TabWidget->addTab(CreateDoc(), "Documentation"); + m_TabWidget->addTab(m_LogText, tr("Logs")); + m_TabWidget->addTab(CreateDoc(), tr("Documentation")); mainLayout->addWidget(m_TabWidget); - m_Message = new QLabel("<center><font color=\"#FF0000\">Select parameters</font></center>"); - connect( m_Model, SIGNAL(SetApplicationReady(bool)), this, SLOT(UpdateMessageAfterApplicationReady(bool)) ); + m_Message = new QLabel("<center><font color=\"#FF0000\">"+tr("Select parameters")+"</font></center>"); + connect( m_Model, SIGNAL(SetApplicationReady(bool)), this, SLOT( UpdateMessageAfterApplicationReady(bool)) ); connect( m_Model, SIGNAL(SetProgressReportDone(int)), this, SLOT(UpdateMessageAfterExecution(int)) ); mainLayout->addWidget(m_Message); - QtWidgetSimpleProgressReport * progressReport = new QtWidgetSimpleProgressReport(m_Model); - progressReport->SetApplication(m_Application); + otb::Wrapper::QtWidgetSimpleProgressReport * progressReport = new otb::Wrapper::QtWidgetSimpleProgressReport(m_Model); + progressReport->SetApplication(m_Model->GetApplication()); + QWidget* footer = CreateFooter(); + QHBoxLayout *footLayout = new QHBoxLayout; footLayout->addWidget(progressReport); - footLayout->addWidget(CreateFooter()); + footLayout->addWidget(footer); mainLayout->addLayout(footLayout); + footLayout->setAlignment(footer, Qt::AlignBottom); + QGroupBox *mainGroup = new QGroupBox(); mainGroup->setLayout(mainLayout); QVBoxLayout *finalLayout = new QVBoxLayout(); finalLayout->addWidget(mainGroup); - connect( m_Model, SIGNAL(ExceptionRaised(QString)), this, SLOT(OnExceptionRaised(QString)) ); - // Make the final layout to the widget this->setLayout(finalLayout); } -void QtWidgetView::UpdateMessageAfterExecuteClicked() -{ - m_Message->setText("<center><font color=\"#FF0000\">Running</font></center>"); -} - void QtWidgetView::UpdateMessageAfterExecution(int status) { if (status >= 0) { - m_Message->setText("<center><font color=\"#00A000\">Done</font></center>"); + m_Message->setText("<center>"+QString(m_IconPathDone.c_str())+ + "<font color=\"#00A000\">"+tr("Done")+"</font></center>"); } else { - m_Message->setText("<center><font color=\"#FF0000\">Failed</font></center>"); + m_Message->setText("<center>"+QString(m_IconPathFailed.c_str())+ + "<font color=\"#FF0000\">"+tr("Failed")+"</font></center>"); } + m_ExecButton->setText(QObject::tr("Execute")); + m_IsRunning = false; } void QtWidgetView::UpdateMessageAfterApplicationReady( bool val ) { - if(val == true) - m_Message->setText("<center><font color=\"#00A000\">Ready to run</font></center>"); - else - m_Message->setText("<center><font color=\"#FF0000\">Select parameters</font></center>"); + if(!m_IsRunning) + { + if(val == true) + m_Message->setText("<center><font color=\"#00A000\">"+tr("Ready to run")+"</font></center>"); + else + m_Message->setText("<center><font color=\"#FF0000\">"+tr("Select parameters")+"</font></center>"); + } } QWidget* QtWidgetView::CreateInputWidgets() { QScrollArea *scrollArea = new QScrollArea; - // Put the main group inside a scroll area - scrollArea->setWidget(QtWidgetParameterFactory::CreateQtWidget(m_Model->GetApplication()->GetParameterList(), m_Model)); + + scrollArea->setWidget( otb::Wrapper::QtWidgetParameterFactory::CreateQtWidget( + m_Model->GetApplication()->GetParameterList(), + m_Model)); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setWidgetResizable(true); @@ -131,7 +180,7 @@ QWidget* QtWidgetView::CreateFooter() // an HLayout with two buttons : Execute and Quit QGroupBox *footerGroup = new QGroupBox; QHBoxLayout *footerLayout = new QHBoxLayout; - + footerGroup->setFixedHeight(40); footerGroup->setContentsMargins(0, 0, 0, 0); footerLayout->setContentsMargins(5, 5, 5, 5); @@ -140,17 +189,17 @@ QWidget* QtWidgetView::CreateFooter() m_ExecButton->setDefault(true); m_ExecButton->setEnabled(false); m_ExecButton->setText(QObject::tr("Execute")); - connect( m_ExecButton, SIGNAL(clicked()), m_Model, SLOT(ExecuteAndWriteOutputSlot() ) ); - connect( m_Model, SIGNAL(SetApplicationReady(bool)), m_ExecButton, SLOT(setEnabled(bool)) ); - connect( m_ExecButton, SIGNAL(clicked()), this, SLOT(UpdateMessageAfterExecuteClicked() ) ); + connect( m_Model, SIGNAL( SetApplicationReady( bool ) ), m_ExecButton, SLOT( setEnabled( bool ) )); + QObject::connect( m_ExecButton, SIGNAL( clicked() ), this, SLOT( OnExecButtonClicked() )); + QObject::connect( this, SIGNAL( ExecuteAndWriteOutput() ), m_Model, SLOT( ExecuteAndWriteOutputSlot() )); + QObject::connect( this, SIGNAL( Stop() ), m_Model, SIGNAL( Stop() )); m_QuitButton = new QPushButton(footerGroup); m_QuitButton->setText(QObject::tr("Quit")); - connect( m_QuitButton, SIGNAL(clicked()), this, SLOT(CloseSlot()) ); + connect(m_QuitButton, SIGNAL( clicked() ), this, SLOT( close() )); // Add Ctrl-Q shortcut to quit - m_QuitShortcut = new QShortcut(QKeySequence("Ctrl+Q"), this); - connect( m_QuitShortcut, SIGNAL(activated()), this, SLOT(CloseSlot()) ); + connect( m_QuitShortcut, SIGNAL(activated()), this, SLOT(close()) ); // Put the buttons on the right footerLayout->addStretch(); @@ -170,7 +219,7 @@ QWidget* QtWidgetView::CreateDoc() QTextDocument * doc = new QTextDocument(); std::string docContain; - ApplicationHtmlDocGenerator::GenerateDoc( m_Application, docContain, true); + otb::Wrapper::ApplicationHtmlDocGenerator::GenerateDoc( GetModel()->GetApplication(), docContain); doc->setHtml(docContain.c_str()); @@ -179,13 +228,49 @@ QWidget* QtWidgetView::CreateDoc() return text; } -void QtWidgetView::CloseSlot() +void QtWidgetView::closeEvent( QCloseEvent * e ) { - // Close the widget - this->close(); + assert( e!=NULL ); + + if( !IsClosable() ) + { + assert( GetModel()->GetApplication() ); + + QMessageBox::warning( + this, + tr( "Warning!" ), + tr( "OTB-Application '%1' cannot be closed while running!") + .arg( GetModel()->GetApplication()->GetDocName() ) + ); + + e->ignore(); + + return; + } + + QWidget::closeEvent( e ); - // Emit a signal to close any widget that this gui belonging to emit QuitSignal(); + + deleteLater(); +} + +void +QtWidgetView +::OnExecButtonClicked() +{ + if (m_IsRunning) + { + m_Message->setText("<center><font color=\"#FF0000\">"+tr("Cancelling")+"...</font></center>"); + emit Stop(); + } + else + { + m_IsRunning = true; + m_Message->setText("<center><font color=\"#FF0000\">"+tr("Running")+"</font></center>"); + m_ExecButton->setText(QObject::tr("Cancel")); + emit ExecuteAndWriteOutput(); + } } void QtWidgetView::UnhandledException(QString message) @@ -194,10 +279,16 @@ void QtWidgetView::UnhandledException(QString message) m_LogText->append(message); } -void QtWidgetView::OnExceptionRaised(QString /*message*/) +void QtWidgetView::OnExceptionRaised( QString /*message*/) { m_TabWidget->setCurrentIndex(1); } +bool QtWidgetView::IsRunning() +{ + return m_IsRunning; } -} + +} // end of namespace Wrapper +} // end of namespace otb +