📄 kwqobject.cpp
字号:
/*
* Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
* Portions Copyright (c) 2005 Nokia Corporation, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "KWQObject.h"
#include "KWQVariant.h"
#include "KWQAssertions.h"
#include "KWQPtrList.h"
#include "KWQPtrDict.h"
#include "KWQTimer.h"
#include <e32base.h>
// symbian timer object
class KWQObjectTimerTarget : public CActive
{
public:
KWQObjectTimerTarget(QObject* aTarget, TInt aTimerId);
virtual ~KWQObjectTimerTarget();
void SendTimerEvent();
void RunL();
void DoCancel();
void Start(TInt aDelayMilli);
void Pause();
void Resume();
void SetTarget(QObject* aTarget) { iTarget = aTarget; }
void DeleteNowOrLater();
TInt TimerId() { return iTimerId; }
void StartTimer(TInt aDelayMilli);
private:
TInt iTimerId;
QObject* iTarget;
RTimer iTimer;
TInt iRemainingDelayMilli;
TInt iCumulativePauses;
TInt iDelayMilli;
TTime iStarted;
TBool iInTimerEvent;
TBool iKillMe;
};
// this code is lifted from GTK Linux version
// it uses Q-collections instead of native ones like Apple code does
// -antti
typedef QPtrList<KWQObjectTimerTarget> PausedTimerList;
const QObject *QObject::_sender;
bool QObject::_defersTimers = false;
static QPtrDict<PausedTimerList> allPausedTimers;
static QPtrList<KWQObjectTimerTarget> deferredTimers;
static bool deferringTimers = false;
struct _initer {
_initer() {
allPausedTimers.setAutoDelete(true);
}
};
static _initer _hack_initer;
KWQSignal *QObject::findSignal(const char *signalName) const
{
for (KWQSignal *signal = _signalListHead; signal; signal = signal->_next) {
if (KWQNamesMatch(signalName, signal->_name)) {
return signal;
}
}
return 0;
}
void QObject::connect(const QObject *sender, const char *signalName, const QObject *receiver, const char *member)
{
// FIXME: Assert that sender is not NULL rather than doing the if statement.
if (!sender) {
return;
}
KWQSignal *signal = sender->findSignal(signalName);
if (!signal) {
#if !ERROR_DISABLED
if (1
&& !KWQNamesMatch(member, SIGNAL(setStatusBarText(const QString &)))
&& !KWQNamesMatch(member, SLOT(slotHistoryChanged()))
&& !KWQNamesMatch(member, SLOT(slotJobPercent(KIO::Job *, unsigned long)))
&& !KWQNamesMatch(member, SLOT(slotJobSpeed(KIO::Job *, unsigned long)))
&& !KWQNamesMatch(member, SLOT(slotScrollBarMoved()))
&& !KWQNamesMatch(member, SLOT(slotShowDocument(const QString &, const QString &)))
&& !KWQNamesMatch(member, SLOT(slotViewCleared())) // FIXME: Should implement this one!
)
ERROR("connecting member %s to signal %s, but that signal was not found", member, signalName);
#endif
return;
}
signal->connect(KWQSlot(const_cast<QObject *>(receiver), member));
}
void QObject::disconnect(const QObject *sender, const char *signalName, const QObject *receiver, const char *member)
{
// FIXME: Assert that sender is not NULL rather than doing the if statement.
if (!sender)
return;
KWQSignal *signal = sender->findSignal(signalName);
if (!signal) {
// FIXME: ERROR
return;
}
signal->disconnect(KWQSlot(const_cast<QObject *>(receiver), member));
}
KWQObjectSenderScope::KWQObjectSenderScope(const QObject *o)
: _savedSender(QObject::_sender)
{
QObject::_sender = o;
}
KWQObjectSenderScope::~KWQObjectSenderScope()
{
QObject::_sender = _savedSender;
}
QObject::QObject(QObject *parent, const char *name)
: _signalListHead(0), _signalsBlocked(false)
, _destroyed(this, SIGNAL(destroyed()))
, _eventFilterObject(0)
{
_guardedPtrDummyList.append(this);
_timers.setAutoDelete(false);
}
QObject::~QObject()
{
_destroyed.call();
ASSERT(_signalListHead == &_destroyed);
killTimers();
}
void QObject::timerEvent(QTimerEvent *te)
{
}
bool QObject::event(QEvent *)
{
return false;
}
KWQObjectTimerTarget* _find(QPtrList<KWQObjectTimerTarget> *l, int id)
{
QPtrListIterator<KWQObjectTimerTarget> it(*l);
KWQObjectTimerTarget *p = 0;
while((p=it.current())) {
if (p->TimerId() == id)
return p;
++it;
}
return p;
}
void QObject::pauseTimer (int timerId, const void *key)
{
KWQObjectTimerTarget* target = _find(&_timers, timerId);
if (target) {
PausedTimerList* pausedTimers = allPausedTimers.find(const_cast<void*>(key));
if (!pausedTimers) {
pausedTimers = new PausedTimerList;
allPausedTimers.insert(const_cast<void*>(key), pausedTimers);
}
target->Pause();
pausedTimers->append(target);
_timers.removeRef(target);
}
}
static int nextTimerID = 1;
/*
void QObject::clearPausedTimers (const void *key)
{
PausedTimerList* pausedTimers = allPausedTimers.find(const_cast<void*>(key));
if (pausedTimers) {
pausedTimers->setAutoDelete(true); //delete all paused timers
allPausedTimers.remove(const_cast<void*>(key)); // pausedTimers entry deleted
}
}*/
void QObject::resumeTimers (const void *key, QObject *_target)
{
PausedTimerList* pausedTimers = allPausedTimers.find(const_cast<void*>(key));
if (!pausedTimers)
return;
int maxId = QMAX(0, nextTimerID);
QPtrListIterator<KWQObjectTimerTarget> it(*pausedTimers);
KWQObjectTimerTarget *target = 0;
while((target=it.current())) {
target->SetTarget(_target);
target->Resume();
maxId = QMAX(maxId, target->TimerId());
_timers.append(target);
++it;
}
nextTimerID = maxId+1;
allPausedTimers.remove(const_cast<void*>(key)); // pausedTimers entry deleted, do not delete contents
}
int QObject::startTimer(int milliseconds)
{
KWQObjectTimerTarget *target = new KWQObjectTimerTarget(this, nextTimerID);
target->Start(milliseconds);
_timers.append(target);
return nextTimerID++;
}
void QObject::killTimer(int timerId)
{
if (timerId == 0) {
return;
}
KWQObjectTimerTarget *p = _find(&_timers, timerId);
if (p) {
deferredTimers.removeRef(p);
_timers.removeRef(p);
p->DeleteNowOrLater();
}
}
void QObject::killTimers()
{
deferredTimers.clear(); // not deleted
QPtrListIterator<KWQObjectTimerTarget> it(_timers);
KWQObjectTimerTarget *target = 0;
while((target=it.current())) {
target->DeleteNowOrLater();
++it;
}
_timers.clear();
}
static void stopDeferringTimers()
{
ASSERT(deferringTimers);
deferredTimers.first();
while (deferredTimers.current() != 0) {
// remove before sending the timer event, in case the timer
// callback cancels the timer - we don't want to remove too
// much in that case.
KWQObjectTimerTarget *timerTarget = deferredTimers.take();
timerTarget->StartTimer(0);
}
deferringTimers = false;
QTimer::stopDeferringTimers();
}
void QObject::setDefersTimers(bool defers)
{
if (defers) {
_defersTimers = true;
deferringTimers = true;
// NOTE: apples version is async:
// [NSObject cancelPreviousPerformRequestsWithTarget:[KWQObjectTimerTarget class]];
return;
}
if (_defersTimers) {
_defersTimers = false;
if (deferringTimers) {
// NOTE: Apples' version is async:
// [KWQObjectTimerTarget performSelector:@selector(stopDeferringTimers) withObject:nil afterDelay:0];
stopDeferringTimers();
}
}
}
KWQObjectTimerTarget::KWQObjectTimerTarget(QObject* aTarget, TInt aTimerId)
: CActive(CActive::EPriorityStandard)
{
iTimer.CreateLocal();
iTarget = aTarget;
iTimerId = aTimerId;
CActiveScheduler::Add(this);
}
KWQObjectTimerTarget::~KWQObjectTimerTarget()
{
Cancel();
iTimer.Close();
}
void KWQObjectTimerTarget::SendTimerEvent()
{
OOM_CRITICAL_PATH_BEGIN( "KWQObjectTimerTarget::SendTimerEvent", 0 )
QTimerEvent event(iTimerId);
iTarget->timerEvent(&event);
OOM_CRITICAL_PATH_END
}
void KWQObjectTimerTarget::RunL()
{
if (iRemainingDelayMilli)
{
// work around maxint limitation in After(), start the time again
StartTimer(iRemainingDelayMilli);
}
else if (deferringTimers) {
if (!deferredTimers.containsRef(this)) {
deferredTimers.append(this);
}
} else {
TTime timeBefore;
timeBefore.HomeTime();
// guard against deletion
iInTimerEvent = ETrue;
// send the event
SendTimerEvent();
//
iInTimerEvent = EFalse;
// were we killed during the timer event?
if (iKillMe)
delete this; // delete now
else
{
// restart timer, substract the time used to process the event from the delay
TTime timeNow;
timeNow.HomeTime();
TInt eventProcessingTime = I64INT(timeNow.MicroSecondsFrom(timeBefore).Int64()/1000);
iCumulativePauses = 0;
StartTimer(Max(1,iDelayMilli-eventProcessingTime));
}
}
}
void KWQObjectTimerTarget::DeleteNowOrLater()
{
// if this was called from a timer event delay deletion
if (iInTimerEvent)
iKillMe = ETrue;
else
delete this;
}
void KWQObjectTimerTarget::DoCancel()
{
iTimer.Cancel();
}
void KWQObjectTimerTarget::Start(TInt aDelayMilli)
{
iCumulativePauses = 0;
iDelayMilli = aDelayMilli;
StartTimer(iDelayMilli);
}
void KWQObjectTimerTarget::StartTimer(TInt aDelayMilli)
{
Cancel();
if (aDelayMilli<0)
aDelayMilli = 0;
// prevent maxint overflows
TInt t;
if (aDelayMilli<(TInt)(KMaxTInt32/1000))
{
t = aDelayMilli*1000;
iRemainingDelayMilli = 0;
}
else
{
t = KMaxTInt32;
iRemainingDelayMilli = aDelayMilli - (TInt)(KMaxTInt32/1000);
}
iStarted.HomeTime();
iTimer.After(iStatus, t);
SetActive();
}
void KWQObjectTimerTarget::Pause()
{
TTime timeNow;
timeNow.HomeTime();
iCumulativePauses = iCumulativePauses + I64INT(timeNow.MicroSecondsFrom(iStarted).Int64()/1000);
Cancel();
}
void KWQObjectTimerTarget::Resume()
{
TInt t = iDelayMilli - iCumulativePauses;
if (t<0)
t = 0;
StartTimer(t);
}
bool QObject::inherits(const char *className) const
{
if (strcmp(className, "RenderLineEdit") == 0) {
return isRenderLineEdit();
}
if (strcmp(className, "Loader") == 0) {
return isLoader();
}
if (strcmp(className, "KHTMLPart") == 0) {
return isKHTMLPart();
}
if (strcmp(className, "KHTMLView") == 0) {
return isKHTMLView();
}
if (strcmp(className, "KParts::Factory") == 0) {
return false;
}
if (strcmp(className, "KParts::ReadOnlyPart") == 0) {
return isKPartsReadOnlyPart();
}
if (strcmp(className, "QFrame") == 0) {
return isQFrame();
}
if (strcmp(className, "QScrollView") == 0) {
return isQScrollView();
}
ERROR("class name %s not recognized", className);
return false;
}
bool QObject::isKHTMLPart() const
{
return false;
}
bool QObject::isKHTMLView() const
{
return false;
}
bool QObject::isKPartsReadOnlyPart() const
{
return false;
}
bool QObject::isQFrame() const
{
return false;
}
bool QObject::isQScrollView() const
{
return false;
}
bool QObject::isRenderLineEdit() const
{
return false;
}
bool QObject::isLoader() const
{
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -