Commit 93bdb8cd authored by Clinton Stimpson's avatar Clinton Stimpson
Browse files

ENH: Add support for recording/playback of advanced interaction with

      QAbstractItemViews (QTreeView, QListView, QTableView, etc..).
parent 18d6bb91
......@@ -35,11 +35,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QAbstractItemView>
#include <QApplication>
#include <QMouseEvent>
#include <QTime>
#include <QKeyEvent>
#include <QtDebug>
#include "pqEventDispatcher.h"
/// Converts a string representation of a model index into the real thing
static QModelIndex GetIndex(QAbstractItemView& View, const QString& Name)
static QModelIndex OldGetIndex(QAbstractItemView& View, const QString& Name)
{
QStringList rows = Name.split('/', QString::SkipEmptyParts);
QString column;
......@@ -59,6 +61,20 @@ static QModelIndex GetIndex(QAbstractItemView& View, const QString& Name)
return index;
}
static QModelIndex GetIndex(QAbstractItemView* View, const QString& Name)
{
QStringList idxs = Name.split('/', QString::SkipEmptyParts);
QModelIndex index;
for(int i = 0; i != idxs.size(); ++i)
{
QStringList rowCol = idxs[i].split(':');
index = View->model()->index(rowCol[0].toInt(), rowCol[1].toInt(), index);
}
return index;
}
///////////////////////////////////////////////////////////////////////////////
// pqAbstractItemViewEventPlayer
......@@ -75,15 +91,50 @@ bool pqAbstractItemViewEventPlayer::playEvent(QObject* Object, const QString& Co
return false;
}
if(Command == "currentChanged")
if(Command == "currentChanged") // left to support old recordings
{
const QModelIndex index = GetIndex(*object, Arguments);
const QModelIndex index = OldGetIndex(*object, Arguments);
if(!index.isValid())
return false;
object->setCurrentIndex(index);
return true;
}
else if(Command == "keyEvent")
{
QStringList data = Arguments.split(',');
if(data.size() == 6)
{
QKeyEvent ke(static_cast<QEvent::Type>(data[0].toInt()),
data[1].toInt(),
static_cast<Qt::KeyboardModifiers>(data[2].toInt()),
data[3],
!!data[4].toInt(),
data[5].toInt());
QCoreApplication::sendEvent(object, &ke);
return true;
}
}
else if(Command.startsWith("mouse"))
{
QStringList args = Arguments.split(',');
if(args.size() == 4)
{
Qt::MouseButton button = static_cast<Qt::MouseButton>(args[0].toInt());
Qt::MouseButtons buttons = static_cast<Qt::MouseButton>(args[1].toInt());
Qt::KeyboardModifiers keym = static_cast<Qt::KeyboardModifier>(args[2].toInt());
QModelIndex idx = GetIndex(object, args[3]);
QRect r = object->visualRect(idx);
QEvent::Type type = QEvent::MouseButtonPress;
type = Command == "mouseMove" ? QEvent::MouseMove : type;
type = Command == "mouseRelease" ? QEvent::MouseButtonRelease : type;
type = Command == "mouseDblClick" ? QEvent::MouseButtonDblClick : type;
QMouseEvent e(type, r.center(), button, buttons, keym);
QCoreApplication::sendEvent(object->viewport(), &e);
pqEventDispatcher::processEventsAndWait(1);
return true;
}
}
qCritical() << "Unknown abstract item command: " << Command << "\n";
Error = true;
......
......@@ -34,52 +34,111 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QAbstractItemView>
#include <QEvent>
#include <QKeyEvent>
static const QString str(const QModelIndex& index)
static QString toIndexStr(QModelIndex index)
{
QString result;
for(QModelIndex i = index; i.isValid(); i = i.parent())
{
result = "/" + QString().setNum(i.row()) + result;
result = "/" + QString("%1:%2").arg(i.row()).arg(i.column()) + result;
}
if(index.isValid())
{
result = result + "|" + QString().setNum(index.column());
}
return result;
}
pqAbstractItemViewEventTranslator::pqAbstractItemViewEventTranslator(QObject* p)
: pqWidgetEventTranslator(p),
CurrentObject(0)
: pqWidgetEventTranslator(p)
{
}
bool pqAbstractItemViewEventTranslator::translateEvent(QObject* Object, QEvent* Event, bool& /*Error*/)
{
QAbstractItemView* const object = qobject_cast<QAbstractItemView*>(Object);
QAbstractItemView* object = qobject_cast<QAbstractItemView*>(Object);
if(!object)
{
// mouse events go to the viewport widget
object = qobject_cast<QAbstractItemView*>(Object->parent());
}
if(!object)
return false;
// Don't try to record events for QComboBox implementation details
if(QString(Object->metaObject()->className()) == "QComboBoxListView")
if(QString(object->metaObject()->className()) == "QComboBoxListView")
return false;
switch(Event->type())
{
case QEvent::Enter:
this->CurrentObject = object;
connect(object->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(onCurrentChanged(const QModelIndex&, const QModelIndex&)));
case QEvent::KeyPress:
case QEvent::KeyRelease:
{
QKeyEvent* ke = static_cast<QKeyEvent*>(Event);
QString data =QString("%1,%2,%3,%4,%5,%6")
.arg(ke->type())
.arg(ke->key())
.arg(static_cast<int>(ke->modifiers()))
.arg(ke->text())
.arg(ke->isAutoRepeat())
.arg(ke->count());
emit recordEvent(object, "keyEvent", data);
return true;
break;
case QEvent::Leave:
disconnect(Object, 0, this, 0);
disconnect(object->selectionModel(), 0, this, 0);
this->CurrentObject = 0;
}
case QEvent::MouseButtonPress:
{
if(Object == object)
{
return false;
}
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(Event);
this->LastPos = mouseEvent->pos();
QModelIndex idx = object->indexAt(mouseEvent->pos());
QString idxStr = toIndexStr(idx);
QString info = QString("%1,%2,%3,%4")
.arg(mouseEvent->button())
.arg(mouseEvent->buttons())
.arg(mouseEvent->modifiers())
.arg(idxStr);
emit recordEvent(object, "mousePress", info);
return true;
break;
}
case QEvent::MouseButtonDblClick:
{
if(Object == object)
{
return false;
}
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(Event);
this->LastPos = mouseEvent->pos();
QModelIndex idx = object->indexAt(mouseEvent->pos());
QString idxStr = toIndexStr(idx);
QString info = QString("%1,%2,%3,%4")
.arg(mouseEvent->button())
.arg(mouseEvent->buttons())
.arg(mouseEvent->modifiers())
.arg(idxStr);
emit recordEvent(object, "mouseDblClick", info);
return true;
}
case QEvent::MouseButtonRelease:
{
if(Object == object)
{
return false;
}
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(Event);
QModelIndex idx = object->indexAt(mouseEvent->pos());
QString idxStr = toIndexStr(idx);
QString info = QString("%1,%2,%3,%4")
.arg(mouseEvent->button())
.arg(mouseEvent->buttons())
.arg(mouseEvent->modifiers())
.arg(idxStr);
if(this->LastPos != mouseEvent->pos())
{
emit recordEvent(object, "mouseMove", info);
}
emit recordEvent(object, "mouseRelease", info);
return true;
}
default:
break;
}
......@@ -87,8 +146,4 @@ bool pqAbstractItemViewEventTranslator::translateEvent(QObject* Object, QEvent*
return false;
}
void pqAbstractItemViewEventTranslator::onCurrentChanged(const QModelIndex& current, const QModelIndex& /*previous*/)
{
emit recordEvent(this->CurrentObject, "currentChanged", str(current));
}
......@@ -34,10 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _pqAbstractItemViewEventTranslator_h
#include "pqWidgetEventTranslator.h"
class QAbstractItemView;
class QModelIndex;
class QPoint;
#include <QPoint>
/**
Translates low-level Qt events into high-level ParaView events that can be recorded as test cases.
......@@ -54,15 +51,14 @@ public:
pqAbstractItemViewEventTranslator(QObject* p=0);
virtual bool translateEvent(QObject* Object, QEvent* Event, bool& Error);
protected:
QPoint LastPos;
private:
pqAbstractItemViewEventTranslator(const pqAbstractItemViewEventTranslator&);
pqAbstractItemViewEventTranslator& operator=(const pqAbstractItemViewEventTranslator&);
QAbstractItemView* CurrentObject;
private slots:
void onCurrentChanged(const QModelIndex&, const QModelIndex&);
};
#endif // !_pqAbstractItemViewEventTranslator_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