File indexing completed on 2024-09-29 12:09:25

0001 /* This file is part of the KDE libraries
0002     Copyright (C) 2003,2004,2005,2006 Ian Reinhart Geiser <geiseri@kde.org>
0003     Copyright (C) 2003,2004,2005,2006 Matt Broadstone <mbroadst@gmail.com>
0004     Copyright (C) 2003,2004,2005,2006 Richard J. Moore <rich@kde.org>
0005     Copyright (C) 2003,2004,2005,2006 Erik L. Bunce <kde@bunce.us>
0006 
0007     This library is free software; you can redistribute it and/or
0008     modify it under the terms of the GNU Library General Public
0009     License as published by the Free Software Foundation; either
0010     version 2 of the License, or (at your option) any later version.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Library General Public License for more details.
0016 
0017     You should have received a copy of the GNU Library General Public License
0018     along with this library; see the file COPYING.LIB.  If not, write to
0019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020     Boston, MA 02110-1301, USA.
0021 */
0022 #include "eventproxy.h"
0023 
0024 #include  <QCoreApplication>
0025 
0026 #include "qobject_binding.h"
0027 #include <kjs/interpreter.h>
0028 
0029 #include "kjseglobal.h"
0030 #include "jseventmapper.h"
0031 #include "jseventutils.h"
0032 
0033 using namespace KJSEmbed;
0034 
0035 EventProxy::EventProxy(QObjectBinding *watch, KJS::Interpreter *interpreter) :
0036     QObject(watch->object<QObject>()), m_watch(watch), m_interpreter(interpreter)
0037 {
0038     m_refcount = 0l;
0039 }
0040 
0041 EventProxy::~EventProxy()
0042 {
0043 }
0044 
0045 bool EventProxy::isFiltered(QEvent::Type t) const
0046 {
0047     if (m_eventMask.size() <= t) {
0048         return false;
0049     }
0050     return m_eventMask.testBit(t);
0051 }
0052 
0053 void EventProxy::addFilter(QEvent::Type t)
0054 {
0055     if (t == QEvent::None) {
0056         return;
0057     }
0058     if (!m_refcount) {
0059         m_watch->object<QObject>()->installEventFilter(this);
0060     }
0061 
0062     if (m_eventMask.size() <= t) {
0063         m_eventMask.resize(t + 1);
0064     }
0065 
0066     if (!m_eventMask.testBit(t)) {
0067         m_refcount++;
0068         m_eventMask.setBit(t);
0069     }
0070 }
0071 
0072 void EventProxy::removeFilter(QEvent::Type t)
0073 {
0074     if (t == QEvent::None) {
0075         return;
0076     }
0077     if (m_eventMask.size() <= t) {
0078         return;
0079     }
0080     m_eventMask.clearBit(t);
0081     m_refcount--;
0082     if (!m_refcount) {
0083         m_watch->object<QObject>()->removeEventFilter(this);
0084         deleteLater();
0085     }
0086 }
0087 
0088 bool EventProxy::eventFilter(QObject * /*watched*/, QEvent *e)
0089 {
0090     if (isFiltered(e->type())) {
0091         return !callHandler(e);
0092     }
0093     return false;
0094 }
0095 
0096 bool EventProxy::callHandler(QEvent *e)
0097 {
0098 // Be careful enabling this as if there are a lot of events then the event loop times
0099 // out and the app crashes with 'Alarm Clock'.
0100 //    qDebug("JSObjectEventProxy::callHandler() event type %d" , e->type() );
0101 
0102     KJS::ExecState *exec = m_interpreter->globalExec();
0103     KJS::Identifier id = JSEventMapper::mapper()->findEventHandler(e->type());
0104 
0105     KJS::JSObject *jsobj(m_watch);
0106     KJS::JSObject *fun = jsobj->get(exec, id)->toObject(exec);
0107 
0108     KJS::JSValue *retValue;
0109     if (!fun->implementsCall()) {
0110         QString msg = i18n("Bad event handler: Object %1 Identifier %2 Method %3 Type: %4.",
0111                            jsobj->className().ascii(),
0112                            id.ascii(),
0113                            fun->className().ascii(),
0114                            e->type());
0115         retValue = throwError(exec, KJS::TypeError, msg);
0116     } else {
0117         // Process args
0118         KJS::List args;
0119         args.append(JSEventUtils::event(exec, e));
0120 
0121         // Call handler
0122         retValue = fun->call(exec, jsobj, args);
0123     }
0124 
0125     if (exec->hadException()) {
0126         if (m_interpreter->shouldPrintExceptions()) {
0127             KJS::JSLock lock;
0128             KJS::JSObject *exceptObj = retValue->toObject(exec);
0129             QString message = toQString(exceptObj->toString(exec));
0130             QString sourceURL = toQString(exceptObj->get(exec, "sourceURL")->toString(exec));
0131             int sourceId = exceptObj->get(exec, "sourceId")->toUInt32(exec);
0132             int line = exceptObj->get(exec, "line")->toUInt32(exec);
0133             (*KJSEmbed::conerr()) << i18n("Exception calling '%1' function from %2:%3:%4", id.ascii(), !sourceURL.isEmpty() ? sourceURL : QString::number(sourceId), line, message) << Qt::endl;
0134         }
0135 
0136         // clear it so it doesn't stop other things
0137         exec->clearException();
0138         return false;
0139     }
0140 
0141     return true;
0142 }
0143