Commit bb01f998 by Sebastian Eichelbaum

[CHANGE] - prepared the GUI and module container for deep removal of modules.

parent d8ae0784
......@@ -48,6 +48,7 @@
#include "events/WRoiAssocEvent.h"
#include "events/WRoiRemoveEvent.h"
#include "events/WModuleReadyEvent.h"
#include "events/WModuleRemovedEvent.h"
#include "events/WModuleCrashEvent.h"
#include "events/WUpdateTextureSorterEvent.h"
......@@ -156,10 +157,19 @@ int WQt4Gui::run()
WDataHandler::getDefaultSubject()->getListChangeCondition()->subscribeSignal( newDatasetSignal );
// bind the GUI's slot with the ready signal
// Assoc Event
t_ModuleGenericSignalHandlerType assocSignal = boost::bind( &WQt4Gui::slotAddDatasetOrModuleToBrowser, this, _1 );
m_kernel->getRootContainer()->addDefaultNotifier( WM_ASSOCIATED, assocSignal );
// Ready Event
t_ModuleGenericSignalHandlerType readySignal = boost::bind( &WQt4Gui::slotActivateDatasetOrModuleInBrowser, this, _1 );
m_kernel->getRootContainer()->addDefaultNotifier( WM_READY, readySignal );
// Remove Event
t_ModuleGenericSignalHandlerType removedSignal = boost::bind( &WQt4Gui::slotRemoveDatasetOrModuleInBrowser, this, _1 );
m_kernel->getRootContainer()->addDefaultNotifier( WM_REMOVED, removedSignal );
boost::function< void( boost::shared_ptr< WRMROIRepresentation > ) > assocRoiSignal =
boost::bind( &WQt4Gui::slotAddRoiToBrowser, this, _1 );
m_kernel->getRoiManager()->addAddNotifier( assocRoiSignal );
......@@ -268,6 +278,12 @@ void WQt4Gui::slotActivateDatasetOrModuleInBrowser( boost::shared_ptr< WModule >
QCoreApplication::postEvent( m_mainWindow, new WModuleReadyEvent( module ) );
}
void WQt4Gui::slotRemoveDatasetOrModuleInBrowser( boost::shared_ptr< WModule > module )
{
// create a new event for this and insert it into event queue
QCoreApplication::postEvent( m_mainWindow->getDatasetBrowser(), new WModuleRemovedEvent( module ) );
}
boost::shared_ptr< WModule > WQt4Gui::getSelectedModule()
{
return m_mainWindow->getDatasetBrowser()->getSelectedModule();
......
......@@ -109,6 +109,13 @@ public:
virtual void slotActivateDatasetOrModuleInBrowser( boost::shared_ptr< WModule > module );
/**
* Slot gets called whenever a module has been removed from the root container.
*
* \param module the module
*/
virtual void slotRemoveDatasetOrModuleInBrowser( boost::shared_ptr< WModule > module );
/**
* getter functions for the signales proved by the gui
*/
boost::signals2::signal1< void, std::vector< std::string > >* getLoadButtonSignal();
......
......@@ -46,6 +46,7 @@
#include "../events/WRoiRemoveEvent.h"
#include "../events/WModuleReadyEvent.h"
#include "../events/WModuleDeleteEvent.h"
#include "../events/WModuleRemovedEvent.h"
#include "../events/WEventTypes.h"
#include "../guiElements/WQtApplyModulePushButton.h"
#include "../WMainWindow.h"
......@@ -75,7 +76,7 @@ WQtDatasetBrowser::WQtDatasetBrowser( WMainWindow* parent )
// create context menu for tree items
m_deleteModuleAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "remove" ), "Remove Module", m_moduleTreeWidget );
connect( m_deleteModuleAction, SIGNAL( triggered() ), this, SLOT( m_deleteModuleTreeItem() ) );
connect( m_deleteModuleAction, SIGNAL( triggered() ), this, SLOT( deleteModuleTreeItem() ) );
m_moduleTreeWidget->addAction( m_deleteModuleAction );
m_textureSorter = new WQtTextureSorter( m_panel );
......@@ -208,20 +209,21 @@ bool WQtDatasetBrowser::event( QEvent* event )
}
// a module tree item should be deleted
if ( event->type() == WQT_MODULE_REMOVE_EVENT )
if ( event->type() == WQT_MODULE_DELETE_EVENT )
{
WModuleDeleteEvent* e = dynamic_cast< WModuleDeleteEvent* >( event ); // NOLINT
if ( !e )
{
// this should never happen, since the type is set to WQT_Ready_EVENT.
WLogger::getLogger()->addLogMessage( "Event is not an WModuleRemoveEvent although its type claims it. Ignoring event.",
WLogger::getLogger()->addLogMessage( "Event is not an WModuleDeleteEvent although its type claims it. Ignoring event.",
"DatasetBrowser", LL_WARNING );
return true;
}
// grab the module reference and print some info
boost::shared_ptr< WModule > module = e->getTreeItem()->getModule();
WLogger::getLogger()->addLogMessage( "Removing module \"" + module->getName() + "\" from Tree.", "DatasetBrowser", LL_DEBUG );
WLogger::getLogger()->addLogMessage( "Deleting module \"" + module->getName() + "\" from Tree.",
"DatasetBrowser", LL_DEBUG );
// remove it from the tree and free last ref count
m_moduleTreeWidget->deleteItem( e->getTreeItem() );
......@@ -236,6 +238,56 @@ bool WQtDatasetBrowser::event( QEvent* event )
return true;
}
// a module was removed from the container
if ( event->type() == WQT_MODULE_REMOVE_EVENT )
{
WModuleRemovedEvent* e = dynamic_cast< WModuleRemovedEvent* >( event ); // NOLINT
if ( !e )
{
// this should never happen, since the type is set to WQT_Ready_EVENT.
WLogger::getLogger()->addLogMessage( "Event is not an WModuleRemovedEvent although its type claims it. Ignoring event.",
"DatasetBrowser", LL_WARNING );
return true;
}
// iterate tree items and find proper one
QTreeWidgetItemIterator it( m_moduleTreeWidget );
while ( *it )
{
WQtTreeItem* item = dynamic_cast< WQtTreeItem* >( *it );
boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >();
if ( item )
{
module = item->getModule();
}
// if the pointer is NULL the item was none of the above
if ( !module.get() )
{
++it;
continue;
}
// we found it
if ( e->getModule() == module )
{
item->gotRemoved();
}
++it;
}
// be nice and print some info
WLogger::getLogger()->addLogMessage( "Removing module \"" + e->getModule()->getName() + "\" from Tree.", "DatasetBrowser", LL_DEBUG );
// stop the module
e->getModule()->requestStop();
WLogger::getLogger()->addLogMessage( "Waiting for module \"" + e->getModule()->getName() + "\" to finish before deleting.",
"DatasetBrowser", LL_DEBUG );
return true;
}
// a module changed its state to "ready" -> activate it in dataset browser
if ( event->type() == WQT_READY_EVENT )
{
......@@ -395,6 +447,7 @@ void WQtDatasetBrowser::selectTreeItem()
{
// TODO(schurade): qt doc says clear() doesn't delete tabs so this is possibly a memory leak
m_tabWidget->clear();
// the WQtToolbar also deletes the buttons!
m_mainWindow->getCompatiblesToolBar()->clearButtons();
boost::shared_ptr< WModule > module;
......@@ -716,8 +769,11 @@ void WQtDatasetBrowser::deleteModuleTreeItem()
if ( ( m_moduleTreeWidget->selectedItems().at( 0 )->type() == MODULE ) ||
( m_moduleTreeWidget->selectedItems().at( 0 )->type() == DATASET ) )
{
// instead of deleting the tree item directly -> inform the tree item and let it do the job:
static_cast< WQtTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) )->deleteSelf();
// remove from the container. It will create a new event in the GUI after it has been removed which is then handled by the tree item.
// This method deep removes the module ( it also removes depending modules )
WKernel::getRunningKernel()->getRootContainer()->removeDeep(
static_cast< WQtTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) )->getModule()
);
// select another item
m_moduleTreeWidget->setCurrentItem( m_moduleTreeWidget->topLevelItem( 0 ) );
}
......
......@@ -187,15 +187,11 @@ void WQtTreeItem::updateState()
updateTooltip( progress );
}
void WQtTreeItem::deleteSelf()
void WQtTreeItem::gotRemoved()
{
// instruct the kernel to remove module
WKernel::getRunningKernel()->getRootContainer()->remove( m_module );
// this ensures a visual feedback to the user while waiting for the module to finish.
// update tree item state
m_deleteInProgress = true;
// instruct the module to finish
m_module->requestStop();
}
......@@ -72,9 +72,9 @@ public:
std::string getName();
/**
* Initiates the item to delete itself from the tree. It also removes the underlying module to be deleted from the module graph.
* Gets called by the GUI whenever the module was removed from the root container and should now be deleted.
*/
virtual void deleteSelf();
virtual void gotRemoved();
public slots:
......
......@@ -54,7 +54,10 @@
// when a roi got removed
#define WQT_ROI_REMOVE_EVENT QEvent::User + 7
// when a module got deleted
// when a module got removed from the root container
#define WQT_MODULE_REMOVE_EVENT QEvent::User + 8
// when a module should be deleted finally.
#define WQT_MODULE_DELETE_EVENT QEvent::User + 9
#endif // WEVENTTYPES_H
......@@ -27,7 +27,7 @@
#include "WModuleDeleteEvent.h"
WModuleDeleteEvent::WModuleDeleteEvent( WQtTreeItem* treeItem )
: QEvent( static_cast< QEvent::Type >( WQT_MODULE_REMOVE_EVENT ) ),
: QEvent( static_cast< QEvent::Type >( WQT_MODULE_DELETE_EVENT ) ),
m_item( treeItem )
{
// initialize members
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WEventTypes.h"
#include "WModuleRemovedEvent.h"
WModuleRemovedEvent::WModuleRemovedEvent( boost::shared_ptr< WModule > module )
: QEvent( static_cast< QEvent::Type >( WQT_MODULE_REMOVE_EVENT ) ),
m_module( module )
{
// initialize members
}
WModuleRemovedEvent::~WModuleRemovedEvent()
{
// cleanup
}
boost::shared_ptr< WModule > WModuleRemovedEvent::getModule()
{
return m_module;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WMODULEREMOVEDEVENT_H
#define WMODULEREMOVEDEVENT_H
#include <boost/shared_ptr.hpp>
#include <QtCore/QEvent>
#include "../../../kernel/WModule.h"
/**
* Event signalling a module was removed from the kernel root container.
*/
class WModuleRemovedEvent: public QEvent
{
public:
/**
* Creates a new event instance denoting that the specified module got removed from the root container.
*
* \param module the module
*/
explicit WModuleRemovedEvent( boost::shared_ptr< WModule > module );
/**
* Destructor.
*/
virtual ~WModuleRemovedEvent();
/**
* Getter for the module that got removed.
*
* \return the module.
*/
boost::shared_ptr< WModule > getModule();
protected:
/**
* The module that got removed.
*/
boost::shared_ptr< WModule > m_module;
private:
};
#endif // WMODULEREMOVEDEVENT_H
......@@ -191,6 +191,23 @@ void WModuleContainer::remove( boost::shared_ptr< WModule > module )
m_moduleAccess->endWrite();
module->setAssociatedContainer( boost::shared_ptr< WModuleContainer >() );
// tell all interested about removal
boost::shared_lock<boost::shared_mutex> slock = boost::shared_lock<boost::shared_mutex>( m_removedNotifiersLock );
for ( std::list< t_ModuleGenericSignalHandlerType >::iterator iter = m_removedNotifiers.begin(); iter != m_removedNotifiers.end(); ++iter)
{
// call associated notifier
( *iter )( module );
}
slock.unlock();
}
void WModuleContainer::removeDeep( boost::shared_ptr< WModule > module )
{
WLogger::getLogger()->addLogMessage( "Deep removal of modules is not yet implemented.", "ModuleContainer (" + getName() + ")", LL_WARNING );
// at least, remove the module itself
remove( module );
}
WModuleContainer::DataModuleListType WModuleContainer::getDataModules()
......@@ -278,6 +295,11 @@ void WModuleContainer::addDefaultNotifier( MODULE_SIGNAL signal, t_ModuleGeneric
m_readyNotifiers.push_back( notifier );
lock.unlock();
break;
case WM_REMOVED:
lock = boost::unique_lock<boost::shared_mutex>( m_removedNotifiersLock );
m_removedNotifiers.push_back( notifier );
lock.unlock();
break;
default:
std::ostringstream s;
s << "Could not subscribe to unknown signal.";
......
......@@ -118,6 +118,14 @@ public:
virtual void remove( boost::shared_ptr< WModule > module );
/**
* As \ref remove, it removes the module from the container. In contrast to \ref remove, it also removes all the depending modules from the
* container.
*
* \param module the module which should be removed including all depending modules
*/
virtual void removeDeep( boost::shared_ptr< WModule > module );
/**
* Stops all modules inside this container. Note that this function could take some time, since it waits until the last module
* has quit.
*/
......@@ -303,6 +311,16 @@ protected:
std::list< t_ModuleGenericSignalHandlerType > m_associatedNotifiers;
/**
* Lock for remove-notifiers set.
*/
boost::shared_mutex m_removedNotifiersLock;
/**
* The notifiers connected to added modules by default and fired whenever the module got removed again.
*/
std::list< t_ModuleGenericSignalHandlerType > m_removedNotifiers;
/**
* Set of all threads that currently depend upon this container.
*/
std::set< boost::shared_ptr< WThreadedRunner > > m_pendingThreads;
......
......@@ -36,9 +36,10 @@ class WException;
*/
typedef enum
{
WM_ASSOCIATED, // module got associated to a container
WM_READY, // module ready
WM_ERROR // error during execution
WM_ASSOCIATED, // module got associated to a container
WM_READY, // module ready
WM_ERROR, // error during execution
WM_REMOVED // removed from the container
}
MODULE_SIGNAL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment