Home · All Classes · Main Classes · Grouped Classes · Modules · Functions

qcontext2dcanvas.cpp Example File
script/context2d/qcontext2dcanvas.cpp

 /****************************************************************************
 **
 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
 **
 ** This file is part of the example classes of the Qt Toolkit.
 **
 ** Licensees holding a valid Qt License Agreement may use this file in
 ** accordance with the rights, responsibilities and obligations
 ** contained therein.  Please consult your licensing agreement or
 ** contact sales@trolltech.com if any conditions of this licensing
 ** agreement are not clear to you.
 **
 ** Further information about Qt licensing is available at:
 ** http://www.trolltech.com/products/qt/licensing.html or by
 ** contacting info@trolltech.com.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/

 #include "qcontext2dcanvas.h"

 #include "context2d.h"
 #include "domimage.h"

 #include <QApplication>
 #include <QPainter>
 #include <QPaintEvent>
 #include <QMouseEvent>
 #include <QDateTime>

 struct FakeDomEvent
 {
     enum KeyCodes  {
         DOM_VK_UNDEFINED            = 0x0,
         DOM_VK_RIGHT_ALT            = 0x12,
         DOM_VK_LEFT_ALT             = 0x12,
         DOM_VK_LEFT_CONTROL         = 0x11,
         DOM_VK_RIGHT_CONTROL        = 0x11,
         DOM_VK_LEFT_SHIFT           = 0x10,
         DOM_VK_RIGHT_SHIFT          = 0x10,
         DOM_VK_META                 = 0x9D,
         DOM_VK_BACK_SPACE           = 0x08,
         DOM_VK_CAPS_LOCK            = 0x14,
         DOM_VK_DELETE               = 0x7F,
         DOM_VK_END                  = 0x23,
         DOM_VK_ENTER                = 0x0D,
         DOM_VK_ESCAPE               = 0x1B,
         DOM_VK_HOME                 = 0x24,
         DOM_VK_NUM_LOCK             = 0x90,
         DOM_VK_PAUSE                = 0x13,
         DOM_VK_PRINTSCREEN          = 0x9A,
         DOM_VK_SCROLL_LOCK          = 0x91,
         DOM_VK_SPACE                = 0x20,
         DOM_VK_TAB                  = 0x09,
         DOM_VK_LEFT                 = 0x25,
         DOM_VK_RIGHT                = 0x27,
         DOM_VK_UP                   = 0x26,
         DOM_VK_DOWN                 = 0x28,
         DOM_VK_PAGE_DOWN            = 0x22,
         DOM_VK_PAGE_UP              = 0x21,
         DOM_VK_F1                   = 0x70,
         DOM_VK_F2                   = 0x71,
         DOM_VK_F3                   = 0x72,
         DOM_VK_F4                   = 0x73,
         DOM_VK_F5                   = 0x74,
         DOM_VK_F6                   = 0x75,
         DOM_VK_F7                   = 0x76,
         DOM_VK_F8                   = 0x77,
         DOM_VK_F9                   = 0x78,
         DOM_VK_F10                  = 0x79,
         DOM_VK_F11                  = 0x7A,
         DOM_VK_F12                  = 0x7B,
         DOM_VK_F13                  = 0xF000,
         DOM_VK_F14                  = 0xF001,
         DOM_VK_F15                  = 0xF002,
         DOM_VK_F16                  = 0xF003,
         DOM_VK_F17                  = 0xF004,
         DOM_VK_F18                  = 0xF005,
         DOM_VK_F19                  = 0xF006,
         DOM_VK_F20                  = 0xF007,
         DOM_VK_F21                  = 0xF008,
         DOM_VK_F22                  = 0xF009,
         DOM_VK_F23                  = 0xF00A,
         DOM_VK_F24                  = 0xF00B
     };

     FakeDomEvent();
     FakeDomEvent(QMouseEvent *e, QScriptEngine *eng);
     FakeDomEvent(QKeyEvent *e, QScriptEngine *eng);

     void setupModifiers(QInputEvent *e, QScriptEngine *eng);

     static int qtToDomKey(int keyCode);
     static void setupDefaults(QScriptEngine *e);
     static void setup(QScriptEngine *e);

     static QScriptValue m_proto;
 };

 Q_DECLARE_METATYPE(FakeDomEvent)

 FakeDomEvent::FakeDomEvent()
 {
 }

 FakeDomEvent::FakeDomEvent(QMouseEvent *e, QScriptEngine *eng)
 {
     setupDefaults(eng);
     setupModifiers(e, eng);
     m_proto.setProperty("type",
                         QScriptValue(eng, QLatin1String("mouseevent")));
     int button = 0;
     if (e->button() == Qt::RightButton)
         button = 2;
     else if (e->button() == Qt::MidButton)
         button = 1;
     m_proto.setProperty("button", QScriptValue(eng, button));

     m_proto.setProperty("clientX", QScriptValue(eng, e->x()));
     m_proto.setProperty("clientY", QScriptValue(eng, e->y()));
     m_proto.setProperty("layerX", QScriptValue(eng, e->x()));
     m_proto.setProperty("layerY", QScriptValue(eng, e->y()));
     m_proto.setProperty("pageX", QScriptValue(eng, e->x()));
     m_proto.setProperty("pageY", QScriptValue(eng, e->y()));
     m_proto.setProperty("screenX", QScriptValue(eng, e->globalX()));
     m_proto.setProperty("screenY", QScriptValue(eng, e->globalY()));

     eng->setDefaultPrototype(qMetaTypeId<FakeDomEvent>(), m_proto);
 }

 FakeDomEvent::FakeDomEvent(QKeyEvent *e, QScriptEngine *eng)
 {
     setupDefaults(eng);
     setupModifiers(e, eng);
     m_proto.setProperty("type", QScriptValue(eng, QLatin1String("keyevent")));

     m_proto.setProperty("isChar", QScriptValue(eng, !e->text().isEmpty()));
     m_proto.setProperty("charCode", QScriptValue(eng, e->text()));
     m_proto.setProperty("keyCode", QScriptValue(eng, qtToDomKey(e->key())));
     m_proto.setProperty("which", QScriptValue(eng, e->key()));

     eng->setDefaultPrototype(qMetaTypeId<FakeDomEvent>(), m_proto);
 }

 void FakeDomEvent::setupModifiers(QInputEvent *e, QScriptEngine *eng)
 {
     if (e->modifiers() & Qt::AltModifier)
         m_proto.setProperty("altKey", QScriptValue(eng, true));
     else
         m_proto.setProperty("altKey", QScriptValue(eng, false));

     if (e->modifiers() & Qt::ControlModifier)
         m_proto.setProperty("ctrlKey", QScriptValue(eng, true));
     else
         m_proto.setProperty("ctrlKey", QScriptValue(eng, false));

     if (e->modifiers() & Qt::MetaModifier)
         m_proto.setProperty("metaKey", QScriptValue(eng, true));
     else
         m_proto.setProperty("metaKey", QScriptValue(eng, false));

     if (e->modifiers() & Qt::ShiftModifier)
         m_proto.setProperty("shiftKey", QScriptValue(eng, true));
     else
         m_proto.setProperty("shiftKey", QScriptValue(eng, true));
 }

 int FakeDomEvent::qtToDomKey(int keyCode)
 {
     switch (keyCode) {
     case Qt::Key_Backspace:
         return  DOM_VK_BACK_SPACE;
     case Qt::Key_Enter:
         return  DOM_VK_ENTER;
     case Qt::Key_Return:
         return  DOM_VK_ENTER;
     case Qt::Key_NumLock:
         return  DOM_VK_NUM_LOCK;
     case Qt::Key_Alt:
         return  DOM_VK_RIGHT_ALT;
     case Qt::Key_Control:
         return  DOM_VK_LEFT_CONTROL;
     case Qt::Key_Shift:
         return  DOM_VK_LEFT_SHIFT;
     case Qt::Key_Meta:
         return  DOM_VK_META;
     case Qt::Key_CapsLock:
         return  DOM_VK_CAPS_LOCK;
     case Qt::Key_Delete:
         return  DOM_VK_DELETE;
     case Qt::Key_End:
         return  DOM_VK_END;
     case Qt::Key_Escape:
         return  DOM_VK_ESCAPE;
     case Qt::Key_Home:
         return  DOM_VK_HOME;
     case Qt::Key_Pause:
         return  DOM_VK_PAUSE;
     case Qt::Key_Print:
         return  DOM_VK_PRINTSCREEN;
     case Qt::Key_ScrollLock:
         return  DOM_VK_SCROLL_LOCK;
     case Qt::Key_Left:
         return  DOM_VK_LEFT;
     case Qt::Key_Right:
         return  DOM_VK_RIGHT;
     case Qt::Key_Up:
         return  DOM_VK_UP;
     case Qt::Key_Down:
         return  DOM_VK_DOWN;
     case Qt::Key_PageDown:
         return  DOM_VK_PAGE_DOWN;
     case Qt::Key_PageUp:
         return  DOM_VK_PAGE_UP;
     case Qt::Key_F1:
         return  DOM_VK_F1;
     case Qt::Key_F2:
         return  DOM_VK_F2;
     case Qt::Key_F3:
         return  DOM_VK_F3;
     case Qt::Key_F4:
         return  DOM_VK_F4;
     case Qt::Key_F5:
         return  DOM_VK_F5;
     case Qt::Key_F6:
         return  DOM_VK_F6;
     case Qt::Key_F7:
         return  DOM_VK_F7;
     case Qt::Key_F8:
         return  DOM_VK_F8;
     case Qt::Key_F9:
         return  DOM_VK_F9;
     case Qt::Key_F10:
         return  DOM_VK_F10;
     case Qt::Key_F11:
         return  DOM_VK_F11;
     case Qt::Key_F12:
         return  DOM_VK_F12;
     case Qt::Key_F13:
         return  DOM_VK_F13;
     case Qt::Key_F14:
         return  DOM_VK_F14;
     case Qt::Key_F15:
         return  DOM_VK_F15;
     case Qt::Key_F16:
         return  DOM_VK_F16;
     case Qt::Key_F17:
         return  DOM_VK_F17;
     case Qt::Key_F18:
         return  DOM_VK_F18;
     case Qt::Key_F19:
         return  DOM_VK_F19;
     case Qt::Key_F20:
         return  DOM_VK_F20;
     case Qt::Key_F21:
         return  DOM_VK_F21;
     case Qt::Key_F22:
         return  DOM_VK_F22;
     case Qt::Key_F23:
         return  DOM_VK_F23;
     case Qt::Key_F24:
         return  DOM_VK_F24;
     }
     return keyCode;
 }

 void FakeDomEvent::setupDefaults(QScriptEngine *e)
 {
     m_proto.setProperty("timeStamp", QScriptValue(e, QDateTime::currentDateTime().toTime_t()));
     m_proto.setProperty("button", QScriptValue(e, 0));
     m_proto.setProperty("charCode", QScriptValue(e, 0));
     m_proto.setProperty("clientX", QScriptValue(e, 0));
     m_proto.setProperty("clientY", QScriptValue(e, 0));
     m_proto.setProperty("isChar", QScriptValue(e, 0));
     m_proto.setProperty("keyCode", QScriptValue(e, 0));
     m_proto.setProperty("layerX", QScriptValue(e, 0));
     m_proto.setProperty("layerY", QScriptValue(e, 0));
     m_proto.setProperty("pageX", QScriptValue(e, 0));
     m_proto.setProperty("pageY", QScriptValue(e, 0));
     m_proto.setProperty("screenX", QScriptValue(e, 0));
     m_proto.setProperty("screenY", QScriptValue(e, 0));
     m_proto.setProperty("which ", QScriptValue(e, 0));
 }

 void FakeDomEvent::setup(QScriptEngine *e)
 {
     qRegisterMetaType<FakeDomEvent>();

     m_proto = e->newObject();

     setupDefaults(e);

     m_proto.setProperty("bubbles", QScriptValue(e, 0));
     m_proto.setProperty("cancelBubble", QScriptValue(e, 0));
     m_proto.setProperty("cancelable", QScriptValue(e, 0));
     m_proto.setProperty("currentTarget", QScriptValue(e, 0));
     m_proto.setProperty("detail", QScriptValue(e, 0));
     m_proto.setProperty("eventPhase", QScriptValue(e, 0));
     m_proto.setProperty("explicitOriginalTarget", QScriptValue(e, 0));
     m_proto.setProperty("originalTarget", QScriptValue(e, 0));
     m_proto.setProperty("relatedTarget", QScriptValue(e, 0));
     m_proto.setProperty("target", QScriptValue(e, 0));
     m_proto.setProperty("view", QScriptValue(e, 0));
 }

 QScriptValue FakeDomEvent::m_proto;

 static QScriptValue getElementById(QScriptContext *context, QScriptEngine *env)
 {
     QString el  = context->argument(0).toString();
     QList<QObject*> lst = qFindChildren<QObject*>(QCoreApplication::instance(), el);
     if (lst.isEmpty()) {
         foreach (QWidget *widget, QApplication::topLevelWidgets()) {
             if (el == widget->objectName() ) {
                 lst << widget;
                 break;
             } else {
                 lst = qFindChildren<QObject*>(widget, el);
             }

             if (lst.count())
                 break;
         }
     }

     return env->newQObject(lst[0]);
 }

 static QScriptValue setInterval(QScriptContext *context, QScriptEngine *env)
 {
     QScriptValue func = context->argument(0);
     qsreal interval  = context->argument(1).toNumber();
     QScriptValue val = env->globalObject().property("_qcontext");
     QContext2DCanvas *canvas =
         qobject_cast<QContext2DCanvas*>(val.toQObject());
     if (!canvas) {
         qWarning("Couldn't find a QContext2DCanvas!");
         return env->undefinedValue();
     }
     if (!func.isFunction()) {
         QString funcStr = func.toString();
         if (funcStr.endsWith("()")) {
             funcStr.chop(2);
         }
         func = env->globalObject().property(funcStr);
     }
     if (!func.isFunction()) {
         qWarning("Couldn't find function %s",
                  qPrintable(context->argument(0).toString()));
         return env->undefinedValue();
     }

     canvas->setInterval(func, interval);

     return env->undefinedValue();
 }

 static QScriptValue setTimeout(QScriptContext *ctx, QScriptEngine *env)
 {
     return setInterval(ctx, env);
 }

 QContext2DCanvas::QContext2DCanvas(QWidget *parent)
     : QWidget(parent),
       m_firstRun(true)
 {
     setObjectName("tutorial");
     m_context = new Context2D(this);

     m_self = m_engine.newQObject(this);

     FakeDomEvent::setup(&m_engine);
     DomImage::setup(&m_engine);

     m_doc = m_engine.newObject();
     m_doc.setProperty("getElementById",
                     m_engine.newFunction(::getElementById,
                                             /*argc = */ 1));

     m_engine.globalObject().setProperty("document", m_doc);

     m_engine.globalObject().setProperty(
         "setInterval",
         m_engine.newFunction(::setInterval, 2));
     m_engine.globalObject().setProperty(
         "setTimeout",
         m_engine.newFunction(::setTimeout, 2));
     m_engine.globalObject().setProperty("_qcontext", m_self);

     connect(&m_timer, SIGNAL(timeout()),
             SLOT(update()));
 }

 QScriptEngine *QContext2DCanvas::engine()
 {
     return &m_engine;
 }

 void QContext2DCanvas::setScriptContents(const QString &txt)
 {
     m_timer.stop();
     m_intervalFunc     = QScriptValue();
     m_keyDownHandler   = QScriptValue();
     m_keyUpHandler     = QScriptValue();
     m_mouseDownHandler = QScriptValue();
     m_mouseUpHandler   = QScriptValue();
     m_mouseMoveHandler = QScriptValue();
     m_firstRun = true;
     m_script = txt;
     m_context->clear();
     update();
 }

 void QContext2DCanvas::paintEvent(QPaintEvent *e)
 {
     QPainter p(this);
     p.setClipRect(e->rect());

     QScriptValue ret;
     if (m_intervalFunc.isValid()) {
         m_context->begin();
         ret = m_intervalFunc.call(m_engine.globalObject());
     } else {
         ret = m_engine.evaluate(m_script);
     }
     if (!m_script.isEmpty() && m_engine.hasUncaughtException()) {
         int lineno = m_engine.uncaughtExceptionLineNumber();
         QString msg = ret.toString();
         qWarning("%s, at %d", qPrintable(msg), lineno);
         emit error(msg, lineno);
         m_timer.stop();
         return;
     }
     p.drawImage(0, 0, m_context->end());

     if (m_firstRun) {
         m_keyDownHandler = m_doc.property("onkeydown");
         m_keyUpHandler = m_doc.property("onkeyup");
         m_mouseDownHandler = m_doc.property("onmousedown");
         m_mouseUpHandler = m_doc.property("onmouseup");
         m_mouseMoveHandler = m_doc.property("onmousemove");
         setMouseTracking(m_mouseMoveHandler.isValid());
     }

     m_firstRun = false;
 }

 void QContext2DCanvas::mouseMoveEvent(QMouseEvent *e)
 {
     Q_UNUSED(e);
     if (m_mouseMoveHandler.isValid()) {
         FakeDomEvent event(e, &m_engine);
         QScriptValueList args;
         args << event.m_proto;
         m_mouseMoveHandler.call(m_engine.globalObject(), args);
     }
 }

 void QContext2DCanvas::mousePressEvent(QMouseEvent *e)
 {
     if (m_mouseDownHandler.isValid()) {
         FakeDomEvent event(e, &m_engine);
         QScriptValueList args;
         args << event.m_proto;
         m_mouseDownHandler.call(m_engine.globalObject(), args);
     }
 }

 void QContext2DCanvas::mouseReleaseEvent(QMouseEvent *e)
 {
     if (m_mouseUpHandler.isValid()) {
         FakeDomEvent event(e, &m_engine);
         QScriptValueList args;
         args << event.m_proto;
         m_mouseUpHandler.call(m_engine.globalObject(), args);
     }
 }

 void QContext2DCanvas::keyPressEvent(QKeyEvent *e)
 {
     if (m_keyDownHandler.isValid()) {
         FakeDomEvent event(e, &m_engine);
         QScriptValueList args;
         args << event.m_proto;
         m_keyDownHandler.call(m_engine.globalObject(), args);
     }
 }

 void QContext2DCanvas::keyReleaseEvent(QKeyEvent *e)
 {
     if (m_keyUpHandler.isValid()) {
         FakeDomEvent event(e, &m_engine);
         QScriptValueList args;
         args << event.m_proto;
         m_keyUpHandler.call(m_engine.globalObject(), args);
     }
 }

 void QContext2DCanvas::resizeEvent(QResizeEvent *e)
 {
     Q_UNUSED(e);
     m_context->setSize(e->size().width(), e->size().height());
 }

 QObject * QContext2DCanvas::getContext(const QString &str) const
 {
     if (str != QLatin1String("2d")) {
         qWarning("Passing invalid context %s", qPrintable(str));
     }

     m_context->begin();
     return m_context;
 }

 QContext2DCanvas::~QContext2DCanvas()
 {
 }

 void QContext2DCanvas::setInterval(const QScriptValue &func,
                                    qreal interval)
 {
     m_intervalFunc = func;
     m_timer.setInterval((int)interval);
     m_timer.start();
 }

 void QContext2DCanvas::resize(int w, int h)
 {
     QWidget::resize(w, h);
 }


Copyright © 2008 Trolltech Trademarks
Qt 4.3.5