OpenWalnut  1.5.0dev
WQtTreeItem.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <memory>
26 #include <set>
27 #include <string>
28 #include <vector>
29 
30 #include <QApplication>
31 
32 #include "../WMainWindow.h"
33 #include "../WQtGui.h"
34 #include "../events/WEventTypes.h"
35 #include "../events/WModuleConnectorEvent.h"
36 #include "../events/WModuleDeleteEvent.h"
37 #include "../events/WPropertyChangedEvent.h"
38 #include "WQtControlPanel.h"
39 #include "WQtTreeItem.h"
40 #include "WTreeItemTypes.h"
41 #include "core/common/WLogger.h"
42 #include "core/common/WProgress.h"
43 #include "core/common/WProgressCombiner.h"
44 #include "core/kernel/WKernel.h"
45 #include "core/kernel/WModuleInputConnector.h"
46 #include "core/kernel/WModuleOutputConnector.h"
47 
48 WQtTreeItem::WQtTreeItem( QTreeWidgetItem * parent, WTreeItemType type, std::shared_ptr< WModule > module ) :
49  QTreeWidgetItem( parent, type ),
50  m_deleteInProgress( false ),
51  m_needPostDeleteEvent( true ),
52  m_handledInput( "" )
53 {
54  m_module = module;
55  m_name = module->getName();
56 
57  if( module->getProperties()->getProperty( "active" )->toPropBool()->get() )
58  {
59  this->setCheckState( 0, Qt::Checked );
60  }
61  else
62  {
63  this->setCheckState( 0, Qt::Unchecked );
64  }
65 
66  this->setFlags( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
67 
68  // grab the runtime name property
69  // replace the name by the filename
70  std::shared_ptr< WPropertyBase > p = module->getProperties()->findProperty( "Name" );
71 
72  // always ensure that findProperty really found something
73  if( p )
74  {
75  m_nameProp = p->toPropString();
76  }
77 
78  // was it a string prop?
79  if( m_nameProp )
80  {
81  m_name = m_nameProp->get( true );
82  m_nameProp->getUpdateCondition()->subscribeSignal( boost::bind( &WQtTreeItem::nameChanged, this ) );
83  }
84 
85  m_updateTimer = std::shared_ptr< QTimer >( new QTimer() );
86  connect( m_updateTimer.get(), SIGNAL( timeout() ), this, SLOT( update() ) );
87  m_updateTimer->start( 500 );
88 
89  // we need to get informed about updated outputs.
90  const WModule::OutputConnectorList& outs = module->getOutputConnectors();
91  t_GenericSignalHandlerType changeSignal = boost::bind( &WQtTreeItem::slotDataChanged, this, boost::placeholders::_2 );
92  for( WModule::OutputConnectorList::const_iterator iter = outs.begin(); iter != outs.end(); ++iter )
93  {
94  // subscribe each connectors update signal
95  m_outputUpdateConnections.push_back( ( *iter )->subscribeSignal( DATA_CHANGED, changeSignal ) );
96  }
97 }
98 
100 {
101  // disconnect each subscription
102  for( std::vector< boost::signals2::connection >::iterator iter = m_outputUpdateConnections.begin();
103  iter != m_outputUpdateConnections.end(); ++iter )
104  {
105  ( *iter ).disconnect();
106  }
107 }
108 
109 std::shared_ptr< WModule > WQtTreeItem::getModule()
110 {
111  return m_module;
112 }
113 
114 std::string WQtTreeItem::getName()
115 {
116  return m_name;
117 }
118 
120 {
121  // create the tooltip text
122  std::string tooltip = "";
123  tooltip += "<b>Module: </b>" + module->getName() + "<br/>";
124  if( module->isCrashed()() )
125  {
126  tooltip += "<b>State: </b>crashed<br/>";
127  tooltip += "<b>Crash-Message: </b>" + module->getCrashMessage() + "<br/>";
128  }
129  else
130  {
131  tooltip += "<b>State: </b>normal<br/>";
132  }
133  tooltip += "<b>Connectors: </b>";
134 
135  // also list the connectors
136  std::string conList = "";
137  WModule::InputConnectorList consIn = module->getInputConnectors();
138  WModule::OutputConnectorList consOut = module->getOutputConnectors();
139  conList += "<table><tr><th>Name</th><th>Description</th><th>Type (I/O)</th><th>Connected</th></tr>";
140  int conCount = 0;
141  for( WModule::InputConnectorList::const_iterator it = consIn.begin(); it != consIn.end(); ++it )
142  {
143  ++conCount;
144  conList += "<tr><td><b>" + ( *it )->getName() + "&nbsp;</b></td><td>" + ( *it )->getDescription() + "&nbsp;</td>";
145  conList += "<td><center>In</center></td>";
146  conList += ( *it )->isConnected() ? "<td><center>Yes</center></td>" : "<td><center>No</center></td>";
147  conList += "</tr>";
148  }
149  for( WModule::OutputConnectorList::const_iterator it = consOut.begin(); it != consOut.end(); ++it )
150  {
151  ++conCount;
152  conList += "<tr><td><b>" + ( *it )->getName() + "&nbsp;</b></td><td>" + ( *it )->getDescription() + "&nbsp;</td>";
153  conList += "<td><center>Out</center></td>";
154  conList += ( *it )->isConnected() ? "<td></center>Yes</center></td>" : "<td><center>No</center></td>";
155  conList += "</tr>";
156  }
157  conList += "</table>";
158 
159  tooltip += conCount ? "Yes" + conList + "<br/><br/>" : "None<br/>";
160  tooltip += "<b>Module Description: </b><br/>" + module->getMetaInformation()->getDescription();
161 
162  return tooltip;
163 }
164 
165 void WQtTreeItem::slotDataChanged( std::shared_ptr<WModuleConnector> connector )
166 {
167  // post event
168  QCoreApplication::postEvent( WQtGui::getMainWindow()->getControlPanel(), new WModuleConnectorEvent( m_module, connector ) );
169 }
170 
172 {
173  updateState();
174 }
175 
177 {
178  std::shared_ptr< WProgressCombiner> p = m_module->getRootProgressCombiner();
179 
180  // update the progress combiners internal state
181  p->update();
182 
183  std::string connInfo = "";
184  if( ( m_handledOutput != "" ) && ( m_handledInput != "" ) )
185  {
186  connInfo = " (" + m_handledOutput + "->" + m_handledInput + ") ";
187  }
188 
189  // is it pending?
190  std::string progress = "Waiting";
191  if( m_module->isCrashed()() )
192  {
193  progress = "Problem occurred";
194  setText( 0, ( m_name + " (problem occurred)" + connInfo ).c_str() );
195 
196  // strike out the name of the module to show the crash visually.
197  QFont curFont = font( 0 );
198  curFont.setStrikeOut( true );
199  setFont( 0, curFont );
200  setIcon( 0, WQtGui::getMainWindow()->getIconManager()->getIcon( "moduleCrashed" ) );
201 
202  // this ensures that crashed modules can be deleted
203  setDisabled( false );
204  }
205  else if( p->isPending() )
206  {
207  progress = "Busy " + p->getCombinedNames();
208  setIcon( 0, WQtGui::getMainWindow()->getIconManager()->getIcon( "moduleBusy" ) );
209  std::ostringstream progressText;
210 
211  // construct a name for the progress indicator
212  std::string name = p->getName();
213  if( !name.empty() )
214  {
215  name = " [" + name + "]";
216  }
217 
218  if( p->isDetermined() )
219  {
220  progressText.setf( std::ios::fixed );
221  progressText.precision( 0 );
222  progressText << p->getProgress() << "%" << name;
223  }
224  else
225  {
226  progressText << "Pending" << name;
227  }
228 
229  setText( 0, ( m_name + " - " + progressText.str() + connInfo ).c_str() );
230  }
231  else
232  {
233  setIcon( 0, QIcon() );
234  setText( 0, ( m_name + connInfo ).c_str() );
235  }
236 
237  // if the user requested it to be deleted: disable and color it
238  if( m_deleteInProgress )
239  {
240  setForeground( 0, QBrush( QColor::fromRgb( 255, 0, 0 ) ) );
241  setDisabled( true );
242  }
243 
244  // is finished?
245  if( m_deleteInProgress && !m_module->isRunning().get() && m_needPostDeleteEvent )
246  {
247  m_needPostDeleteEvent = false; // this ensures the event is only posted once
248  QCoreApplication::postEvent( WQtGui::getMainWindow()->getNetworkEditor(), new WModuleDeleteEvent( this ) );
249  QCoreApplication::postEvent( WQtGui::getMainWindow()->getControlPanel(), new WModuleDeleteEvent( this ) );
250  }
251 
252  // active ?
253  if( m_module->getProperties()->getProperty( "active" )->toPropBool()->get() )
254  {
255  setCheckState( 0, Qt::Checked );
256  }
257  else
258  {
259  setCheckState( 0, Qt::Unchecked );
260  }
261 
262  // update tooltip
263  setToolTip( 0, WQtTreeItem::createTooltip( m_module ).c_str() );
264 }
265 
267 {
268  // this ensures a visual feedback to the user while waiting for the module to finish.
269 
270  // update tree item state
271  m_deleteInProgress = true;
272 }
273 
275 {
276  // luckily, the update mechanism of WQtTreeItem regularly sets the name using m_name. So we do not even need to post some kind of event.
277  m_name = m_nameProp->get( true );
278 }
279 
280 std::string WQtTreeItem::getHandledInput() const
281 {
282  return m_handledInput;
283 }
284 
285 void WQtTreeItem::setHandledInput( std::string in )
286 {
287  m_handledInput = in;
288 }
289 
290 std::string WQtTreeItem::getHandledOutput() const
291 {
292  return m_handledOutput;
293 }
294 
295 void WQtTreeItem::setHandledOutput( std::string out )
296 {
297  m_handledOutput = out;
298 }
299 
301 {
302  // active ?
303  if( checkState( 0 ) == Qt::Checked )
304  {
305  m_module->getProperties()->getProperty( "active" )->toPropBool()->set( true );
306  }
307  else
308  {
309  m_module->getProperties()->getProperty( "active" )->toPropBool()->set( false );
310  }
311 }
312 
Event signalling a module connector changed its data.
Event signalling a module item should be deleted.
std::shared_ptr< WModule > SPtr
Shared pointer to a WModule.
Definition: WModule.h:106
std::vector< std::shared_ptr< WModuleOutputConnector > > OutputConnectorList
The type for the list of output connectors.
Definition: WModule.h:101
std::vector< std::shared_ptr< WModuleInputConnector > > InputConnectorList
The type for the list of input connectors.
Definition: WModule.h:96
static WMainWindow * getMainWindow()
Returns the current main window instance or NULL if not existent.
Definition: WQtGui.cpp:88
std::vector< boost::signals2::connection > m_outputUpdateConnections
The output connector update connections.
Definition: WQtTreeItem.h:185
std::shared_ptr< WModule > m_module
The module represented by this tree item.
Definition: WQtTreeItem.h:175
std::string m_name
Name of the tree item.
Definition: WQtTreeItem.h:144
WModule::SPtr getModule()
Get for the module pointer.
void setHandledOutput(std::string out)
Sets the name of the output represented by this item.
virtual ~WQtTreeItem()
Destructor.
Definition: WQtTreeItem.cpp:99
std::string getHandledOutput() const
The name of the output represented by this item.
std::string getHandledInput() const
The name of the input represented by this item.
std::string getName()
Returns the name used for this tree item.
void nameChanged()
Called when the name property changes.
void slotDataChanged(std::shared_ptr< WModuleConnector > connector)
Called on output-connector update.
bool m_deleteInProgress
True if the treeitem and the module gets deleted currently.
Definition: WQtTreeItem.h:149
virtual void updateState()
Updates the state of the tree item basing on the module's state.
static std::string createTooltip(WModule::SPtr module)
Create tooltip for a given module.
std::shared_ptr< QTimer > m_updateTimer
Updates this item in regular intervals.
Definition: WQtTreeItem.h:139
virtual void gotRemoved()
Gets called by the GUI whenever the module was removed from the root container and should now be dele...
void update()
Gets called by m_updateTimer in some interval to update the item state, basing on the state of m_modu...
WQtTreeItem(QTreeWidgetItem *parent, WTreeItemType type, std::shared_ptr< WModule > module)
Constructor creates an empty item.
Definition: WQtTreeItem.cpp:48
void setHandledInput(std::string in)
Sets the name of the input represented by this item.
std::string m_handledOutput
The output name handled by this item.
Definition: WQtTreeItem.h:169
bool m_needPostDeleteEvent
True if no delete event has been posted yet.
Definition: WQtTreeItem.h:154
std::string m_handledInput
The name of the input connector represented by this item.
Definition: WQtTreeItem.h:164
virtual void handleCheckStateChange()
Handle changes in check state.
WPropString m_nameProp
The property containing the name of the module.
Definition: WQtTreeItem.h:159