From cc5a322cbfa9ae84a6114ef7c171d7e119e6a86c Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 6 Jul 2009 16:22:56 +1000 Subject: Make TextEdit's cursor position usable from Qml. --- src/declarative/fx/qfxtextedit.cpp | 21 ++++++++++++++++++++- src/declarative/fx/qfxtextedit.h | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index 7f08fba..3778e9a 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -410,7 +410,7 @@ void QFxTextEdit::setWrap(bool w) } /*! - \property QFxTextEdit::cursorVisible + \qmlproperty TextEdit::cursorVisible \brief If true the text edit shows a cursor. This property is set and unset when the text edit gets focus, but it can also @@ -435,6 +435,25 @@ void QFxTextEdit::setCursorVisible(bool on) } /*! + \qmlproperty TextEdit::cursorPosition + \brief The position of the cursor in the TextEdit. +*/ +int QFxTextEdit::cursorPosition() const +{ + Q_D(const QFxTextEdit); + return d->control->textCursor().position(); +} + +void QFxTextEdit::setCursorPosition(int pos) +{ + Q_D(QFxTextEdit); + QTextCursor cursor = d->control->textCursor(); + if (cursor.position() == pos) + return; + cursor.setPosition(pos); +} + +/*! \qmlproperty bool TextEdit::focusOnPress Whether the TextEdit should gain focus on a mouse press. By default this is diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h index 24ba3fe..6988822 100644 --- a/src/declarative/fx/qfxtextedit.h +++ b/src/declarative/fx/qfxtextedit.h @@ -77,6 +77,7 @@ class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible) + Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition) Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress) Q_PROPERTY(bool preserveSelection READ preserveSelection WRITE setPreserveSelection) Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin) @@ -129,6 +130,9 @@ public: bool isCursorVisible() const; void setCursorVisible(bool on); + int cursorPosition() const; + void setCursorPosition(int pos); + bool focusOnPress() const; void setFocusOnPress(bool on); -- cgit v0.12 From 2e063be4256d64599fd04d40894b187e0dbba045 Mon Sep 17 00:00:00 2001 From: mae Date: Mon, 6 Jul 2009 19:08:55 +0200 Subject: extend the QObjectPrivate::connectedSignals bitfield to make space for all the required NOTIFY signals we need for QML bindings. An additional internal function QMetaObject::isConnected() allows to query the bits, or you use connectedSignals[0] if you know that the signal in question has a QMetaObject::indexOfSignal() < 32. --- src/corelib/animation/qvariantanimation.cpp | 2 +- src/corelib/kernel/qobject.cpp | 77 +++++++++++++++++++++++------ src/corelib/kernel/qobject_p.h | 2 +- src/corelib/kernel/qobjectdefs.h | 3 ++ src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 8 +-- 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index c5c805f..d166869 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -267,7 +267,7 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) localProgress); qSwap(currentValue, ret); q->updateCurrentValue(currentValue); - if ((connectedSignals & changedSignalMask) && currentValue != ret) { + if ((connectedSignals[0] & changedSignalMask) && currentValue != ret) { //the value has changed emit q->valueChanged(currentValue); } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d53ca7d..724ebca 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -139,7 +139,8 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals = 0; + for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) + connectedSignals[i] = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; @@ -2831,10 +2832,16 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, s->d_func()->addConnection(signal_index, c); - if (signal_index < 0) - sender->d_func()->connectedSignals = ~0u; - else if (signal_index < 32) - sender->d_func()->connectedSignals |= (1 << signal_index); + if (signal_index < 0) { + for (uint i = 0; i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0] ); ++i) + sender->d_func()->connectedSignals[i] = ~0u; + } else if (signal_index < (int)sizeof sender->d_func()->connectedSignals * 8) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + sender->d_func()->connectedSignals[n] |= (1 << (signal_index - n * 8 + * sizeof sender->d_func()->connectedSignals[0])); + } + return true; } @@ -3174,11 +3181,12 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) { - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3191,11 +3199,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void **argv) { int signal_index = m->methodOffset() + local_signal_index; - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3207,21 +3216,59 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void QMetaObject::activate(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) { + Q_ASSERT(from_local_signal_index <= to_local_signal_index); int offset = m->methodOffset(); int from_signal_index = offset + from_local_signal_index; int to_signal_index = offset + to_local_signal_index; - if (to_signal_index < 32 + + if (to_signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = (1 << (to_signal_index + 1)) - 1; - signal_mask ^= (1 << from_signal_index) - 1; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + + uint n = (from_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (from_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + uint nt = (to_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint mt = 1 << (to_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + bool connected = false; + quint32 *connectedSignals = sender->d_func()->connectedSignals; + for (uint i = 0; !connected && i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0]); ++i) { + uint mask = 0; + if (i > n) + mask = ~0u; + else if (i == n) + mask = ~(m -1); + if (i > nt) + mask = 0; + else if (i == nt) + mask &= (mt << 1) - 1; + connected = connectedSignals[i] & mask; + } + if (!connected) // nothing connected to these signals, and no spy return; } activate(sender, from_signal_index, to_signal_index, argv); } +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. +*/ +bool QMetaObject::isConnected(QObject *sender, int signal_index) { + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) + // nothing connected to these signals, and no spy + return false; + } + return true; +} /***************************************************************************** Properties diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 1b8aee6..83239fe 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -150,7 +150,7 @@ public: QList propertyValues; }; ExtraData *extraData; - mutable quint32 connectedSignals; + mutable quint32 connectedSignals[2]; QString objectName; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 7eb7c44..abfb01a 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -336,6 +336,9 @@ struct Q_CORE_EXPORT QMetaObject static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); + + static bool isConnected(QObject *sender, int signal_index); + // internal guarded pointers static void addGuard(QObject **ptr); static void removeGuard(QObject **ptr); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2223f5d..4c15a15 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6490,7 +6490,7 @@ void QGraphicsItem::prepareGeometryChange() // if someone is connected to the changed signal or the scene has no views. // Note that this has to be done *after* markDirty to ensure that // _q_processDirtyItems is called before _q_emitUpdated. - if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) + if ((scenePrivate->connectedSignals[0] & scenePrivate->changedSignalMask) || scenePrivate->views.isEmpty()) { d_ptr->scene->update(sceneTransform().mapRect(boundingRect())); } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e50ee94..7e7ea98 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -604,7 +604,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from // Qt 4.4 and backward. - if (connectedSignals & changedSignalMask) { + if (connectedSignals[0] & changedSignalMask) { for (int i = 0; i < views.size(); ++i) { QGraphicsView *view = views.at(i); if (!view->d_func()->connectedToScene) { @@ -3730,7 +3730,7 @@ void QGraphicsScene::update(const QRectF &rect) // Check if anyone's connected; if not, we can send updates directly to // the views. Otherwise or if there are no views, use old behavior. - bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty(); + bool directUpdates = !(d->connectedSignals[0] & d->changedSignalMask) && !d->views.isEmpty(); if (rect.isNull()) { d->updateAll = true; d->updatedRects.clear(); @@ -5394,7 +5394,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (removingItemFromScene) { // Note that this function can be called from the item's destructor, so // do NOT call any virtual functions on it within this block. - if ((connectedSignals & changedSignalMask) || views.isEmpty()) { + if ((connectedSignals[0] & changedSignalMask) || views.isEmpty()) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. @@ -5481,7 +5481,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { - const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); + const bool useCompatUpdate = views.isEmpty() || (connectedSignals[0] & changedSignalMask); const bool untransformableItem = item->d_ptr->itemIsUntransformable(); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); -- cgit v0.12 From 36018fb9de1d1943454d518fb4df1f8df41e67b5 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 7 Jul 2009 09:38:31 +1000 Subject: Add textFormat property to the Text element. --- src/declarative/fx/qfxtext.cpp | 75 +++++++++++++++++++++++++++++++++++++- src/declarative/fx/qfxtext.h | 8 ++++ src/declarative/fx/qfxtext_p.h | 4 +- src/declarative/fx/qfxtextedit.cpp | 2 +- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index f2519dc..57897ed 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -162,7 +162,7 @@ void QFxText::setText(const QString &n) if (d->text == n) return; - d->richText = Qt::mightBeRichText(n); // ### what's the cost? + d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n)); if (d->richText) { if (!d->doc) { @@ -170,7 +170,7 @@ void QFxText::setText(const QString &n) d->control->setTextInteractionFlags(Qt::TextBrowserInteraction); d->doc = d->control->document(); d->doc->setDocumentMargin(0); - } + } d->doc->setHtml(n); } @@ -377,6 +377,77 @@ void QFxText::setWrap(bool w) } /*! + \qmlproperty enumeration Text::textFormat + + The way the text property should be displayed. + + Supported text formats are \c AutoText, \c PlainText and \c RichText. + + The default is AutoText. If the text format is AutoText the text element + will automatically determine whether the text should be treated as + rich text. This determination is made using Qt::mightBeRichText(). + + \table + \row + \o + \qml +VerticalLayout { + TextEdit { + font.size: 24 + text: "Hello World!" + } + TextEdit { + font.size: 24 + textFormat: "RichText" + text: "Hello World!" + } + TextEdit { + font.size: 24 + textFormat: "PlainText" + text: "Hello World!" + } +} + \endqml + \o \image declarative-textformat.png + \endtable +*/ + +QFxText::TextFormat QFxText::textFormat() const +{ + Q_D(const QFxText); + return d->format; +} + +void QFxText::setTextFormat(TextFormat format) +{ + Q_D(QFxText); + if (format == d->format) + return; + bool wasRich = d->richText; + d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text)); + + if (wasRich && !d->richText) { + //### delete control? (and vice-versa below) + d->imgDirty = true; + d->updateSize(); + update(); + } else if (!wasRich && d->richText) { + if (!d->doc) + { + d->control = new QTextControl(this); + d->control->setTextInteractionFlags(Qt::TextBrowserInteraction); + d->doc = d->control->document(); + d->doc->setDocumentMargin(0); + } + d->doc->setHtml(d->text); + d->imgDirty = true; + d->updateSize(); + update(); + } + d->format = format; +} + +/*! \qmlproperty Qt::TextElideMode Text::elide Set this property to elide parts of the text fit to the Text item's width. diff --git a/src/declarative/fx/qfxtext.h b/src/declarative/fx/qfxtext.h index ee38a94..bd91f0e 100644 --- a/src/declarative/fx/qfxtext.h +++ b/src/declarative/fx/qfxtext.h @@ -58,6 +58,7 @@ class Q_DECLARATIVE_EXPORT QFxText : public QFxItem Q_ENUMS(HAlignment) Q_ENUMS(VAlignment) Q_ENUMS(TextStyle) + Q_ENUMS(TextFormat) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QmlFont *font READ font CONSTANT) @@ -67,6 +68,7 @@ class Q_DECLARATIVE_EXPORT QFxText : public QFxItem Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign) Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign) Q_PROPERTY(bool wrap READ wrap WRITE setWrap) + Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat) Q_PROPERTY(Qt::TextElideMode elide READ elideMode WRITE setElideMode) Q_PROPERTY(QString activeLink READ activeLink) Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform) @@ -85,6 +87,9 @@ public: Outline, Raised, Sunken }; + enum TextFormat { AutoText, + PlainText, + RichText }; QString text() const; void setText(const QString &); @@ -109,6 +114,9 @@ public: bool wrap() const; void setWrap(bool w); + TextFormat textFormat() const; + void setTextFormat(TextFormat format); + Qt::TextElideMode elideMode() const; void setElideMode(Qt::TextElideMode); diff --git a/src/declarative/fx/qfxtext_p.h b/src/declarative/fx/qfxtext_p.h index c58705c..670b685 100644 --- a/src/declarative/fx/qfxtext_p.h +++ b/src/declarative/fx/qfxtext_p.h @@ -75,7 +75,8 @@ public: QFxTextPrivate() : _font(0), color((QRgb)0), style(QFxText::Normal), imgDirty(true), hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone), - dirty(false), wrap(false), smooth(false), richText(false), singleline(false), control(0), doc(0) + dirty(false), wrap(false), smooth(false), richText(false), singleline(false), control(0), doc(0), + format(QFxText::AutoText) { } @@ -132,6 +133,7 @@ public: QTextDocument *doc; QTextLayout layout; QSize cachedLayoutSize; + QFxText::TextFormat format; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index 3778e9a..7162bdf 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -179,7 +179,7 @@ void QFxTextEdit::setText(const QString &text) Supported text formats are \c AutoText, \c PlainText and \c RichText. The default is AutoText. If the text format is AutoText the text edit - edit will automatically determine whether the text should be treated as + will automatically determine whether the text should be treated as rich text. This determination is made using Qt::mightBeRichText(). \table -- cgit v0.12 From a2c1be26c495efac6da1668c24675afa7fc1142b Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 7 Jul 2009 09:51:05 +1000 Subject: Mark QMetaObjectBuilder and friends as internal. --- src/corelib/kernel/qmetaobjectbuilder.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index d4891ff..8775c5c 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE /*! \class QMetaObjectBuilder + \internal \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime. */ @@ -1725,6 +1726,7 @@ void QMetaObjectBuilder::deserialize /*! \class QMetaMethodBuilder + \internal \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder. */ @@ -1921,6 +1923,7 @@ void QMetaMethodBuilder::setAttributes(int value) /*! \class QMetaPropertyBuilder + \internal \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder. */ @@ -2340,6 +2343,7 @@ void QMetaPropertyBuilder::setDynamic(bool value) /*! \class QMetaEnumBuilder + \internal \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder. */ -- cgit v0.12