...
 
Commits (32)
......@@ -1372,56 +1372,6 @@ MainWindow
{
assert( e!=NULL );
{
//
// List OTB-application widgets.
typedef QList< mvd::Wrapper::QtWidgetView * > QtWidgetViewList;
QtWidgetViewList c( findChildren< mvd::Wrapper::QtWidgetView * >() );
QStringList names;
//
// Find out which OTB-applications are running.
for( QtWidgetViewList::iterator it( c.begin() );
it!=c.end();
++ it )
{
assert( *it );
if( !( *it )->IsClosable() )
{
assert( ( *it )->GetModel()->GetApplication() );
// qDebug() << "OTB-application:" << ( *it )->GetApplication()->GetDocName();
names.push_back( ( *it )->GetModel()->GetApplication()->GetDocName() );
}
}
//
// If some OTB-application is running, display warning, names and
// prevent to close.
if( !names.isEmpty() )
{
QMessageBox::warning(
this,
tr( "Warning!" ),
tr(
PROJECT_NAME
" cannot exit while some OTB-application is running!\n\n"
"Please wait for following OTB-applicatio(s) to exit:\n- %1"
)
.arg( names.join( "\n- " ) )
);
e->ignore();
return;
}
}
{
assert( I18nCoreApplication::Instance()!=NULL );
assert( I18nCoreApplication::Instance()->GetModel()==
......
......@@ -62,7 +62,7 @@ public:
otb::Wrapper::Application::Pointer PrepareApplication(const QString& appName, bool isStandalone = false) const;
otb::Wrapper::QtMainWindow* NewOtbApplicationWindow(const QString& appName, bool isStandalone = false, QWidget* p = nullptr, Qt::WindowFlags = 0) const;
otb::Wrapper::QtMainWindow* NewOtbApplicationWindow(const QString& appName, bool isStandalone = false, QWidget* p = nullptr) const;
};
} // namespace mvd
......
......@@ -64,18 +64,10 @@ namespace Wrapper
class OTBMonteverdiGUI_EXPORT QtWidgetView :
public otb::Wrapper::QtWidgetView
{
/*-[ QOBJECT SECTION ]-----------------------------------------------------*/
Q_OBJECT
/*-[ PUBLIC SECTION ]------------------------------------------------------*/
//
// Public methods.
public:
/**
*/
static char const * const OBJECT_NAME;
/** \brief Constructor. */
......@@ -86,30 +78,18 @@ public:
/** \brief Destructor. */
~QtWidgetView() override;
protected:
bool BeforeExecuteButtonClicked() override;
protected:
QWidget* CreateInputWidgets() override;
protected slots:
/** extend the behaviour of base class OnExecButtonClicked */
void OnExecButtonClicked() override;
/** modify the behaviour of base class OnExceptionRaised
*/
void OnExceptionRaised( QString what ) override;
private:
QtWidgetView(const QtWidgetView&) = delete;
void operator=(const QtWidgetView&) = delete;
/**
*/
void SetupParameterWidgets( QWidget* widget );
/**
*/
void SetupFileSelectionWidget( QWidget * );
private slots:
......@@ -119,12 +99,8 @@ private slots:
// image filename{s} set by the user in this OTB application (if any).
void OnApplicationExecutionDone( int );
/**
*/
inline void OnFileSelectionWidgetAdded0( QWidget * );
/**
*/
inline void OnFileSelectionWidgetAdded1( QWidget * );
};
......@@ -132,16 +108,12 @@ private slots:
} // end namespace 'mvd'
/*****************************************************************************/
/* INLINE SECTION */
namespace mvd
{
namespace Wrapper
{
/*******************************************************************************/
inline
void
QtWidgetView
......@@ -150,7 +122,6 @@ QtWidgetView
SetupFileSelectionWidget( widget );
}
/*******************************************************************************/
inline
void
QtWidgetView
......
......@@ -183,8 +183,7 @@ otb::Wrapper::QtMainWindow*
ApplicationLauncher
::NewOtbApplicationWindow( const QString & appName,
bool isStandalone,
QWidget* parent,
Qt::WindowFlags flags ) const
QWidget* parent) const
{
// Setup the otb application
auto otbApp = PrepareApplication(appName, isStandalone);
......@@ -194,7 +193,7 @@ ApplicationLauncher
gui->CreateGui();
// Make the application window
auto window = new ::otb::Wrapper::QtMainWindow(otbApp, gui, parent, flags | Qt::Window);
auto window = new ::otb::Wrapper::QtMainWindow(otbApp, gui, parent);
return window;
}
......
......@@ -116,13 +116,6 @@ char const * const
QtWidgetView
::OBJECT_NAME = "mvd::Wrapper::QtWidgetView";
/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION */
/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION */
/*****************************************************************************/
QtWidgetView
::QtWidgetView( const otb::Wrapper::Application::Pointer & otbApp,
QWidget* p,
......@@ -131,10 +124,6 @@ QtWidgetView
{
setObjectName( QtWidgetView::OBJECT_NAME );
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(
GetModel(),
......@@ -211,197 +200,90 @@ QtWidgetView
initialize( qobject_cast< FileSelectionInitializer::argument_type >( widget ) );
}
/*******************************************************************************/
/* SLOTS */
/*******************************************************************************/
void
QtWidgetView
::OnExecButtonClicked()
bool QtWidgetView::BeforeExecuteButtonClicked()
{
if ( !IsRunning() )
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;
for (StringVector::const_iterator it(paramKeys.begin()); it != paramKeys.end(); ++it)
{
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());
std::string filename;
switch (otbApp->GetParameterType(*it))
{
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 ) )
{
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;
//
// NONE.
default:
break;
case otb::Wrapper::ParameterType_OutputFilename:
filename = otb::DynamicCast<otb::Wrapper::OutputFilenameParameter>(param)->GetValue();
break;
case otb::Wrapper::ParameterType_OutputImage:
filename = otb::DynamicCast<otb::Wrapper::OutputImageParameter>(param)->GetFileName();
break;
case otb::Wrapper::ParameterType_OutputVectorData:
filename = otb::DynamicCast<otb::Wrapper::OutputVectorDataParameter>(param)->GetFileName();
break;
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( QFileInfo( filename.c_str() ).exists() )
filenames1.push_back( filename.c_str() );
if( layerStack!=NULL )
}
{
QString message;
if (filenames1.size() == 1)
{
KeyLayerAccumulator accumulator(
std::for_each(
layerStack->Begin(),
layerStack->End(), KeyLayerAccumulator( filename, layers )
)
);
if( accumulator.GetCount()>0 )
filenames2.push_back( filename.c_str() );
message = tr("Are you sure you want to overwrite file '%1'?").arg(filenames1.front());
}
}
}
else if (filenames1.size() > 1)
{
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;
}
message = tr("Following files will be overwritten. Are you sure you want to continue?\n- %1").arg(filenames1.join("\n- "));
}
if (!message.isEmpty())
{
QString message;
if( filenames2.size()==1 )
{
// 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();
}
}
QMessageBox::StandardButton button = QMessageBox::question(this, PROJECT_NAME, message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (button == QMessageBox::No)
return false;
}
}
otb::Wrapper::QtWidgetView::OnExecButtonClicked();
}
// Delete from layer stack the images that will be overwritten and reloaded
while (!layers.empty())
{
layerStack->Delete(layers.front().first);
/*******************************************************************************/
void
QtWidgetView
::OnExceptionRaised( QString what )
{
qWarning() << what;
layers.pop_front();
}
#if defined( OTB_DEBUG )
QMessageBox::warning(
this,
PROJECT_NAME,
what,
QMessageBox::Ok
);
#endif
return true;
}
/*******************************************************************************/
......@@ -429,18 +311,6 @@ QtWidgetView
return;
}
/*
// Removed as per MVDX-259.
QMessageBox::information(
this,
PROJECT_NAME,
tr( "'%1' has succeeded.\n"
"Result(s) will be imported as dataset(s).\n")
.arg( otbApp->GetName() ),
QMessageBox::Ok
);
*/
CountType count = 0;
//
......
......@@ -105,6 +105,8 @@ public:
TiXmlElement* ParseApplication(Application::Pointer app);
static std::string MakeCommandLine(otb::Wrapper::Application::Pointer application);
protected:
OutputProcessXMLParameter();
......
......@@ -366,6 +366,77 @@ OutputProcessXMLParameter::ParseGroup(const std::string& group)
}
}
std::string OutputProcessXMLParameter::MakeCommandLine(Application::Pointer application)
{
OutputProcessXMLParameter::Pointer outXMLParam = OutputProcessXMLParameter::New();
TiXmlElement* XMLAppElement = outXMLParam->ParseApplication(application);
// Create command line from the XML document
TiXmlElement * pName, *pParam;
std::ostringstream cmdLine;
cmdLine << "";
if (XMLAppElement)
{
pName = XMLAppElement->FirstChildElement("name");
cmdLine << "otbcli_" << pName->GetText();
#ifdef _WIN32
cmdLine << ".bat";
#endif
cmdLine << " ";
// Parse application parameters
pParam = XMLAppElement->FirstChildElement("parameter");
while (pParam)
{
// Get parameter key
cmdLine << "-";
cmdLine << pParam->FirstChildElement("key")->GetText();
cmdLine << " ";
// Some parameters can have multiple values. Test it and handle this
// specific case
TiXmlElement* values = pParam->FirstChildElement("values");
if (values)
{
// Loop over value
TiXmlElement* pValue = values->FirstChildElement("value");
while (pValue)
{
cmdLine << pValue->GetText();
cmdLine << " ";
pValue = pValue->NextSiblingElement(); // iteration over multiple values
}
}
else
{
// Get parameter value
cmdLine << pParam->FirstChildElement("value")->GetText();
cmdLine << " ";
// In case of OutputImageparameter we need to report output pixel type
TiXmlElement* pPixType = pParam->FirstChildElement("pixtype");
if (pPixType)
{
cmdLine << pPixType->GetText();
cmdLine << " ";
}
}
pParam = pParam->NextSiblingElement(); // iteration over parameters
}
}
return cmdLine.str();
}
} //end namespace wrapper
} //end namespace otb
......@@ -22,12 +22,18 @@
#define otbWrapperQtWidgetMainWindow_h
#include <QMainWindow>
#include "OTBQtWidgetExport.h"
#include "otbWrapperApplication.h"
namespace Ui {
class AppMainWindow;
}
class QAction;
class QMenu;
class QPlainTextEdit;
namespace otb
{
......@@ -41,16 +47,26 @@ class OTBQtWidget_EXPORT QtMainWindow : public QMainWindow
Q_OBJECT
public:
QtMainWindow(Application::Pointer app, QtWidgetView* gui, QWidget* parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
QtMainWindow(Application::Pointer app, QtWidgetView* gui, QWidget* parent = nullptr);
~QtMainWindow();
otb::Wrapper::QtWidgetView* Gui() const;
void closeEvent(QCloseEvent* event) override;
QtWidgetView* Gui() const;
signals:
void ExecuteAndWriteOutput();
void Stop();
public slots:
void UnhandledException(QString message);
void UpdateMessageAfterApplicationReady(bool val);
void UpdateMessageAfterExecution(int status);
void on_executeButton_clicked();
void CopyCommandLine();
private:
QMenu* helpMenu;
QAction* helpAction;
::Ui::AppMainWindow* ui;
QtWidgetView* gui;
};
......
......@@ -37,17 +37,17 @@ class OTBQtWidget_EXPORT AppliThread : public QThread
Q_OBJECT
public:
AppliThread(Application* app)
AppliThread(Application::Pointer app) :
m_Application(app)
{
m_Application = app;
}
~AppliThread() override;
void Execute()
/** Ask the running application to stop */
void Stop()
{
// Call the signal start to begin running the program
start();
m_Application->Stop();
}
signals:
......@@ -66,13 +66,6 @@ signals:
*/
void ExceptionRaised( QString what );
public slots:
/** Ask the running application to stop */
void Stop()
{
m_Application->Stop();
}
protected:
void run() override;
......@@ -107,6 +100,10 @@ public:
return m_LogOutput;
}
bool IsRunning() const;
void Stop();
/** Logger warning message sender */
void SendLogWARNING( const std::string & mes );
/** Logger info message sender */
......@@ -144,8 +141,6 @@ signals:
void UpdateGui();
void Stop();
public slots:
/**
* \brief Slots called every time one of the widget needs to be
......@@ -168,19 +163,18 @@ private slots:
*/
void OnApplicationExecutionDone( int status );
void TimerDone();
private:
QtWidgetModel(const QtWidgetModel&) = delete;
void operator=(const QtWidgetModel&) = delete;
Application::Pointer m_Application;
QtLogOutput::Pointer m_LogOutput;
AppliThread* m_taskAppli;
bool m_IsRunning;
QTimer *m_Timer;
public:
Application::Pointer m_Application;
};
......
/*
* Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef otbWrapperQtWidgetProgressReport_h
#define otbWrapperQtWidgetProgressReport_h
#include <QtWidgets>
#include "otbWrapperQtWidgetModel.h"
#include "itkQtProgressBar.h"
#include "itkProcessObject.h"
#include <string>
namespace otb
{
namespace Wrapper
{
/** \class QtWidgetProgressReport
* \brief Create a widget reporting the progress of the application
* process.
*
* \ingroup OTBQtWidget
*/
class OTBQtWidget_EXPORT QtWidgetProgressReport : public QWidget
{
Q_OBJECT
public:
QtWidgetProgressReport(QtWidgetModel * model, QWidget * parent);
~QtWidgetProgressReport() override;
void SetApplication(Application::Pointer app);
typedef itk::MemberCommand< QtWidgetProgressReport > AddProcessCommandType;
void ProcessEvent( itk::Object * caller, const itk::EventObject & event );
std::string GetCurrentDescription()
{
return m_CurrentDescription;
}
/*
itk::ProcessObject* GetCurrentProcess()
{
return m_CurrentProcess;
}
QtWidgetModel * GetModel()
{
m_Model;
}
QVBoxLayout * GetLayout()
{
return m_Layout;
}
*/
public slots:
void RemoveLayout();
/*virtual */void ReportProcess();
signals:
void AddNewProcessToReport();
private:
QtWidgetProgressReport(const QtWidgetProgressReport&) = delete;
void operator=(const QtWidgetProgressReport&) = delete;
Application::Pointer m_Application;
QtWidgetModel * m_Model;
QVBoxLayout * m_Layout;
AddProcessCommandType::Pointer m_AddProcessCommand;
itk::ProcessObject* m_CurrentProcess;
std::string m_CurrentDescription;
};
}
}
#endif
......@@ -39,14 +39,14 @@ namespace Wrapper
*
* \ingroup OTBQtWidget
*/
class OTBQtWidget_EXPORT QtWidgetSimpleProgressReport : public QWidget
class OTBQtWidget_EXPORT QtWidgetSimpleProgressReport : public itk::QtProgressBar
{
Q_OBJECT
public:
QtWidgetSimpleProgressReport(QtWidgetModel * model, QWidget * parent);
QtWidgetSimpleProgressReport(QWidget* parent);
~QtWidgetSimpleProgressReport() override;
void SetApplication(Application::Pointer app);
void SetModel(QtWidgetModel* model);
typedef itk::MemberCommand< QtWidgetSimpleProgressReport > AddProcessCommandType;
......@@ -56,25 +56,17 @@ public slots:
void Init();
void ReportProcess();
signals:
signals:
void AddNewProcessToReport();
void SetText(QString);
private:
QtWidgetSimpleProgressReport(const QtWidgetSimpleProgressReport&) = delete;
void operator=(const QtWidgetSimpleProgressReport&); //purposely not
//implemented
Application::Pointer m_Application;
QtWidgetModel * m_Model;
QVBoxLayout * m_Layout;
void operator=(const QtWidgetSimpleProgressReport&) = delete;
AddProcessCommandType::Pointer m_AddProcessCommand;
itk::ProcessObject* m_CurrentProcess;
std::string m_CurrentDescription;
itk::QtProgressBar * m_Bar;
QLabel * m_Label;
};
}
......
......@@ -44,10 +44,6 @@ class OTBQtWidget_EXPORT QtWidgetView :
{
Q_OBJECT
Q_PROPERTY( bool isClosable
READ IsClosable
WRITE SetClosable );
public:
static char const * const OBJECT_NAME;
......@@ -66,12 +62,12 @@ public:
/** \brief Model Accessor */
QtWidgetModel* GetModel() const;
bool IsClosable() const;
virtual bool BeforeExecuteButtonClicked() { return true; }
void UnhandledException(QString message);
void Disable();
void Enable();
signals:
void QuitSignal();
void ExecuteAndWriteOutput();
void Stop();
void OTBApplicationOutputImageChanged( const QString &, const QString &);
......@@ -83,24 +79,10 @@ protected:
virtual QWidget* CreateInputWidgets();
// QWidget overloads.
void closeEvent( QCloseEvent * event ) override;
protected:
/** Html section for 'Done' icon */
std::string m_IconPathDone;
/** Html section for 'Failed' icon */
std::string m_IconPathFailed;
protected slots:
virtual void OnExecButtonClicked();
virtual void OnExecButtonClicked() {}
virtual void OnExceptionRaised( QString what );
// Private methods.
private:
QtWidgetView(const QtWidgetView&) = delete;
......@@ -108,29 +90,10 @@ private:
QWidget* CreateFooter();
// Private attributes.
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:
void UpdateMessageAfterExecution(int status);
void UpdateMessageAfterApplicationReady(bool val);
void OnProgressReportBegin();
void OnProgressReportEnd( int status );
void SetClosable( bool );
};
} // end namespace 'Wrapper'
......
......@@ -44,7 +44,6 @@ set(OTBQtWidget_SRC
otbWrapperQtWidgetParameterGroup.cxx
otbWrapperQtWidgetInputFilenameListParameter.cxx
otbWrapperQtWidgetRAMParameter.cxx
otbWrapperQtWidgetProgressReport.cxx
otbWrapperQtWidgetOutputProcessXMLParameter.cxx
otbWrapperQtWidgetParameterBase.cxx
otbWrapperQtWidgetInputImageParameter.cxx
......@@ -79,7 +78,6 @@ set(OTBQtWidget_MOC_HDR
../include/otbWrapperQtWidgetModel.h
../include/otbWrapperQtWidgetView.h
../include/otbWrapperQtWidgetMainWindow.h
../include/otbWrapperQtWidgetProgressReport.h
../include/otbWrapperQtWidgetListViewParameter.h
../include/otbQtFileSelectionWidget.h
../include/otbQtStringSelectionWidget.h
......@@ -101,6 +99,7 @@ set(OTBQtWidget_MOC_HDR
set( OTBQtWidget_FORMS
otbWrapperQtWidgetListEditWidget.ui
appmainwindow.ui
)
set( OTBQtWidget_RESOURCES
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AppMainWindow</class>
<widget class="QMainWindow" name="AppMainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>900</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowIcon">
<iconset resource="otbWrapperQtWidgetIcons.qrc">
<normaloff>:/Utilities/Data/Icons/monteverdi-48x48.png</normaloff>:/Utilities/Data/Icons/monteverdi-48x48.png</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>16</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab1">
<attribute name="title">
<string>Parameters</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>16</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>864</width>
<height>425</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>16</number>
</property>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab2">
<attribute name="title">
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>16</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="message">
<property name="text">
<string>Status text</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>16</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="otb::Wrapper::QtWidgetSimpleProgressReport" name="progressBar">
<property name="enabled">
<bool>true</bool>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="executeButton">
<property name="text">
<string>Execute</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>900</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuApplication">
<property name="title">
<string>Application</string>
</property>
<addaction name="separator"/>
<addaction name="actionCopy_command_line"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionDocumentation"/>
</widget>
<addaction name="menuApplication"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusBar">
<property name="styleSheet">
<string notr="true">color: rgb(85, 87, 83);</string>
</property>
</widget>
<action name="actionDocumentation">
<property name="text">
<string>Documentation</string>
</property>
<property name="shortcut">
<string>F1</string>
</property>
</action>
<action name="actionAboutOTB">
<property name="text">
<string>About</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
<action name="actionView_log">
<property name="text">
<string>View log</string>
</property>
</action>
<action name="actionLoad_parameters">
<property name="text">
<string>Load parameters</string>
</property>
</action>
<action name="actionSave_parameters">
<property name="text">
<string>Save parameters</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionReset_parameters">
<property name="text">
<string>Reset parameters</string>
</property>
</action>
<action name="actionReset">
<property name="text">
<string>Reset All</string>
</property>
</action>
<action name="actionLoad_from_XML">
<property name="text">
<string>Load from XML</string>
</property>
</action>
<action name="actionSave_to_XML">
<property name="text">
<string>Save to XML</string>
</property>
</action>
<action name="actionCopy_command_line">
<property name="text">
<string>Copy command line to clipboard</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>otb::Wrapper::QtWidgetSimpleProgressReport</class>
<extends>QProgressBar</extends>
<header>otbWrapperQtWidgetSimpleProgressReport.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="otbWrapperQtWidgetIcons.qrc"/>
</resources>
<connections/>
</ui>
......@@ -2,5 +2,6 @@
<qresource>
<file>../../../../Utilities/Data/Icons/mIconClearText.png</file>
<file>../../../../Utilities/Data/Icons/mIconClearTextHover.png</file>
<file>../../../../Utilities/Data/Icons/monteverdi-48x48.png</file>
</qresource>
</RCC>
......@@ -120,7 +120,6 @@ void QtWidgetListViewParameter::DoCreateWidget()
m_VLayout = new QHBoxLayout;
m_VLayout->setContentsMargins(0, 0, 0, 0);
m_VLayout->addWidget(m_ListView);
m_ListView->setMaximumSize(m_ListView->width() , 4* m_LineHeight);
m_VLayout->activate();
this->setLayout(m_VLayout);
......@@ -144,6 +143,9 @@ void QtWidgetListViewParameter::SelectedItems()
// make sure parameter is enabled
m_ListViewParam->SetActive(true);
m_ListViewParam->SetUserValue(true);
// Call the application DoUpdateParameters, then all widgets' DoUpdateGUI (including this one)
this->GetModel()->NotifyUpdate();
}
}
......
......@@ -21,44 +21,146 @@
#include "otbWrapperQtWidgetMainWindow.h"
#include <QtWidgets>
#include "otbWrapperQtWidgetView.h"
#include "otbWrapperQtWidgetOutputProcessXMLParameter.h"
#include "ui_appmainwindow.h"
namespace otb
{
namespace Wrapper
{
QtMainWindow::QtMainWindow(Application::Pointer app, QtWidgetView* gui, QWidget* parent, Qt::WindowFlags flags) :
QMainWindow(parent, flags),
QtMainWindow::QtMainWindow(Application::Pointer app, QtWidgetView* gui, QWidget* parent) :
QMainWindow(parent),
ui(new Ui::AppMainWindow),
gui(gui)
{
this->setWindowIcon(QIcon(":/otb_small.png"));
this->setWindowTitle(QString(app->GetDocName()).append(" - ").append(OTB_VERSION_STRING));
ui->setupUi(this);
// Setup the "View command line" widget
this->setWindowTitle(QString(app->GetName()).append(" - OTB ").append(OTB_VERSION_STRING));
// Set the given application view widget
gui->setParent(this);
this->setCentralWidget(gui);
// Connect the View "Quit" signal, to the mainWindow close slot
connect(gui, &QtWidgetView::QuitSignal, this, &QMainWindow::close);
// Setup the help menu
QMenu* helpMenu = this->menuBar()->addMenu(tr("&Help"));
helpAction = new QAction(tr("&Documentation"), this);
helpAction->setShortcuts(QKeySequence::HelpContents);
helpMenu->addAction(helpAction);
const std::string url = std::string("https://www.orfeo-toolbox.org/CookBook/Applications/app_") + app->GetName() + std::string(".html");
QObject::connect(helpAction, &QAction::triggered, this, [=] { QDesktopServices::openUrl(QUrl(QString::fromStdString(url))); });
ui->scrollArea->setWidget(gui);
// Connect menu buttons
connect(ui->actionQuit, &QAction::triggered, this, &QMainWindow::close);
const auto url = std::string("https://www.orfeo-toolbox.org/CookBook/Applications/app_") + app->GetName() + std::string(".html");
connect(ui->actionDocumentation, &QAction::triggered, this, [=] { QDesktopServices::openUrl(QUrl(QString::fromStdString(url))); });
connect(ui->actionCopy_command_line, &QAction::triggered, this, &QtMainWindow::CopyCommandLine);
// Setup execute / cancel button
ui->executeButton->setDefault(true);
ui->executeButton->setEnabled(false);
ui->executeButton->setText(QObject::tr("Execute"));
connect(gui->GetModel(), &QtWidgetModel::SetApplicationReady, ui->executeButton, &QPushButton::setEnabled);
connect(this, &QtMainWindow::ExecuteAndWriteOutput, gui->GetModel(), &QtWidgetModel::ExecuteAndWriteOutputSlot);
connect( gui->GetModel(), &QtWidgetModel::SetApplicationReady, this, &QtMainWindow::UpdateMessageAfterApplicationReady );
connect( gui->GetModel(), &QtWidgetModel::SetProgressReportDone, this, &QtMainWindow::UpdateMessageAfterExecution );
connect(gui->GetModel(), &QtWidgetModel::ExceptionRaised, [&] { ui->tabWidget->setCurrentIndex(1); });
// Status bar and message default text
ui->statusBar->showMessage(tr("Select parameters"));
ui->message->setText("");
// Setup the progress bar to observe the model
ui->progressBar->SetModel(gui->GetModel());
// Connect application progress text to the QLabel
connect(ui->progressBar, &QtWidgetSimpleProgressReport::SetText, ui->message, &QLabel::setText);
// Connect log output to the textEdit area
connect(gui->GetModel()->GetLogOutput(), &QtLogOutput::NewContentLog, ui->plainTextEdit, &QPlainTextEdit::appendPlainText);
}
QtWidgetView* QtMainWindow::Gui() const
void QtMainWindow::UpdateMessageAfterApplicationReady( bool val )
{
if (!gui->GetModel()->IsRunning())
{
if (val == true)
{
ui->statusBar->showMessage(tr("Ready to run"));
}
else
{
ui->statusBar->showMessage(tr("Select parameters"));
}
}
}
void QtMainWindow::UpdateMessageAfterExecution(int status)
{
if (status >= 0)
{
ui->statusBar->showMessage(tr("Done"));
}
else
{
ui->statusBar->showMessage(tr("Failed!"));
}
ui->executeButton->setText(tr("Execute"));
gui->Enable();
}
void QtMainWindow::on_executeButton_clicked()
{
if (gui->GetModel()->IsRunning())
{
ui->statusBar->showMessage(tr("Cancelling..."));
gui->GetModel()->Stop();
}
else
{
if (gui->BeforeExecuteButtonClicked())
{
gui->Disable();
ui->statusBar->showMessage(tr("Running..."));
ui->executeButton->setText(tr("Cancel"));
emit ExecuteAndWriteOutput();
}
}
}
void QtMainWindow::CopyCommandLine()
{
// Get command line
std::string cmdLine = OutputProcessXMLParameter::MakeCommandLine(gui->GetModel()->m_Application);
// Copy it to clipboard
QClipboard* clipboard = QGuiApplication::clipboard();
clipboard->setText(QString::fromStdString(cmdLine));
// Also show it in the log
gui->GetModel()->SendLogINFO(cmdLine);
}
QtMainWindow::~QtMainWindow()
{
delete ui;
}
otb::Wrapper::QtWidgetView* QtMainWindow::Gui() const
{
return gui;
}
void QtMainWindow::UnhandledException(QString message)
{
gui->UnhandledException(message);
ui->plainTextEdit->appendPlainText(message);
ui->tabWidget->setCurrentIndex(1);
}
void QtMainWindow::closeEvent(QCloseEvent* event)
{
gui->GetModel()->Stop();
QMainWindow::closeEvent(event);
}
} // namespace Wrapper
......
......@@ -33,9 +33,10 @@ namespace Wrapper
QtWidgetModel
::QtWidgetModel(Application* app) :
m_Application(app),
m_LogOutput(),
m_IsRunning(false)
m_taskAppli(nullptr),
m_IsRunning(false),
m_Application(app)
{
// Init only if not already done
if(!m_Application->IsInitialized())
......@@ -47,23 +48,19 @@ QtWidgetModel
// Attach log output to the Application logger
m_Application->GetLogger()->AddLogOutput(m_LogOutput);
m_Timer = new QTimer(this);
m_Timer->setSingleShot(true);
m_Timer->setInterval(1000);
QObject::connect( m_Timer, &QTimer::timeout, this, &QtWidgetModel::TimerDone );
}
QtWidgetModel::~QtWidgetModel()
{
if (m_Timer)
delete m_Timer;
delete m_taskAppli;
}
void
QtWidgetModel
::NotifyUpdate()
{
assert(!m_IsRunning && "Cannot update parameters while application is running.");
// Update the parameters
try
{
......@@ -118,108 +115,41 @@ QtWidgetModel
emit SetApplicationReady(false);
m_IsRunning = true;
//Buld corresponding command line and display to the Log tab
//Build XML DOM from m_application
OutputProcessXMLParameter::Pointer outXMLParam = OutputProcessXMLParameter::New();
TiXmlElement* XMLAppElement = outXMLParam->ParseApplication(m_Application);
//Create command line from the XML document
TiXmlElement * pName, *pParam;
std::ostringstream cmdLine;
cmdLine << "";
if(XMLAppElement)
{
pName = XMLAppElement->FirstChildElement("name");
cmdLine << "otbcli_" << pName->GetText();
#ifdef _WIN32
cmdLine << ".bat";
#endif
cmdLine << " ";
//Parse application parameters
pParam = XMLAppElement->FirstChildElement("parameter");
while(pParam)
{
//Get parameter key
cmdLine << "-";
cmdLine << pParam->FirstChildElement("key")->GetText();
cmdLine << " ";
//Some parameters can have multiple values. Test it and handle this
//specific case
TiXmlElement * values = pParam->FirstChildElement("values");
if (values)
{
//Loop over value
TiXmlElement * pValue = values->FirstChildElement("value");
while(pValue)
{
cmdLine << pValue->GetText();
cmdLine << " ";
pValue = pValue->NextSiblingElement(); // iteration over multiple values
}
}
else
{
//Get parameter value
cmdLine << pParam->FirstChildElement("value")->GetText();
cmdLine << " ";
//In case of OutputImageparameter we need to report output pixel type
TiXmlElement * pPixType = pParam->FirstChildElement("pixtype");
if (pPixType)
{
cmdLine << pPixType->GetText();
cmdLine << " ";
}
}
pParam = pParam->NextSiblingElement(); // iteration over parameters
}
//Insert a new line character at the end of the command line
cmdLine << std::endl;
//Report the command line string to the application logger
m_Application->GetLogger()->Write(itk::LoggerBase::INFO, cmdLine.str());
}