diff -r 7516d6d86cf5 -r ed14f46c0e55 src/hbwidgets/editors/hbabstractedit.cpp --- a/src/hbwidgets/editors/hbabstractedit.cpp Mon Oct 04 17:49:30 2010 +0300 +++ b/src/hbwidgets/editors/hbabstractedit.cpp Mon Oct 18 18:23:13 2010 +0300 @@ -38,11 +38,10 @@ #include "hbselectioncontrol_p.h" #include "hbsmileyengine_p.h" #include "hbinputeditorinterface.h" -#include "hbfeaturemanager_r.h" -#include "hbtextmeasurementutility_p.h" -#include "hbtapgesture.h" -#include "hbpangesture.h" -#include "hbnamespace_p.h" +#ifdef HB_TEXT_MEASUREMENT_UTILITY +#include "hbtextmeasurementutility_r.h" +#include "hbtextmeasurementutility_r_p.h" +#endif #include #include "hbpopup.h" @@ -93,8 +92,9 @@ editor widget only one or the other type might be supported. Plain text content is set with method \ref setPlainText. Method \ref toPlainText returns the content converted to plain text. - \li Focus control: Editor is responsble for controlling the input panel visibility. In some situations special editor may need to also handle this, but in general it is always handled by HbAbstractEdit. - Input panel is closed when editor loses focus. + \li Focus control: Editor is responsble for controlling the input panel visibility. In some situations special editor may need to also handle this, + but in general it is always handled by HbAbstractEdit. Input panel is closed when editor loses focus. + However when setting the editor focus programmatically with setFocus() it is the responsibility of client to control the visibility of input panel. \li Cursor control: A convenience method \ref moveCursor can also be used to move the cursor. @@ -107,14 +107,7 @@ \section composition Widget composition - Editor widget consists of these sub-items visible in the picture. - In this example editor shows only one visible line of the content. - - \image html editor_composition.jpg - - The size of the canvas is always same as the size of the document, and the width of the scroll area - is same as the width of the document. The editor margins are defined in the CSS. - + The size of the canvas is always same as the size of the document, and the width of the scroll area is same as the width of the document. */ /*! @@ -153,6 +146,9 @@ #define Hb_Invalid_Position QPointF(-1.0, -1.0) + + + /*! Constructs a HbAbstractEdit with parent \a parent. */ @@ -225,6 +221,18 @@ d->smileyEngineInstance()->insertSmiley(matchCursor); d->cursorChanged(HbValidator::CursorChangeFromContentUpdate); + } else if (p == "Magnifier") { + QString param = property("Magnifier").toString(); + + if (param == "Enabled") { + d->enableMagnifier = true; + } else if (param == "Disabled") { + d->enableMagnifier = false; + } + + if (d->selectionControl) { + d->selectionControl->setMagnifierEnabled(d->enableMagnifier); + } } } else { //HbEvent handler if (event->type() == HbEvent::InputMethodFocusIn) { @@ -283,6 +291,10 @@ d->cursor.beginEditBlock(); if (isGettingInput) { + if (d->selectionControl) { + d->selectionControl->hideHandles(); + d->updateCursorType(); + } if (!d->imEditInProgress) { d->imEditInProgress = true; d->imPosition = d->selectionCursor.selectionStart(); @@ -345,10 +357,8 @@ d->_q_contentsChanged(); } - if(d->hasInputFocus()) { - d->cursorOn = true; - } d->ensureCursorVisible(); + d->canvas->setPreferredSize(d->calculatePreferredDocSize()); } /*! @@ -358,8 +368,10 @@ { Q_D(HbAbstractEdit); - if (d->interactionFlags & Qt::NoTextInteraction) - return; + if (d->selectionControl) { + d->selectionControl->hideHandles(); + d->updateCursorType(); + } #ifndef QT_NO_SHORTCUT #ifndef QT_NO_CLIPBOARD @@ -489,9 +501,7 @@ HbWidget::focusInEvent(event); d->selectionControl = HbSelectionControl::attachEditor(this); - - if (d->interactionFlags & Qt::NoTextInteraction) - return; + d->selectionControl->setMagnifierEnabled(isSelectionControlEnabled()&&d->enableMagnifier); // It sets the cursor the focus item's depending on if // the input panel is connceted or not @@ -509,9 +519,6 @@ Q_D(HbAbstractEdit); - if (d->interactionFlags & Qt::NoTextInteraction) - return; - // It sets the cursor the focus item's depending on if // the input panel is connceted or not d->setInputFocusEnabled(d->hasInputFocus()); @@ -680,7 +687,7 @@ Returns pointer to a \a primitive of HbAbstractEdit. - Available primitive is HbStyle::P_Edit_text. + Available primitive is HbStylePrivate::P_Edit_text. \reimp \sa HbStyle::Primitive, HbWidget::primitive() @@ -688,8 +695,8 @@ QGraphicsItem *HbAbstractEdit::primitive (HbStyle::Primitive primitive) const { Q_D(const HbAbstractEdit); - - if (primitive == HbStyle::P_Edit_text) { + const HbStylePrivate::Primitive p = (HbStylePrivate::Primitive)primitive; + if (p == HbStylePrivate::P_Edit_text) { return d->scrollArea; } else { return HbWidget::primitive(primitive); @@ -723,6 +730,7 @@ } d->canvas->setGeometry(canvasGeom); + d->canvas->setPreferredSize(d->calculatePreferredDocSize()); d->ensureCursorVisible(); if (d->selectionControl) { @@ -777,12 +785,15 @@ Q_D(HbAbstractEdit); if (e->timerId() == d->cursorBlinkTimer.timerId()) { - d->cursorOn = !d->cursorOn; + d->cursorOn = !d->cursorOn; + d->repaintCursor(); + } else if (e->timerId() == d->doubleTapTimer.timerId()) { + d->doubleTapTimer.stop(); - if (d->cursor.hasSelection()) - d->cursorOn &= (QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) != 0); - - d->repaintCursor(); + if (d->tapCounter == 1 && d->showContextMenu && contextMenuFlags().testFlag(Hb::ShowTextContextMenuOnSelectionClicked)) { + showContextMenu(mapToScene(d->tapPosition)); + } + d->tapCounter = 0; } } @@ -885,8 +896,9 @@ Q_D(HbAbstractEdit); if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection()) return; - copy(); + copy(); d->cursor.removeSelectedText(); + d->cursorChanged(HbValidator::CursorChangeFromContentUpdate); #endif//QT_NO_CLIPBOARD } @@ -926,8 +938,8 @@ if (md) { insertFromMimeData(md); } + d->cursorChanged(HbValidator::CursorChangeFromContentUpdate); } - #endif//QT_NO_CLIPBOARD } @@ -945,7 +957,7 @@ if (cursorPos == -1) return; - setCursorPosition(cursorPos); + d->cursor.setPosition(cursorPos); d->cursor.select(QTextCursor::WordUnderCursor); d->cursorChanged(HbValidator::CursorChangeFromMouse); } @@ -1064,6 +1076,7 @@ return rect; } + /*! Returns the contents as plain text. If smiley recognition is enabled all the smiley images will be replaced by their textual representations. @@ -1111,7 +1124,9 @@ Q_D(HbAbstractEdit); d->validator = validator; - d->initValidator(); + if (d->validator) { + d->initValidator(); + } } /*! @@ -1202,8 +1217,24 @@ Q_D(HbAbstractEdit); #ifdef HB_DEBUG_EDITOR_DRAW_RECTS painter->setPen(Qt::green); - /*for(QTextBlock tb = d->doc->begin(); tb.isValid(); tb=tb.next()) { - painter->drawRect(blockBoundingRect(tb)); + /* + for(QTextBlock tb = d->doc->begin(); tb.isValid(); tb=tb.next()) { + painter->drawRect(blockBoundingRect(tb)); + + // Draw lines + const QPointF layoutPos = blockBoundingRect(tb).topLeft(); + + painter->setPen(Qt::red); + const QTextLayout *layout = tb.layout(); + for(int i = 0;i < layout->lineCount();i++) { + QTextLine line = layout->lineAt(i); + + // Draw descent rect + QRectF rect = QRectF(layoutPos.x() + line.x(), + layoutPos.y() + line.y() + line.ascent(), + line.width(),line.descent()+1); + painter->drawRect(rect); + } }*/ painter->drawRect(d->doc->documentLayout()->frameBoundingRect( d->doc->rootFrame()).adjusted(2,2,-2,-2)); @@ -1218,13 +1249,14 @@ QAbstractTextDocumentLayout::PaintContext ctx = d->getPaintContext(); - // Save painter state that will be modified - QRegion clipRegion = painter->clipRegion(); if (option.exposedRect.isValid()){ painter->setClipRect(intersected, Qt::IntersectClip); } ctx.clip = intersected; + // Disable drawing of Qt cursor and save old cursor position + int oldCursorPosition = ctx.cursorPosition; + ctx.cursorPosition = -1; d->drawContentBackground(painter, option); @@ -1235,19 +1267,16 @@ if(!layout->preeditAreaText().length()) { QColor textColor(ctx.palette.color(QPalette::Text)); QColor hintText(ctx.palette.color(QPalette::NoRole)); - int cursorPos = ctx.cursorPosition; - ctx.cursorPosition = -1; ctx.palette.setColor(QPalette::Text, hintText); d->placeholderDoc->documentLayout()->draw(painter, ctx); ctx.palette.setColor(QPalette::Text, textColor); - ctx.cursorPosition = cursorPos; } } document()->documentLayout()->draw(painter, ctx); - // Draw the pins for the selection handle - d->drawSelectionEdges(painter, ctx); + ctx.cursorPosition = oldCursorPosition; + d->drawCursor(painter, ctx); #ifdef HB_DEBUG_EDITOR_HANDLES QRectF a = rectForPosition(d->cursor.anchor()); @@ -1260,8 +1289,6 @@ painter->setPen(Qt::red); painter->drawRect(d->cursorRect()); #endif - // Restore state - painter->setClipRegion(clipRegion); } /*! @@ -1310,45 +1337,36 @@ if (d->cursor.hasSelection() && d->canCut()) { connect( - menu->addAction(hbTrId("txt_common_menu_cut")), SIGNAL(triggered()), - this, SLOT(cut())); + menu->addAction(hbTrId("txt_common_menu_cut")), SIGNAL(triggered()), this, SLOT(cut())); } if (d->cursor.hasSelection() && d->canCopy()) { connect( - menu->addAction(hbTrId("txt_common_menu_copy")), SIGNAL(triggered()), - this, SLOT(copy())); + menu->addAction(hbTrId("txt_common_menu_copy")), SIGNAL(triggered()), this, SLOT(copy())); } if (!d->cursor.hasSelection() && !d->doc->isEmpty() && d->canCopy()){ connect( - menu->addAction(hbTrId("txt_common_menu_select")), SIGNAL(triggered()), - this, SLOT(selectClickedWord())); - connect( - menu->addAction(hbTrId("txt_common_menu_select_all_contents")), SIGNAL(triggered()), - this, SLOT(selectAll())); + menu->addAction(hbTrId("txt_common_menu_select_all_contents")), SIGNAL(triggered()), this, SLOT(selectAll())); } if (d->canPaste()) { connect( - menu->addAction(hbTrId("txt_common_menu_paste")), SIGNAL(triggered()), - this, SLOT(paste())); + menu->addAction(hbTrId("txt_common_menu_paste")), SIGNAL(triggered()), this, SLOT(paste())); } if (d->cursor.hasSelection()) { connect( - menu->addAction(hbTrId("txt_common_menu_deselect")), SIGNAL(triggered()), - this, SLOT(deselect())); + menu->addAction(hbTrId("txt_common_menu_deselect")), SIGNAL(triggered()), this, SLOT(deselect())); } if (d->canFormat()) { connect( - menu->addAction(hbTrId("txt_common_menu_format")), SIGNAL(triggered()), - this, SLOT(format())); + menu->addAction(hbTrId("txt_common_menu_format")), SIGNAL(triggered()), this, SLOT(format())); } emit aboutToShowContextMenu(menu, d->tapPosition); if(menu->actions().count() > 0){ -// d->minimizeInputPanel(); menu->setPreferredPos(position); menu->show(); } + d->showContextMenu = false; } /*! @@ -1416,8 +1434,8 @@ } /*! - Returns current flags describing on which events context menu is shown - + Returns current flags describing on which events context menu is shown. + The default value is both Hb::ShowTextContextMenuOnSelectionClicked and Hb::ShowTextContextMenuOnLongPress are set. \sa Hb::TextContextMenuFlag */ Hb::TextContextMenuFlags HbAbstractEdit::contextMenuFlags() const @@ -1428,7 +1446,8 @@ } /*! - Sets \a flags describing on which events context menu is shown + Sets \a flags describing on which events context menu is shown. + To disable context menu completely set \a flags to 0. \sa Hb::TextContextMenuFlag */ void HbAbstractEdit::setContextMenuFlags(Hb::TextContextMenuFlags flags) @@ -1492,7 +1511,7 @@ QString txt( placeholderText ); #ifdef HB_TEXT_MEASUREMENT_UTILITY - if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) { + if (HbTextMeasurementUtility::instance()->locTestMode()) { if (placeholderText.endsWith(QChar(LOC_TEST_END))) { int index = placeholderText.indexOf(QChar(LOC_TEST_START)); setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName, placeholderText.mid(index + 1, placeholderText.indexOf(QChar(LOC_TEST_END)) - index - 1) ); @@ -1520,7 +1539,7 @@ QString HbAbstractEdit::anchorAt(const QPointF &pos) const { Q_D(const HbAbstractEdit); - return d->doc->documentLayout()->anchorAt(pos); + return d->doc->documentLayout()->anchorAt(mapToItem(d->canvas,pos)); } /*! @@ -1670,11 +1689,19 @@ */ QVariant HbAbstractEdit::itemChange(GraphicsItemChange change, const QVariant &value) { - Q_D(const HbAbstractEdit); + Q_D(HbAbstractEdit); if (change == QGraphicsItem::ItemScenePositionHasChanged) { if (d->selectionControl) { d->selectionControl->updatePrimitives(); } + } else if (change == QGraphicsItem::ItemEnabledHasChanged) { + if(!value.toBool()) { + if (d->hasInputFocus()) { + d->closeInputPanel(); + } + deselect(); + } + updatePrimitives(); } return HbWidget::itemChange(change, value); } @@ -1687,55 +1714,41 @@ return document()->characterAt(pos); } +/*! + Activates or deactivates the selection control in the editor. + The selection control can be used to resize the selection or fine tune the cursor position. + Note: if the selection control is disabled the word selection is still possible by double-tap on word of text. +*/ +void HbAbstractEdit::setSelectionControlEnabled(bool enabled) +{ + Q_D(HbAbstractEdit); + if(d->enableSelectionControl != enabled) { + d->enableSelectionControl = enabled; + if(enabled && (d->hasInputFocus() || d->cursor.hasSelection())) { + d->selectionControl = HbSelectionControl::attachEditor(this); + d->selectionControl->setMagnifierEnabled(d->enableMagnifier); + d->selectionControl->showHandles(); + } else if (d->selectionControl) { + d->selectionControl->hideHandles(); + } + d->updateCursorType(); + } +} + +/*! + Return true if selection control is enabled in the editor otherwise returns false. +*/ +bool HbAbstractEdit::isSelectionControlEnabled() const +{ + Q_D(const HbAbstractEdit); + return d->enableSelectionControl; +} + + void HbAbstractEdit::gestureEvent(QGestureEvent* event) { Q_D(HbAbstractEdit); - if(HbTapGesture *tap = qobject_cast(event->gesture(Qt::TapGesture))) { - // QTapGesture::position() is in screen coordinates and thus - // needs to be transformed into items own coordinate system. - // The QGestureEvent knows the viewport through which the gesture - // was triggered. - QPointF pos = mapFromScene(event->mapToGraphicsScene(tap->position())); - switch(tap->state()) { - case Qt::GestureStarted: - scene()->setProperty(HbPrivate::OverridingGesture.latin1(),Qt::TapGesture); - if (!tap->property(HbPrivate::ThresholdRect.latin1()).toRect().isValid()) { - tap->setProperty(HbPrivate::ThresholdRect.latin1(), mapRectToScene(boundingRect()).toRect()); - } - - d->tapPosition = pos; - HbWidgetFeedback::triggered(this, Hb::InstantPressed); - break; - case Qt::GestureUpdated: - if(tap->tapStyleHint() == HbTapGesture::TapAndHold) { - d->openInputPanel(); - d->longTapGesture(pos); - } - break; - case Qt::GestureFinished: - scene()->setProperty(HbPrivate::OverridingGesture.latin1(),QVariant()); - - if(tap->tapStyleHint() == HbTapGesture::TapAndHold) { - } else { - d->tapGesture(pos); - } - - HbWidgetFeedback::triggered(this, Hb::InstantReleased); - - d->openInputPanel(); - - break; - case Qt::GestureCanceled: - scene()->setProperty(HbPrivate::OverridingGesture.latin1(),QVariant()); - - break; - default: - break; - } - event->accept(); - } else { - event->ignore(); - } + d->gestureEvent(event); } /*!