Commit cc2536e7 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[FIX] - custom widgets (incl. EEGView) crash on remove due to non-thread-safe...

[FIX] - custom widgets (incl. EEGView) crash on remove due to non-thread-safe programming. This is fixed now. Only one problem remaining: the widget is stored in a shared_ptr which might be deleted outside the GUI thread, causing the widget to use Qt commands outside the qt thread. XInitThreads fixes this for now but this should be fixed properly in the near future.
parent 4fe1bb72
......@@ -77,6 +77,7 @@
#include "events/WModuleReadyEvent.h"
#include "events/WModuleRemovedEvent.h"
#include "events/WOpenCustomDockWidgetEvent.h"
#include "events/WCloseCustomDockWidgetEvent.h"
#include "guiElements/WQtPropertyBoolAction.h"
#include "WQt4Gui.h"
#include "WQtCombinerToolbar.h"
......@@ -907,6 +908,20 @@ void WMainWindow::customEvent( QEvent* event )
ocdwEvent->getFlag()->set( widget );
}
if( event->type() == WCloseCustomDockWidgetEvent::CUSTOM_TYPE )
{
WCloseCustomDockWidgetEvent* closeEvent = static_cast< WCloseCustomDockWidgetEvent* >( event );
boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
if( m_customDockWidgets.count( closeEvent->getTitle() ) > 0 )
{
if( m_customDockWidgets[closeEvent->getTitle()]->decreaseUseCount() )
{
// custom dock widget should be deleted
m_customDockWidgets.erase( closeEvent->getTitle() );
}
}
}
else
{
// other event
......@@ -964,23 +979,13 @@ boost::shared_ptr< WQtCustomDockWidget > WMainWindow::getCustomDockWidget( std::
boost::shared_ptr< WQtCustomDockWidget > out = m_customDockWidgets.count( title ) > 0 ?
m_customDockWidgets[title] :
boost::shared_ptr< WQtCustomDockWidget >();
//m_customDockWidgetsLock.unlock();
return out;
}
void WMainWindow::closeCustomDockWidget( std::string title )
{
boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
if( m_customDockWidgets.count( title ) > 0 )
{
if( m_customDockWidgets[title]->decreaseUseCount() )
{
// custom dock widget should be deleted
m_customDockWidgets.erase( title );
}
}
//m_customDockWidgetsLock.unlock();
QCoreApplication::postEvent( this, new WCloseCustomDockWidgetEvent( title ) );
}
void WMainWindow::newRoi()
......
......@@ -120,7 +120,10 @@ public:
boost::shared_ptr< WQtCustomDockWidget > getCustomDockWidget( std::string name );
/**
* Close one of the custom dock widget saved in the map of customDockWidgets
* Close one of the custom dock widget saved in the map of customDockWidgets. This method is thread-safe and ensures that the widget is
* closed in the GUI thread. NEVER call this in the GUI thread. It will block the GUI.
*
* \note the widget might not be closed after this call. The widget is usage counted.
*
* \param title the title of the widget to close
*/
......
......@@ -65,6 +65,11 @@
#include "WQt4Gui.h"
#ifdef Q_WS_X11
#include <X11/Xlib.h> // NOLINT - this needs to be done AFTER Qt has set some defines in their headers and after several other
// headers which are included indirectly, although it is a system header.
#endif
WMainWindow* WQt4Gui::m_mainWindow = NULL;
QSettings* WQt4Gui::m_settings = NULL;
......@@ -129,6 +134,10 @@ void WQt4Gui::deferredLoad()
int WQt4Gui::run()
{
#ifdef Q_WS_X11
XInitThreads();
#endif
// init logger
m_loggerConnection = WLogger::getLogger()->subscribeSignal( WLogger::AddLog, boost::bind( &WQt4Gui::slotAddLog, this, _1 ) );
......
......@@ -158,14 +158,14 @@ public:
boost::shared_ptr< WCondition > shutdownCondition );
/**
* Instruct the WMainWindow to close a custom widget.
* Instruct the WMainWindow to close a custom widget. NEVER call this in the GUI thread. It will block the GUI.
*
* \param title The title of the widget
*/
virtual void closeCustomWidget( std::string title );
/**
* Instruct the WMainWindow to close a custom widget.
* Instruct the WMainWindow to close a custom widget. NEVER call this in the GUI thread. It will block the GUI.
*
* \param widget the widget to close
*/
......
//---------------------------------------------------------------------------
//
// 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 <string>
#include "core/gui/WCustomWidget.h"
#include "WCloseCustomDockWidgetEvent.h"
WCloseCustomDockWidgetEvent::WCloseCustomDockWidgetEvent( std::string title ):
QEvent( CUSTOM_TYPE ),
m_title( title )
{
}
std::string WCloseCustomDockWidgetEvent::getTitle() const
{
return m_title;
}
//---------------------------------------------------------------------------
//
// 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 WCLOSECUSTOMDOCKWIDGETEVENT_H
#define WCLOSECUSTOMDOCKWIDGETEVENT_H
#include <string>
#include <QtCore/QEvent>
#include "core/common/WCondition.h"
#include "WEventTypes.h"
/**
* A Qt event to close an existing custom dock widget if posted to the WMainWindow.
*/
class WCloseCustomDockWidgetEvent : public QEvent
{
public:
/**
* Constructor. Use the doneCondition to wait for the event to be processed.
*
* \param title the title of the widget to open
* \param doneCondition This condition is fired whenever the widget is really closed.
*/
explicit WCloseCustomDockWidgetEvent( std::string title );
/**
* Get the title of the widget to open.
*
* \return title of the widget to open
*/
std::string getTitle() const;
/**
* Constant which saves the number used to distinguish this event from other
* custom events.
*/
static const QEvent::Type CUSTOM_TYPE = static_cast< QEvent::Type >( WQT_CLOSECUSTOMDOCKWIDGET );
protected:
private:
/**
* the title of the widget to create
*/
std::string m_title;
};
#endif // WCLOSECUSTOMDOCKWIDGETEVENT_H
......@@ -75,4 +75,10 @@
// when the screencapture update.
#define WQT_SCREENCAPTURE_EVENT QEvent::User + 14
// open a new custom dock widget
#define WQT_OPENCUSTOMDOCKWIDGET QEvent::User + 15
// close an existing custom dock widget
#define WQT_CLOSECUSTOMDOCKWIDGET QEvent::User + 16
#endif // WEVENTTYPES_H
......@@ -33,6 +33,8 @@
#include "core/common/WFlag.h"
#include "core/gui/WCustomWidget.h"
#include "WEventTypes.h"
/**
* A Qt event to open a new custom dock widget if posted to the WMainWindow.
*/
......@@ -74,7 +76,7 @@ public:
* Constant which saves the number used to distinguish this event from other
* custom events.
*/
static const QEvent::Type CUSTOM_TYPE = static_cast< QEvent::Type >( 51051 );
static const QEvent::Type CUSTOM_TYPE = static_cast< QEvent::Type >( WQT_OPENCUSTOMDOCKWIDGET );
protected:
private:
......
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