Commit 932d9c5a authored by Clinton Stimpson's avatar Clinton Stimpson

ENH: Upgrade to Qt 4.2 allows glib to be used on X11, which causes problems.

      Refactored pqEventDispatcher to handle event dispatching in a more
      controlled way and be more immune to the implementation of Qt's event
      handling.
      ifdef Q_OS_MAC's also removed.

BUG:  This fixes sporadic hangs on some dashboards with python tests.
parent c9501866
......@@ -40,6 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QPushButton>
#include <QtDebug>
#include "pqEventDispatcher.h"
pqAbstractActivateEventPlayer::pqAbstractActivateEventPlayer(QObject * p)
: pqWidgetEventPlayer(p)
{
......@@ -107,7 +109,7 @@ bool pqAbstractActivateEventPlayer::playEvent(QObject* Object,
menu_bar->setActiveAction(next->menuAction());
while(!next->isVisible())
{
this->wait(100);
pqEventDispatcher::processEventsAndWait(100);
}
}
else if(QMenu* menu = qobject_cast<QMenu*>(p))
......@@ -119,7 +121,7 @@ bool pqAbstractActivateEventPlayer::playEvent(QObject* Object,
Qt::LeftButton, Qt::LeftButton, 0);
QApplication::sendEvent(menu, &button_press);
// process events before mouse up to help our sub menu show up
QCoreApplication::processEvents();
pqEventDispatcher::processEventsAndWait(0);
QMouseEvent button_release(QEvent::MouseButtonRelease,
geom.center(),
......@@ -131,7 +133,7 @@ bool pqAbstractActivateEventPlayer::playEvent(QObject* Object,
while(!next->isVisible())
{
this->wait(100);
pqEventDispatcher::processEventsAndWait(100);
}
}
}
......
......@@ -30,12 +30,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=========================================================================*/
#include "pqEventDispatcher.h"
#ifdef Q_OS_WIN
#include <windows.h> // for Sleep
#endif
#ifdef Q_OS_UNIX
#include <time.h>
#endif
#include "pqEventPlayer.h"
#include "pqEventSource.h"
#include "pqEventDispatcher.h"
#include <QAbstractEventDispatcher>
#include <QtDebug>
#include <QTime>
#include <QTimer>
#include <QApplication>
......@@ -47,23 +56,28 @@ class pqEventDispatcher::pqImplementation
public:
pqImplementation() :
Source(0),
Player(0)
Player(0),
EventState(FlushEvents)
{
#if defined(Q_WS_MAC)
// for the Mac, work around a Qt bug by using a timer
// (should be fixed in Qt 4.3.0)
this->Timer.setInterval(1);
this->Timer.setSingleShot(true);
#endif
}
pqEventSource* Source;
pqEventPlayer* Player;
#if defined(Q_WS_MAC)
QTimer Timer;
#endif
enum EventStates
{
FlushEvents,
DoEvent,
Done
};
int EventState;
static int WaitTime;
};
int pqEventDispatcher::pqImplementation::WaitTime = 0;
////////////////////////////////////////////////////////////////////////////
// pqEventDispatcher
......@@ -72,6 +86,9 @@ pqEventDispatcher::pqEventDispatcher() :
{
QObject::connect(this, SIGNAL(readyPlayNextEvent()),
this, SLOT(playNextEvent()));
QObject::connect(&this->Implementation->Timer, SIGNAL(timeout()),
this, SLOT(checkPlayNextEvent()));
}
pqEventDispatcher::~pqEventDispatcher()
......@@ -92,27 +109,42 @@ void pqEventDispatcher::playEvents(pqEventSource& source, pqEventPlayer& player)
QApplication::setEffectEnabled(Qt::UI_General, false);
#if defined(Q_WS_MAC)
QObject::connect(
QAbstractEventDispatcher::instance(),
SIGNAL(aboutToBlock()),
&this->Implementation->Timer,
SLOT(start()));
QObject::connect(
&this->Implementation->Timer,
SIGNAL(timeout()),
this,
SIGNAL(readyPlayNextEvent()));
#else
QObject::connect(
QAbstractEventDispatcher::instance(),
SIGNAL(aboutToBlock()),
this,
SIGNAL(readyPlayNextEvent()),
Qt::QueuedConnection);
#endif
this->Implementation->Timer.setInterval(1);
this->Implementation->Timer.start();
this->Implementation->EventState = pqImplementation::FlushEvents;
this->Implementation->WaitTime = 0;
}
void pqEventDispatcher::checkPlayNextEvent()
{
if(this->Implementation->EventState == pqImplementation::Done)
{
return;
}
this->Implementation->Timer.setInterval(1);
// do an event every other time through here to be sure events are processed
if(this->Implementation->EventState == pqImplementation::DoEvent)
{
pqEventDispatcher::processEventsAndWait(1);
this->Implementation->EventState = pqImplementation::FlushEvents;
this->Implementation->Timer.start();
emit this->readyPlayNextEvent();
}
else if(!this->Implementation->WaitTime)
{
pqEventDispatcher::processEventsAndWait(1);
this->Implementation->EventState = pqImplementation::DoEvent;
this->Implementation->Timer.start();
}
else
{
this->Implementation->Timer.setInterval(this->Implementation->WaitTime);
this->Implementation->Timer.start();
}
}
void pqEventDispatcher::playNextEvent()
{
......@@ -158,25 +190,8 @@ void pqEventDispatcher::playNextEvent()
void pqEventDispatcher::stopPlayback()
{
#if defined(Q_WS_MAC)
QObject::disconnect(
QAbstractEventDispatcher::instance(),
SIGNAL(aboutToBlock()),
&this->Implementation->Timer,
SLOT(start()));
QObject::disconnect(
&this->Implementation->Timer,
SIGNAL(timeout()),
this,
SIGNAL(readyPlayNextEvent()));
#else
QObject::disconnect(
QAbstractEventDispatcher::instance(),
SIGNAL(aboutToBlock()),
this,
SIGNAL(readyPlayNextEvent()));
#endif
this->Implementation->Timer.stop();
this->Implementation->EventState = pqImplementation::Done;
this->Implementation->Source->stop();
......@@ -187,3 +202,23 @@ void pqEventDispatcher::stopPlayback()
QCoreApplication::processEvents();
}
void pqEventDispatcher::processEventsAndWait(int ms)
{
pqEventDispatcher::pqImplementation::WaitTime = ms <= 0 ? 1 : ms;
QTime timer;
timer.start();
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
#ifdef Q_OS_WIN
Sleep(uint(10));
#else
struct timespec ts = { 10 / 1000, (10 % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
} while (timer.elapsed() < ms);
pqEventDispatcher::pqImplementation::WaitTime = 0;
}
......@@ -57,6 +57,10 @@ public:
to indicate that playback has finished. */
void playEvents(pqEventSource& source, pqEventPlayer& player);
/** Wait function provided for players that need to wait for the GUI
to perform a certain action */
static void processEventsAndWait(int ms);
signals:
void succeeded();
void failed();
......@@ -64,6 +68,7 @@ signals:
private slots:
void playNextEvent();
void checkPlayNextEvent();
private:
void stopPlayback();
......
......@@ -117,7 +117,6 @@ void pqEventPlayer::playEvent(
return;
}
QApplication::processEvents();
// The event was handled successfully ...
Error = false;
}
......
......@@ -54,6 +54,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Qt testing includes
#include "pqObjectNaming.h"
#include "pqWidgetEventPlayer.h"
#include "pqEventDispatcher.h"
// TODO not have a global instance pointer?
......@@ -216,7 +217,7 @@ QtTesting_wait(PyObject* /*self*/, PyObject* args)
return NULL;
}
pqWidgetEventPlayer::wait(ms);
pqEventDispatcher::processEventsAndWait(ms);
return Py_BuildValue(const_cast<char*>(""));
}
......
......@@ -32,15 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "pqWidgetEventPlayer.h"
#ifdef Q_OS_WIN
#include <windows.h> // for Sleep
#endif
#ifdef Q_OS_UNIX
#include <time.h>
#endif
#include <QCoreApplication>
#include <QTime>
pqWidgetEventPlayer::pqWidgetEventPlayer(QObject* p)
: QObject(p)
......@@ -51,19 +43,4 @@ pqWidgetEventPlayer::~pqWidgetEventPlayer()
{
}
void pqWidgetEventPlayer::wait(int ms)
{
QTime timer;
timer.start();
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
#ifdef Q_OS_WIN
Sleep(uint(10));
#else
struct timespec ts = { 10 / 1000, (10 % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
} while (timer.elapsed() < ms);
}
......@@ -61,10 +61,6 @@ public:
const QString& Arguments,
bool& Error) = 0;
/** Wait function provided for players that need to wait for the GUI
to perform a certain action */
static void wait(int ms);
};
#endif // !_pqWidgetEventPlayer_h
......
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