src/hbwidgets/editors/hbabstractedit.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbabstractedit.h"
       
    27 #include "hbabstractedit_p.h"
       
    28 
       
    29 #include "hbvalidator.h"
       
    30 #include "hbstyle.h"
       
    31 #include "hbstyleoption.h"
       
    32 #include "hbwidget.h"
       
    33 #include "hbscrollarea.h"
       
    34 #include "hbevent.h"
       
    35 #include <hbwidgetfeedback.h>
       
    36 #include "hbmenu.h"
       
    37 #include "hbaction.h"
       
    38 #include "hbselectioncontrol_p.h"
       
    39 #include "hbmeshlayout_p.h"
       
    40 #include "hbsmileyengine.h"
       
    41 #include "hbinputeditorinterface.h"
       
    42 
       
    43 #include <QApplication>
       
    44 #include "hbpopup.h"
       
    45 #include "hbformatdialog.h"
       
    46 #include <QTextList>
       
    47 #include <QFontMetrics>
       
    48 #include <QGraphicsSceneMouseEvent>
       
    49 #include <QPainter>
       
    50 #include <QTextBlock>
       
    51 #include <QAbstractTextDocumentLayout>
       
    52 #include <QClipboard>
       
    53 #include <QInputContext>
       
    54 
       
    55 /*!
       
    56     \class HbAbstractEdit
       
    57     \brief HbAbstractEdit is a base class for all text editors.
       
    58     @proto
       
    59     @hbwidgets
       
    60 
       
    61     This is not mentioned as a class to be used directly. All editors inherit this and
       
    62     basic functionality is in this class.
       
    63 
       
    64     It uses \ref QTextDocument internally to handle the content. And in some editors the document is also exposed to direct access and manipulation.
       
    65 
       
    66     \section functionality Functionality this class provides
       
    67 
       
    68     \li Editor content: The editor is set read-only with method \ref setReadOnly. Content changes emit a \ref contentsChanged signal.
       
    69 
       
    70     \li Cursor position and visibility:  Cursor position can be set with slot \ref setCursorPosition and 
       
    71     read with method \ref cursorPosition(). It is also a property. Cursor position changes emit a \ref cursorPositionChanged signal. 
       
    72     Cursor visibility can be controlled with \ref setCursorVisibility.
       
    73 
       
    74     \li Editing: There is a group of useful methods for editing the content. Clipboard functionality can be found 
       
    75     in \ref cut, \ref copy and \paste.  Finishing editing emits a \ref editingFinished signal and text changes 
       
    76     emit a \ref textChanged signal. 
       
    77 
       
    78     \li Selection handling: Whenever there is a interactive selection special handles are shown which can be used to manipulate the selection. 
       
    79     Selection changes emit a \ref selectionChanged signal.
       
    80 
       
    81     \li Anchor support: Anchors are strings associated to some a content in editor. There are two \ref anchorAt methods to access the anchors. 
       
    82     When user invokes an anchor it will open a context menu that may contain operations related to the anchor item (e.g. creating calls 
       
    83     for phone numbers, opening a web browser for web-addresses, etc.). This is always application specific functionality. 
       
    84     Editor itself does not create any anchors by examining the content.
       
    85 
       
    86     There is also protected API in HbAbstractEdit. Some of these API methods can be exposed as public in more specific editor widgets.
       
    87 
       
    88     \li Editor content:  Both rich text and plain text are supported in HbAbstractEdit. Depending on the actual 
       
    89     editor widget only one or the other type might be supported. Plain text content is set with 
       
    90     method \ref setPlainText. Method \ref toPlainText returns the content converted to plain text. 
       
    91 
       
    92     \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. 
       
    93     Input panel is closed when editor loses focus.
       
    94 
       
    95     \li Cursor control: A convenience method \ref moveCursor can also be used to move the cursor.
       
    96 
       
    97     \li Scrolling: When e.g. the size of the content exceeds the size of editor, method \ref setScrollable
       
    98     can be used to make the editor scrollable. Method isScrollable tells whether the editor is scrollable or not. 
       
    99     Method scrollArea returns the used scroll area widget. Scrolling is enabled by default.
       
   100 
       
   101     \li Input validation: The validator for restricting the content input is set with method \ref setValidator. Only \ref HbValidator
       
   102     based validators can be used.
       
   103 
       
   104     \section composition Widget composition
       
   105 
       
   106     Editor widget consists of these sub-items visible in the picture. 
       
   107     In this example editor shows only one visible line of the content.
       
   108 
       
   109     \image html editor_composition.jpg
       
   110 
       
   111     The size of the canvas is always same as the size of the document, and the width of the scroll area 
       
   112     is same as the width of the document. The editor margins are defined in the CSS.
       
   113 
       
   114 */
       
   115 
       
   116 /*!
       
   117     \fn void HbAbstractEdit::contentsChanged()
       
   118 
       
   119     This signal is emitted whenever the text changes. The text argument is the new text.
       
   120     This signal is also emitted when the text is changed programmatically, for example,
       
   121     by calling setPlainText().
       
   122 */
       
   123 
       
   124 /*!
       
   125     \fn void HbAbstractEdit::selectionChanged(const QTextCursor &oldCursor, const QTextCursor &newCursor)
       
   126 
       
   127     This signal is emitted whenever the selection changes. */
       
   128 
       
   129 /*!
       
   130     \fn void HbAbstractEdit::cursorPositionChanged(int oldPos, int newPos)
       
   131 
       
   132     This signal is emitted when cursor position has been changed.
       
   133 */
       
   134 
       
   135 /*!
       
   136     \fn QString HbAbstractEdit::toPlainText() const
       
   137 
       
   138     Returns the contents as plain text.
       
   139 
       
   140     \sa QTextDocument::toPlainText()
       
   141 */
       
   142 
       
   143 #define Hb_Invalid_Position QPointF(-1.0, -1.0)
       
   144 
       
   145 /*!
       
   146     Constructs a HbAbstractEdit with parent \a parent.
       
   147  */
       
   148 HbAbstractEdit::HbAbstractEdit(QGraphicsItem *parent) :
       
   149     HbWidget(*new HbAbstractEditPrivate, parent)
       
   150 {
       
   151     Q_D(HbAbstractEdit);
       
   152     d->q_ptr = this;
       
   153 
       
   154     d->init();
       
   155 }
       
   156 
       
   157 /*!
       
   158     Constructs a HbAbstractEdit with abstract edit private object \a dd and parent \a parent.
       
   159  */
       
   160 HbAbstractEdit::HbAbstractEdit(HbAbstractEditPrivate &dd, QGraphicsItem *parent) :
       
   161     HbWidget(dd, parent)
       
   162 {
       
   163     Q_D(HbAbstractEdit);
       
   164     d->q_ptr = this;
       
   165 
       
   166     d->init();
       
   167 }
       
   168 
       
   169 /*!
       
   170     Destructor.
       
   171 */
       
   172 HbAbstractEdit::~HbAbstractEdit()
       
   173 {
       
   174 }
       
   175 
       
   176 /*!
       
   177     \reimp
       
   178 */
       
   179 void HbAbstractEdit::resizeEvent(QGraphicsSceneResizeEvent *event)
       
   180 {    
       
   181     HbWidget::resizeEvent(event);
       
   182     updatePrimitives();
       
   183 }
       
   184 
       
   185 /*!
       
   186     \reimp
       
   187 */
       
   188 bool HbAbstractEdit::event(QEvent* event)
       
   189 {
       
   190     if(event->type() ==  QEvent::DynamicPropertyChange) {
       
   191         const QString p = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
       
   192         if(p == "SmileyIcon") {
       
   193             Q_D(HbAbstractEdit);
       
   194             QString iconName = property("SmileyIcon").toString();
       
   195 
       
   196             HbSmileyTheme smileyTheme = d->smileyEngineInstance()->theme();
       
   197 
       
   198             QString pattern = smileyTheme.patterns(iconName).first();
       
   199 
       
   200             QTextCursor cursor = textCursor();
       
   201             int oldPos = cursor.position();
       
   202 
       
   203             cursor.insertText(pattern);
       
   204             setTextCursor(cursor);
       
   205 
       
   206             QTextCursor matchCursor(document());
       
   207             matchCursor.setPosition(oldPos);
       
   208             d->smileyEngineInstance()->insertSmiley(matchCursor);
       
   209 
       
   210             d->cursorChanged(HbValidator::CursorChangeFromContentUpdate);
       
   211         }
       
   212     }
       
   213     return HbWidget::event(event);
       
   214 }
       
   215 
       
   216 /*!
       
   217     \reimp
       
   218 */
       
   219 bool HbAbstractEdit::eventFilter(QObject *obj, QEvent *e)
       
   220 {
       
   221     Q_D(HbAbstractEdit);
       
   222 
       
   223     if (obj == d->scrollArea
       
   224         && (e->type() == QEvent::GraphicsSceneMousePress
       
   225         || e->type() == QEvent::GraphicsSceneMouseMove
       
   226         || e->type() == QEvent::GraphicsSceneMouseRelease)) {
       
   227 
       
   228         // map e->pos to the editor's coordinate system
       
   229         QGraphicsSceneMouseEvent *event = static_cast<QGraphicsSceneMouseEvent*>(e);
       
   230         QPointF oldPos = event->pos();
       
   231         event->setPos(mapFromItem(d->scrollArea,oldPos));
       
   232         bool ret = sceneEvent(e);
       
   233         event->setPos(oldPos);
       
   234         return ret;
       
   235     }
       
   236 
       
   237     return false;
       
   238 }
       
   239 
       
   240 QVariant HbAbstractEdit::inputMethodQuery (Qt::InputMethodQuery query) const
       
   241 {
       
   242     Q_D(const HbAbstractEdit);
       
   243 
       
   244     QTextBlock block = d->cursor.block();
       
   245     switch(query) {
       
   246     case Qt::ImMicroFocus:
       
   247         return d->cursorRect();
       
   248     case Qt::ImFont:
       
   249         return QVariant(d->cursor.charFormat().font());
       
   250     case Qt::ImCursorPosition:
       
   251         return QVariant(d->cursor.position() - block.position());
       
   252     case Qt::ImSurroundingText:
       
   253         return QVariant(block.text());
       
   254     case Qt::ImCurrentSelection:
       
   255         return QVariant(d->cursor.selectedText());
       
   256     default:
       
   257         return QVariant();
       
   258     }
       
   259 }
       
   260 
       
   261 void HbAbstractEdit::inputMethodEvent (QInputMethodEvent *e)
       
   262 {
       
   263     Q_D(HbAbstractEdit);
       
   264     
       
   265     
       
   266     if (!(d->interactionFlags & Qt::TextEditable) || d->cursor.isNull()) {
       
   267         e->ignore();
       
   268         return;
       
   269     }
       
   270 
       
   271     QTextBlock block = d->cursor.block();
       
   272     QTextLayout *layout = block.layout();
       
   273 
       
   274     bool isGettingInput = !e->commitString().isEmpty()
       
   275             || e->preeditString() != layout->preeditAreaText()
       
   276             || e->replacementLength() > 0;
       
   277 
       
   278     d->cursor.beginEditBlock();
       
   279 
       
   280     if (isGettingInput) {
       
   281         if (!d->imEditInProgress) {
       
   282             d->imEditInProgress = true;
       
   283             d->imPosition = d->selectionCursor.selectionStart();
       
   284             d->imRemoved = d->selectionCursor.selectionEnd() - d->selectionCursor.selectionStart();
       
   285         }
       
   286 
       
   287         d->selectionCursor.removeSelectedText();
       
   288     }
       
   289 
       
   290     // insert commit string
       
   291     if (!e->commitString().isEmpty() || e->replacementLength()) {
       
   292         QTextCursor c = d->cursor;
       
   293         c.setPosition(c.position() + e->replacementStart());
       
   294         c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor);
       
   295         QString commitString = e->commitString();
       
   296         c.insertText(commitString, d->nextCharCursor.charFormat());
       
   297         d->imAdded = commitString.length();
       
   298     }
       
   299 
       
   300     if (isGettingInput) {
       
   301         layout->setPreeditArea(d->cursor.position() - block.position(), e->preeditString());
       
   302     }
       
   303 
       
   304     QList<QTextLayout::FormatRange> overrides;
       
   305     d->preeditCursor = e->preeditString().length();
       
   306 
       
   307     d->preeditCursorVisible = true;
       
   308     for (int i = 0; i < e->attributes().size(); ++i) {
       
   309         const QInputMethodEvent::Attribute &a = e->attributes().at(i);
       
   310         if (a.type == QInputMethodEvent::Cursor) {
       
   311             d->preeditCursor = a.start;
       
   312             d->preeditCursorVisible = a.length;
       
   313         } else if (a.type == QInputMethodEvent::TextFormat) {
       
   314             QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
       
   315             if (f.isValid()) {
       
   316                 QTextLayout::FormatRange o;
       
   317                 o.start = a.start + d->cursor.position() - block.position();
       
   318                 o.length = a.length;
       
   319                 o.format = f;
       
   320                 overrides.append(o);
       
   321             }
       
   322         }
       
   323     }
       
   324     layout->setAdditionalFormats(overrides);
       
   325 
       
   326     d->acceptSignalContentsChange = false;
       
   327     d->acceptSignalContentsChanged = false;
       
   328     d->cursor.endEditBlock();
       
   329     d->acceptSignalContentsChange = true;
       
   330     d->acceptSignalContentsChanged = true;
       
   331 
       
   332     d->cursorChanged(HbValidator::CursorChangeFromContentUpdate);
       
   333 
       
   334     // Input method editing is done
       
   335     if (!e->commitString().isEmpty() || e->replacementLength()) {
       
   336         d->imEditInProgress = false;
       
   337         d->imPosition = e->replacementStart();
       
   338         d->imAdded = e->commitString().length();
       
   339         d->imRemoved =  e->replacementLength();
       
   340         d->_q_contentsChanged();
       
   341     }
       
   342 
       
   343     if(hasFocus()) {
       
   344         d->cursorOn = true;
       
   345     }
       
   346     d->ensureCursorVisible();
       
   347 }
       
   348 
       
   349 /*!
       
   350     \reimp
       
   351 */
       
   352 void HbAbstractEdit::keyPressEvent(QKeyEvent *event)
       
   353 {
       
   354     Q_D(HbAbstractEdit);
       
   355 
       
   356     if (d->interactionFlags & Qt::NoTextInteraction)
       
   357         return;
       
   358 
       
   359 #ifndef QT_NO_SHORTCUT
       
   360 #ifndef QT_NO_CLIPBOARD
       
   361     if (event == QKeySequence::Copy) {
       
   362         event->accept();
       
   363         copy();
       
   364         return;
       
   365     }
       
   366     else if (event == QKeySequence::Cut) {
       
   367         cut();
       
   368         d->acceptKeyPressEvent(event);
       
   369         return;
       
   370     }
       
   371     else if (event == QKeySequence::Paste) {
       
   372         paste();
       
   373         d->acceptKeyPressEvent(event);
       
   374         return;
       
   375     }
       
   376 #endif
       
   377 #endif // QT_NO_SHORTCUT
       
   378 
       
   379     if (d->interactionFlags & Qt::TextSelectableByKeyboard
       
   380         && d->cursorMoveKeyEvent(event))
       
   381         d->acceptKeyPressEvent(event);
       
   382 
       
   383     if (!(d->interactionFlags & Qt::TextEditable)) {
       
   384         d->repaintOldAndNewSelection(d->selectionCursor);
       
   385         d->cursorChanged(HbValidator::CursorChangeFromContentUpdate);
       
   386         //ensureCursorVisible();
       
   387         event->ignore();
       
   388         return;
       
   389     }
       
   390 
       
   391     if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
       
   392         QTextBlockFormat fmt;
       
   393         fmt.setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
       
   394         d->cursor.mergeBlockFormat(fmt);
       
   395         d->acceptKeyPressEvent(event);
       
   396     }
       
   397 
       
   398     // schedule a repaint of the region of the cursor, as when we move it we
       
   399     // want to make sure the old cursor disappears (not noticeable when moving
       
   400     // only a few pixels but noticeable when jumping between cells in tables for
       
   401     // example)
       
   402     d->repaintOldAndNewSelection(QTextCursor());
       
   403 
       
   404     if (event->key() == Qt::Key_Backspace && !(event->modifiers() & ~Qt::ShiftModifier)) {
       
   405         QTextBlockFormat blockFmt = d->cursor.blockFormat();
       
   406         QTextList *list = d->cursor.currentList();
       
   407         if (list && d->cursor.atBlockStart()) {
       
   408             list->remove(d->cursor.block());
       
   409         } else if (d->cursor.atBlockStart() && blockFmt.indent() > 0) {
       
   410             blockFmt.setIndent(blockFmt.indent() - 1);
       
   411             d->cursor.setBlockFormat(blockFmt);
       
   412         } else if (d->selectionCursor.hasSelection()) {
       
   413             d->selectionCursor.removeSelectedText();
       
   414         } else {
       
   415             QTextCursor oldCursor(d->cursor);
       
   416             oldCursor.deletePreviousChar();
       
   417         }
       
   418         d->ensureCursorVisible();
       
   419     }
       
   420 #ifndef QT_NO_SHORTCUT
       
   421       else if (event == QKeySequence::InsertParagraphSeparator) {
       
   422         d->cursor.insertBlock();
       
   423         d->acceptKeyPressEvent(event);
       
   424     } else if (event == QKeySequence::InsertLineSeparator) {
       
   425         d->cursor.insertText(QString(QChar::LineSeparator));
       
   426         d->acceptKeyPressEvent(event);
       
   427     }
       
   428 #endif
       
   429     if (false) {
       
   430     }
       
   431 #ifndef QT_NO_SHORTCUT
       
   432       else if (event == QKeySequence::Delete) {
       
   433         d->cursor.deleteChar();
       
   434         d->acceptKeyPressEvent(event);
       
   435     } else if (event == QKeySequence::DeleteEndOfWord) {
       
   436         d->cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
       
   437         d->cursor.removeSelectedText();
       
   438         d->acceptKeyPressEvent(event);
       
   439     } else if (event == QKeySequence::DeleteStartOfWord) {
       
   440         d->cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
       
   441         d->cursor.removeSelectedText();
       
   442         d->acceptKeyPressEvent(event);
       
   443     } else if (event == QKeySequence::DeleteEndOfLine) {
       
   444         QTextBlock block = d->cursor.block();
       
   445         if (d->cursor.position() == block.position() + block.length() - 2) {
       
   446             d->cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
       
   447         } else {
       
   448             d->cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
       
   449         }
       
   450         d->cursor.removeSelectedText();
       
   451         d->acceptKeyPressEvent(event);
       
   452     }
       
   453 #endif // QT_NO_SHORTCUT
       
   454     else {
       
   455 
       
   456     QString text = event->text();
       
   457     if (!text.isEmpty()
       
   458         && (text.at(0).isPrint()
       
   459         || text.at(0) == QLatin1Char('\t')
       
   460         || (d->scrollable
       
   461         && (text.at(0) == QLatin1Char('\n')
       
   462         || text.at(0) == QLatin1Char('\r'))))) {
       
   463             d->cursor.insertText(text, d->nextCharCursor.charFormat());
       
   464             d->acceptKeyPressEvent(event);
       
   465         }
       
   466     }
       
   467 
       
   468     d->cursorChanged(HbValidator::CursorChangeFromContentUpdate);
       
   469 }
       
   470 
       
   471 /*!
       
   472     \reimp
       
   473 */
       
   474 void HbAbstractEdit::keyReleaseEvent (QKeyEvent *event)
       
   475 {   
       
   476     event->accept();
       
   477 }
       
   478 
       
   479 /*!
       
   480     \reimp
       
   481 */
       
   482 void HbAbstractEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
       
   483 {
       
   484     Q_D(HbAbstractEdit);
       
   485 
       
   486     if (d->selectionControl) {
       
   487         d->selectionControl->panStarted();
       
   488     }
       
   489 
       
   490     if (d->interactionFlags & Qt::NoTextInteraction)
       
   491         return;
       
   492 
       
   493     if (!(event->button() & Qt::LeftButton))
       
   494         return;
       
   495 
       
   496     if (!((d->interactionFlags & Qt::TextSelectableByMouse) || (d->interactionFlags & Qt::TextEditable)))
       
   497         return;
       
   498 
       
   499     d->mousePressPos = event->pos();
       
   500     d->wasGesture = false;
       
   501 
       
   502     HbWidgetFeedback::triggered(this, Hb::InstantPressed);
       
   503 
       
   504 //    d->minimizeInputPanel();
       
   505 
       
   506     event->accept();
       
   507 }
       
   508 
       
   509 /*!
       
   510     \reimp
       
   511 */
       
   512 void HbAbstractEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
       
   513 {
       
   514     Q_UNUSED(event)
       
   515 }
       
   516 
       
   517 /*!
       
   518     \reimp
       
   519 */
       
   520 void HbAbstractEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   521 {
       
   522     Q_D(HbAbstractEdit);
       
   523 
       
   524     if (d->selectionControl) {
       
   525         d->selectionControl->panFinished();
       
   526     }
       
   527     if (d->wasGesture) return;
       
   528 
       
   529     if (d->interactionFlags & Qt::NoTextInteraction)
       
   530         return;
       
   531 
       
   532     if (d->mousePressPos != Hb_Invalid_Position) {
       
   533         d->mousePressPos = Hb_Invalid_Position;
       
   534 
       
   535         bool removeSelection = (d->hitTest(event->pos(), Qt::ExactHit) == -1);
       
   536 
       
   537         if (removeSelection && d->cursor.hasSelection()) {
       
   538             const QTextCursor oldCursor = d->cursor;
       
   539             d->cursor.clearSelection();
       
   540             d->repaintOldAndNewSelection(oldCursor);
       
   541             emit selectionChanged(oldCursor, d->cursor);
       
   542         }
       
   543 
       
   544         int newCursorPos = d->hitTest(event->pos(), Qt::FuzzyHit);
       
   545 
       
   546         if (d->cursor.hasSelection() &&
       
   547             newCursorPos >= d->cursor.selectionStart() &&
       
   548             newCursorPos <= d->cursor.selectionEnd()){
       
   549             // we have a selection under mouse click
       
   550             if (d->contextMenuShownOn.testFlag(Hb::ShowTextContextMenuOnSelectionClicked)) {
       
   551                 showContextMenu(mapToScene(event->pos()));
       
   552             }
       
   553         } else {
       
   554 
       
   555             // Currently focused widget to listen to InputContext before updating the cursor position
       
   556             d->sendMouseEventToInputContext(event);
       
   557             setCursorPosition(newCursorPos);
       
   558 
       
   559             HbWidgetFeedback::triggered(this, Hb::InstantReleased);
       
   560 
       
   561             if (d->interactionFlags & Qt::TextEditable) {
       
   562                 d->updateCurrentCharFormat();
       
   563             }
       
   564             d->cursorChanged(HbValidator::CursorChangeFromMouse);
       
   565         }
       
   566     }
       
   567 
       
   568     d->openInputPanel();
       
   569 
       
   570     event->accept();
       
   571 }
       
   572 
       
   573 
       
   574 /*!
       
   575     \reimp
       
   576 */
       
   577 void HbAbstractEdit::focusInEvent(QFocusEvent *event)
       
   578 {
       
   579     HbWidget::focusInEvent(event);
       
   580 
       
   581     Q_D(HbAbstractEdit);
       
   582 
       
   583     if (d->interactionFlags & Qt::NoTextInteraction)
       
   584         return;
       
   585 
       
   586     update(d->selectionRect());
       
   587 
       
   588     if (d->interactionFlags & Qt::TextEditable) {
       
   589         d->setBlinkingCursorEnabled(true);
       
   590     } else {
       
   591         d->cursorOn = (d->interactionFlags & Qt::TextSelectableByKeyboard);
       
   592     }
       
   593 
       
   594     d->openInputPanel();
       
   595 
       
   596     event->accept();
       
   597 }
       
   598 
       
   599 /*!
       
   600     \reimp
       
   601 */
       
   602 void HbAbstractEdit::focusOutEvent(QFocusEvent *event)
       
   603 {
       
   604     HbWidget::focusOutEvent(event);
       
   605 
       
   606     Q_D(HbAbstractEdit);
       
   607 
       
   608     if (d->interactionFlags & Qt::NoTextInteraction)
       
   609         return;
       
   610 
       
   611     d->setBlinkingCursorEnabled(false);
       
   612     d->repaintOldAndNewSelection(d->selectionCursor);
       
   613 
       
   614     event->accept();
       
   615 }
       
   616 
       
   617 /*!
       
   618     \reimp
       
   619 */
       
   620 void HbAbstractEdit::changeEvent (QEvent *event)
       
   621 {
       
   622     Q_D(HbAbstractEdit);
       
   623     HbWidget::changeEvent(event);
       
   624 
       
   625     switch (event->type()) {
       
   626         case QEvent::FontChange: {
       
   627             d->doc->setDefaultFont(font());
       
   628             updateGeometry();
       
   629             break;
       
   630         }
       
   631         case QEvent::LayoutDirectionChange: {
       
   632             QTextOption textOption = d->doc->defaultTextOption();
       
   633             textOption.setTextDirection(layoutDirection());
       
   634             d->doc->setDefaultTextOption(textOption);
       
   635             if (d->selectionControl) {
       
   636                 d->selectionControl->updatePrimitives();
       
   637             }
       
   638             break;
       
   639         }
       
   640         default: {
       
   641             if ( event->type() == HbEvent::ThemeChanged ) {
       
   642                 d->updatePaletteFromTheme();
       
   643                 updatePrimitives();
       
   644                 if (d->selectionControl) {
       
   645                     d->selectionControl->updatePrimitives();
       
   646                 }
       
   647             }
       
   648             break;
       
   649         }
       
   650     }
       
   651 }
       
   652 
       
   653 /*!
       
   654     \reimp
       
   655  */
       
   656 void HbAbstractEdit::hideEvent(QHideEvent *event)
       
   657 {
       
   658     HbWidget::hideEvent(event);
       
   659 
       
   660     deselect();
       
   661 
       
   662 #if QT_VERSION >= 0x040600
       
   663     // Send close input panel event.
       
   664     QInputContext *ic = qApp->inputContext();
       
   665     if (ic && !panel()) {
       
   666         QEvent *closeEvent = new QEvent(QEvent::CloseSoftwareInputPanel);
       
   667         ic->filterEvent(closeEvent);
       
   668         delete closeEvent;
       
   669     }
       
   670 #endif
       
   671 }
       
   672 
       
   673 
       
   674 
       
   675 /*!
       
   676     Returns the cursor position.
       
   677 
       
   678     Returned cursor position is a QTextDocucument index for the cursor
       
   679     visible on the screen.
       
   680 
       
   681     \sa setCursorPosition
       
   682  */
       
   683 int HbAbstractEdit::cursorPosition () const
       
   684 {
       
   685     Q_D(const HbAbstractEdit);
       
   686     return d->cursor.position();
       
   687 }
       
   688 
       
   689 /*!
       
   690     Sets the cursor postions to \a pos. If \a pos is greater than the length of the content
       
   691     the cursor is set to the end of the text.
       
   692 
       
   693     Additionally it is possible to create selection using \a mode QTextCursor::KeepAnchor.
       
   694 
       
   695     \sa cursorPosition
       
   696  */
       
   697 void HbAbstractEdit::setCursorPosition (int pos, QTextCursor::MoveMode mode)
       
   698 {
       
   699     Q_D(HbAbstractEdit);
       
   700     if (d->cursor.position() != pos) {
       
   701         d->setCursorPosition(pos, mode);
       
   702     }
       
   703 }
       
   704 
       
   705 /*!
       
   706     Returns the cursor visibility mode.
       
   707 
       
   708     \sa setCursorVisibility
       
   709  */
       
   710 Hb::TextCursorVisibility HbAbstractEdit::cursorVisibility () const
       
   711 {
       
   712     Q_D(const HbAbstractEdit);
       
   713     return d->isCursorVisible() ? Hb::TextCursorVisible : Hb::TextCursorHidden;
       
   714 }
       
   715 
       
   716 /*!
       
   717     Sets the cursor visibility mode to given \a value.
       
   718 
       
   719     In a hidden mode the cursor is always at the end of the inputted content.
       
   720     User can't change the position of the cursor, or select the content.
       
   721 
       
   722     \sa cursorVisibility
       
   723  */
       
   724 void HbAbstractEdit::setCursorVisibility (Hb::TextCursorVisibility value)
       
   725 {
       
   726     Q_D(HbAbstractEdit);
       
   727     bool b = (value == Hb::TextCursorVisible);
       
   728     if (d->apiCursorVisible != b) {
       
   729         d->apiCursorVisible = b;
       
   730         d->repaintOldAndNewSelection(QTextCursor());
       
   731     }
       
   732 }
       
   733 
       
   734 /*!
       
   735     Returns true if edit is in read-only mode; otherwise return false.
       
   736 
       
   737     \sa setReadOnly
       
   738  */
       
   739 bool HbAbstractEdit::isReadOnly () const
       
   740 {
       
   741     Q_D(const HbAbstractEdit);
       
   742 
       
   743     return !(d->interactionFlags & Qt::TextEditable);
       
   744 }
       
   745 
       
   746 /*!
       
   747     Sets edit's read-only mode to given \a value. In a read-only text edit the user
       
   748     can only navigate through the text and select text; modifying the text
       
   749     is not possible.
       
   750 
       
   751     In read-only mode text can be set using setPlainText() or setHtml().
       
   752 
       
   753     \sa isReadOnly
       
   754  */
       
   755 void HbAbstractEdit::setReadOnly (bool value)
       
   756 {
       
   757     Q_D(HbAbstractEdit);
       
   758     Qt::TextInteractionFlags f = d->interactionFlags;
       
   759 
       
   760     if (f.testFlag(Qt::TextEditable) != value) {
       
   761         return;
       
   762     }
       
   763 
       
   764     f ^= Qt::TextEditable;
       
   765 
       
   766     d->setTextInteractionFlags(f);
       
   767 
       
   768     setFlag(QGraphicsItem::ItemAcceptsInputMethod, !value);
       
   769 }
       
   770 
       
   771 /*!
       
   772     Returns pointer to a \a primitive of HbAbstractEdit.
       
   773 
       
   774     Available primitive is HbStyle::P_Edit_text.
       
   775 
       
   776     \reimp
       
   777     \sa HbStyle::Primitive, HbWidget::primitive()
       
   778 */
       
   779 QGraphicsItem *HbAbstractEdit::primitive (HbStyle::Primitive primitive) const
       
   780 {
       
   781     Q_D(const HbAbstractEdit);
       
   782 
       
   783     if (primitive == HbStyle::P_Edit_text) {
       
   784         return d->scrollArea;
       
   785     } else {
       
   786         return HbWidget::primitive(primitive);
       
   787     }
       
   788 }
       
   789 
       
   790 /*!
       
   791     \reimp
       
   792 */
       
   793 void HbAbstractEdit::updatePrimitives()
       
   794 {
       
   795     Q_D(HbAbstractEdit);
       
   796     HbWidget::updatePrimitives();
       
   797 
       
   798     if (d->scrollArea) {
       
   799         d->doc->setTextWidth(d->scrollArea->size().width());
       
   800     }
       
   801     QRectF canvasGeom(QRectF(QPointF(0,0),d->doc->size()));
       
   802     if(d->scrollArea && canvasGeom.height()<d->scrollArea->size().height()) {
       
   803         canvasGeom.setHeight(d->scrollArea->size().height());
       
   804     }
       
   805     d->canvas->setGeometry(canvasGeom);
       
   806     if (d->scrollArea) {
       
   807         d->scrollArea->updateScrollMetrics();
       
   808     }
       
   809     d->ensureCursorVisible();
       
   810 }
       
   811 
       
   812 /*!
       
   813     Replaces editor content with \a text.
       
   814 
       
   815     HbAbstractEdit does not support richtext from cut, copy & paste
       
   816     operations after setPlainText() has been called.
       
   817 
       
   818     If smiley recognition is enabled the textual smiley patterns are replaced
       
   819     with the corresponding image from the active smiley theme.
       
   820 
       
   821     \sa setSmileysEnabled()
       
   822 */
       
   823 void HbAbstractEdit::setPlainText(const QString &text)
       
   824 {
       
   825     Q_D(HbAbstractEdit);
       
   826     d->setContent(Qt::PlainText, text);
       
   827 }
       
   828 
       
   829 /*!
       
   830     Replaces editor content with HTML-formatted string \a text.
       
   831 
       
   832     If smiley recognition is enabled the textual smiley patterns are replaced
       
   833     with the corresponding image from the active smiley theme.
       
   834 
       
   835     \sa setSmileysEnabled()
       
   836 
       
   837     \note It is the responsibility of the caller to make sure that the text
       
   838     is correctly decoded when a QString containing HTML is created and passed to setHtml().
       
   839 */
       
   840 void HbAbstractEdit::setHtml(const QString &text)
       
   841 {
       
   842     Q_D(HbAbstractEdit);
       
   843     d->setContent(Qt::RichText, text);
       
   844 }
       
   845 
       
   846 /*!
       
   847      \internal
       
   848      This is the cursor blinking timer.
       
   849      \reimp
       
   850  */
       
   851 void HbAbstractEdit::timerEvent(QTimerEvent *e)
       
   852 {
       
   853     Q_D(HbAbstractEdit);
       
   854 
       
   855     if (e->timerId() == d->cursorBlinkTimer.timerId()) {
       
   856         d->cursorOn = !d->cursorOn;
       
   857 
       
   858         if (d->cursor.hasSelection())
       
   859             d->cursorOn &= (QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) != 0);
       
   860 
       
   861         d->repaintCursor();
       
   862     }
       
   863 }
       
   864 
       
   865 /*!
       
   866     This is a slot for listening a signal with a same name from QTextDocument.
       
   867     When creating custom editor this slot can be overridden but this base implementation
       
   868     should be called.
       
   869 
       
   870     \sa QTextDocument::documentLayoutChanged()
       
   871 */
       
   872 void HbAbstractEdit::documentLayoutChanged()
       
   873 {
       
   874     Q_D(HbAbstractEdit);
       
   875 
       
   876     QAbstractTextDocumentLayout *layout = d->doc->documentLayout();
       
   877     QObject::connect(layout, SIGNAL(update(QRectF)), this, SLOT(_q_updateRequest(QRectF)));
       
   878     QObject::connect(layout, SIGNAL(updateBlock(QTextBlock)), this, SLOT(_q_updateBlock(QTextBlock)));
       
   879     QObject::connect(layout, SIGNAL(documentSizeChanged(QSizeF)), this, SLOT(documentSizeChanged(QSizeF)));
       
   880 
       
   881     updatePrimitives();
       
   882 }
       
   883 
       
   884 /*!
       
   885     This is a slot for listening a signal with a same name from QTextDocument.
       
   886     When creating custom editor this slot can be overridden but this base implementation
       
   887     should be called.
       
   888 
       
   889     \sa QTextDocument::documentSizeChanged(QSizeF size)
       
   890 */
       
   891 void HbAbstractEdit::documentSizeChanged(const QSizeF &size)
       
   892 {
       
   893     Q_UNUSED(size)
       
   894     updateGeometry();
       
   895     updatePrimitives();
       
   896 }
       
   897 
       
   898 /*!
       
   899     Replaces the QTextDocument that is inside the editor.
       
   900 */
       
   901 void HbAbstractEdit::setDocument(QTextDocument *document)
       
   902 {
       
   903     Q_D(HbAbstractEdit);
       
   904     if (d->doc == document)
       
   905         return;
       
   906     d->removeCurrentDocument();
       
   907     d->connectToNewDocument(document);
       
   908 }
       
   909 
       
   910 /*!
       
   911     Returns the QTextDocument currently in use.
       
   912 */
       
   913 QTextDocument *HbAbstractEdit::document() const
       
   914 {
       
   915     Q_D(const HbAbstractEdit);
       
   916     return d->doc;
       
   917 }
       
   918 
       
   919 /*!
       
   920     Replaces the QTextCursor that is currently in use.
       
   921     \sa textCursor
       
   922 */
       
   923 void HbAbstractEdit::setTextCursor(const QTextCursor &cursor)
       
   924 {
       
   925     Q_D(HbAbstractEdit);
       
   926 
       
   927     // QTextCursor operator!= compares only position
       
   928     if (    cursor.position() != d->cursor.position()
       
   929         ||  cursor.anchor() != d->cursor.anchor() ) {
       
   930         const QTextCursor oldCursor = d->cursor;
       
   931         d->cursor = cursor;
       
   932 
       
   933         d->updateCurrentCharFormat();
       
   934 
       
   935         d->ensureCursorVisible();
       
   936         d->repaintOldAndNewSelection(oldCursor);
       
   937         d->cursorChanged(HbValidator::CursorChangeFromContentSet);
       
   938     }
       
   939 }
       
   940 
       
   941 /*!
       
   942     Returns the QTextCursor currently in use.
       
   943     \sa setTextCursor
       
   944  */
       
   945 QTextCursor HbAbstractEdit::textCursor() const
       
   946 {
       
   947     Q_D(const HbAbstractEdit);
       
   948     return d->cursor;
       
   949 }
       
   950 
       
   951 /*!
       
   952     Adds content which is currently selected in editor to clipboard and
       
   953     deletes the content from editor.
       
   954 
       
   955     When clipboad is not available this method does nothing.
       
   956 
       
   957     \sa copy paste
       
   958  */
       
   959 void HbAbstractEdit::cut()
       
   960 {
       
   961 #ifndef QT_NO_CLIPBOARD
       
   962     Q_D(HbAbstractEdit);
       
   963     if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection())
       
   964         return;
       
   965     copy();
       
   966     d->cursor.removeSelectedText();
       
   967 #endif//QT_NO_CLIPBOARD
       
   968 }
       
   969 
       
   970 /*!
       
   971     Adds content which is currently selected in editor to clipboard.
       
   972 
       
   973     When clipboad is not available this method does nothing.
       
   974 
       
   975     \sa cut paste
       
   976  */
       
   977 void HbAbstractEdit::copy()
       
   978 {
       
   979 #ifndef QT_NO_CLIPBOARD
       
   980     Q_D(HbAbstractEdit);
       
   981     if (!d->cursor.hasSelection() || !d->canCopy())
       
   982         return;
       
   983     QMimeData *data = createMimeDataFromSelection();
       
   984     QApplication::clipboard()->setMimeData(data);
       
   985 #endif//QT_NO_CLIPBOARD
       
   986 }
       
   987 
       
   988 /*!
       
   989     Inserts the content from clipboard to current cursor position in editor.
       
   990     If there is a selection, the selection is replaced with the pasted content.
       
   991 
       
   992     When clipboad is not available this method does nothing.
       
   993 
       
   994     \sa cut copy
       
   995  */
       
   996 void HbAbstractEdit::paste()
       
   997 {
       
   998 #ifndef QT_NO_CLIPBOARD
       
   999     Q_D(HbAbstractEdit);
       
  1000     if (d->canPaste()) {
       
  1001         d->prepDocForPaste();
       
  1002         const QMimeData *md = QApplication::clipboard()->mimeData();
       
  1003         if (md) {
       
  1004             insertFromMimeData(md);
       
  1005         }
       
  1006     }
       
  1007 
       
  1008 #endif//QT_NO_CLIPBOARD
       
  1009 }
       
  1010 
       
  1011 /*!
       
  1012     Selects the word under the cursor in the editor.
       
  1013     Word selection rules comes from QTextCursor::WordUnderCursor.
       
  1014     \sa selectAll deselect
       
  1015 */
       
  1016 void HbAbstractEdit::selectClickedWord()
       
  1017 {
       
  1018     Q_D(HbAbstractEdit);
       
  1019 
       
  1020     int cursorPos = d->hitTest(d->mousePressPos, Qt::FuzzyHit);
       
  1021 
       
  1022     if (cursorPos == -1)
       
  1023         return;
       
  1024 
       
  1025     setCursorPosition(cursorPos);
       
  1026     const QTextCursor oldSelection = d->cursor;
       
  1027     d->cursor.select(QTextCursor::WordUnderCursor);
       
  1028     emit selectionChanged(oldSelection, d->cursor);
       
  1029     d->repaintOldAndNewSelection(oldSelection);
       
  1030     d->cursorChanged(HbValidator::CursorChangeFromMouse);
       
  1031     //TODO: focus is in VKB so needs to re-focus to editor
       
  1032 //    setFocus();
       
  1033 }
       
  1034 
       
  1035 /*!
       
  1036     Selects all the text in the editor.
       
  1037     \sa selectClickedWord deselect
       
  1038  */
       
  1039 void HbAbstractEdit::selectAll()
       
  1040 {
       
  1041     Q_D(HbAbstractEdit);
       
  1042     const QTextCursor oldSelection = d->cursor;
       
  1043     d->cursor.select(QTextCursor::Document);
       
  1044     emit selectionChanged(oldSelection, d->cursor);
       
  1045     d->repaintOldAndNewSelection(oldSelection);
       
  1046     d->cursorChanged(HbValidator::CursorChangeFromMouse);
       
  1047 }
       
  1048 
       
  1049 /*!
       
  1050     Deselects the text in the editor if there is text selected.
       
  1051     \sa selectClickedWord selectAll
       
  1052  */
       
  1053 void HbAbstractEdit::deselect()
       
  1054 {
       
  1055     Q_D(HbAbstractEdit);
       
  1056     const QTextCursor oldSelection = d->cursor;
       
  1057     d->cursor.clearSelection();
       
  1058     emit selectionChanged(oldSelection, d->cursor);
       
  1059 }
       
  1060 
       
  1061 /*!
       
  1062     Launches the format user interface.
       
  1063  */
       
  1064 void HbAbstractEdit::format()
       
  1065 {
       
  1066     Q_D(HbAbstractEdit);
       
  1067     if (d->formatDialog) {
       
  1068         d->formatDialog->launch(this);
       
  1069     }
       
  1070 }
       
  1071 
       
  1072 /*!
       
  1073     This function returns a new MIME data object to represent the
       
  1074     contents of the text edit's current selection.
       
  1075 
       
  1076     It is called when the selection needs to be encapsulated into a new
       
  1077     QMimeData object; for example when data is copyied to the clipboard.
       
  1078 
       
  1079     Ownership of QMimeData is passed to caller.
       
  1080 */
       
  1081 QMimeData *HbAbstractEdit::createMimeDataFromSelection() const
       
  1082 {
       
  1083     Q_D(const HbAbstractEdit);
       
  1084     const QTextDocumentFragment fragment(d->cursor);
       
  1085     return new HbAbstractEditMimeData(fragment);
       
  1086 }
       
  1087 
       
  1088 /*!
       
  1089     This function returns true if the contents of the MIME data object,
       
  1090     specified by source, can be decoded and inserted into the document.
       
  1091  */
       
  1092 bool HbAbstractEdit::canInsertFromMimeData(const QMimeData *source) const
       
  1093 {
       
  1094     return (source->hasText() && !source->text().isEmpty())
       
  1095         || source->hasHtml()
       
  1096         || source->hasFormat(QLatin1String("application/x-qrichtext"))
       
  1097         || source->hasFormat(QLatin1String("application/x-qt-richtext"));
       
  1098 }
       
  1099 
       
  1100 /*!
       
  1101     This function inserts the contents of the MIME data object,
       
  1102     specified by \a source, into the text edit at the current cursor
       
  1103     position.
       
  1104 
       
  1105     It is called for example when text is inserted as the result
       
  1106     of a clipboard paste operation.
       
  1107  */
       
  1108 void HbAbstractEdit::insertFromMimeData(const QMimeData *source)
       
  1109 {
       
  1110     Q_D(HbAbstractEdit);
       
  1111     if (!(d->interactionFlags & Qt::TextEditable) || !source)
       
  1112         return;
       
  1113 
       
  1114     bool hasData = false;
       
  1115     QTextDocumentFragment fragment;
       
  1116 #ifndef QT_NO_TEXTHTMLPARSER
       
  1117     if (source->hasFormat(QLatin1String("application/x-qrichtext"))) {
       
  1118         QString richtext = QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext")));
       
  1119         richtext.prepend(QLatin1String("<meta name=\"qrichtext\" content=\"1\" />"));
       
  1120         fragment = QTextDocumentFragment::fromHtml(richtext, d->doc);
       
  1121         hasData = true;
       
  1122     } else if (source->hasHtml()) {
       
  1123         fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc);
       
  1124         hasData = true;
       
  1125     } else
       
  1126 #endif //QT_NO_TEXTHTMLPARSER
       
  1127     {
       
  1128         QString text = source->text();
       
  1129         if (!text.isNull()) {
       
  1130             fragment = QTextDocumentFragment::fromPlainText(text);
       
  1131             hasData = true;
       
  1132         }
       
  1133     }
       
  1134 
       
  1135     if (hasData) {
       
  1136         d->cursor.insertFragment(fragment);
       
  1137     }
       
  1138     d->ensureCursorVisible();
       
  1139 }
       
  1140 
       
  1141 /*!
       
  1142     Returns the calculated rect in item coordinates of the editor for the the given \a position inside a document.
       
  1143  */
       
  1144 QRectF HbAbstractEdit::rectForPosition(int position, QTextLine::Edge edge) const
       
  1145 {
       
  1146     Q_D(const HbAbstractEdit);
       
  1147 
       
  1148     QRectF rect  = d->rectForPositionInCanvasCoords(position, edge);
       
  1149     rect = mapRectFromItem(d->canvas,rect);
       
  1150     return rect;
       
  1151 }
       
  1152 
       
  1153 /*!
       
  1154     Returns the contents as plain text. If smiley recognition is enabled
       
  1155     all the smiley images will be replaced by their textual representations.
       
  1156 
       
  1157     \sa QTextDocument::toPlainText() setSmileysEnabled()
       
  1158 */
       
  1159 QString HbAbstractEdit::toPlainText() const
       
  1160 {
       
  1161     Q_D(const HbAbstractEdit);
       
  1162     QString retVal;
       
  1163     if(isSmileysEnabled()) {
       
  1164         retVal = d->smileyEngineInstance()->toPlainText();
       
  1165     } else {
       
  1166         retVal = d->doc->toPlainText();
       
  1167     }
       
  1168     return retVal;
       
  1169 }
       
  1170 
       
  1171 /*!
       
  1172     Returns the contents as HTML formatted string. If smiley recognition is enabled
       
  1173     all the smiley images will be replaced by their textual representations.
       
  1174 
       
  1175     \sa QTextDocument::toHtml() setSmileysEnabled()
       
  1176 */
       
  1177 QString HbAbstractEdit::toHtml() const
       
  1178 {
       
  1179     Q_D(const HbAbstractEdit);
       
  1180     QString retVal;
       
  1181     if(isSmileysEnabled()) {
       
  1182         retVal = d->smileyEngineInstance()->toHtml();
       
  1183     } else {
       
  1184         retVal = d->doc->toHtml();
       
  1185     }
       
  1186     return retVal;
       
  1187 }
       
  1188 
       
  1189 /*!
       
  1190     Validator is used to validate the content and cursor movements.
       
  1191 
       
  1192     \note Validator uses undo stack to back out invalid changes. Therefore undo
       
  1193     is enabled when validator is set.
       
  1194  */
       
  1195 void HbAbstractEdit::setValidator(HbValidator* validator)
       
  1196 {
       
  1197     Q_D(HbAbstractEdit);
       
  1198 
       
  1199     if(d->validator) {
       
  1200         delete d->validator;
       
  1201         d->validator = 0;
       
  1202     }
       
  1203 
       
  1204     if(validator) {
       
  1205         d->validator = validator;
       
  1206         d->initValidator();
       
  1207     }
       
  1208 }
       
  1209 
       
  1210 /*!
       
  1211     \property QLineEdit::acceptableInput
       
  1212     This property holds whether the input satisfies the validator.
       
  1213 
       
  1214     By default, this property is true.
       
  1215 
       
  1216     \sa setValidator()
       
  1217 */
       
  1218 bool HbAbstractEdit::hasAcceptableInput() const
       
  1219 {
       
  1220     Q_D(const HbAbstractEdit);
       
  1221     return d->hasAcceptableInput();
       
  1222 }
       
  1223 
       
  1224 /*!
       
  1225     Convenience method to manipulate cursor position.
       
  1226     \sa QTextCursor::movePosition()
       
  1227  */
       
  1228 void HbAbstractEdit::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
       
  1229 {
       
  1230     Q_D(HbAbstractEdit);
       
  1231     //const QTextCursor oldCursor = d->cursor;
       
  1232     d->cursor.movePosition(op, mode);
       
  1233 
       
  1234     d->updateCurrentCharFormat();
       
  1235 
       
  1236     d->ensureCursorVisible();
       
  1237     QTextCursor previousCursor(d->cursor);
       
  1238     previousCursor.setPosition(d->previousCursorAnchor);
       
  1239     previousCursor.setPosition(d->previousCursorPosition, QTextCursor::KeepAnchor);
       
  1240     d->repaintOldAndNewSelection(previousCursor);
       
  1241     d->cursorChanged(HbValidator::CursorChangeFromOperation);
       
  1242 }
       
  1243 
       
  1244 /*!
       
  1245     Returns the bounding rect for given text block.
       
  1246 
       
  1247     \sa QAbstractTextDocumentLayout::blockBoundingRect(const QTextBlock& block)
       
  1248  */
       
  1249 QRectF HbAbstractEdit::blockBoundingRect(const QTextBlock &block) const
       
  1250 {
       
  1251     Q_D(const HbAbstractEdit);
       
  1252     return d->doc->documentLayout()->blockBoundingRect(block);
       
  1253 }
       
  1254 
       
  1255 /*!
       
  1256     This is a slot for listening a signal with a same name from QTextDocument.
       
  1257     When creating custom editor this slot can be overridden but this base implementation
       
  1258     should be called.
       
  1259 
       
  1260     \sa QTextDocument::blockCountChanged(int newBlockCount)
       
  1261 */
       
  1262 void HbAbstractEdit::blockCountChanged(int newBlockCount)
       
  1263 {
       
  1264     Q_UNUSED(newBlockCount);
       
  1265 
       
  1266     updatePrimitives();
       
  1267 }
       
  1268 
       
  1269 /*!
       
  1270     Returns true if the content is scrollable.
       
  1271  */
       
  1272 bool HbAbstractEdit::isScrollable() const
       
  1273 {
       
  1274     Q_D(const HbAbstractEdit);
       
  1275 
       
  1276     return d->scrollable;
       
  1277 }
       
  1278 
       
  1279 /*!
       
  1280     Sets the editor as scrollable if \a value is true; othetwise edit is set as non-scrollable.
       
  1281 */
       
  1282 void HbAbstractEdit::setScrollable(bool value)
       
  1283 {
       
  1284     Q_D(HbAbstractEdit);
       
  1285     if (value != d->scrollable) {
       
  1286         d->scrollable = value;
       
  1287 //            d->scrollArea->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
       
  1288     }
       
  1289 }
       
  1290 
       
  1291 /*!
       
  1292     Content of the editor can be drawn to some outside widget by supplying \a painter and \a option.
       
  1293     This is used be the HbStyle system.
       
  1294  */
       
  1295 void HbAbstractEdit::drawContents(QPainter *painter, const QStyleOptionGraphicsItem &option)
       
  1296 {
       
  1297     Q_D(HbAbstractEdit);
       
  1298 #ifdef HB_DEBUG_EDITOR_DRAW_RECTS
       
  1299     painter->setPen(Qt::green);
       
  1300     /*for(QTextBlock tb = d->doc->begin(); tb.isValid(); tb=tb.next()) {
       
  1301         painter->drawRect(blockBoundingRect(tb));
       
  1302     }*/
       
  1303     painter->drawRect(d->doc->documentLayout()->frameBoundingRect(
       
  1304         d->doc->rootFrame()).adjusted(2,2,-2,-2));
       
  1305     painter->setOpacity(0.3);
       
  1306     painter->setPen(Qt::blue);
       
  1307     painter->drawRect(d->cursorRect());
       
  1308     painter->setOpacity(1.0);
       
  1309 #endif
       
  1310 
       
  1311     QAbstractTextDocumentLayout::PaintContext ctx = d->getPaintContext();
       
  1312     if (option.exposedRect.isValid())
       
  1313         painter->setClipRect(option.exposedRect, Qt::IntersectClip);
       
  1314     ctx.clip = option.exposedRect;
       
  1315 
       
  1316     d->drawContentBackground(painter, option);
       
  1317     document()->documentLayout()->draw(painter, ctx);
       
  1318     // Draw the pins for the selection handle
       
  1319     d->drawSelectionEdges(painter, ctx);
       
  1320 
       
  1321 #ifdef HB_DEBUG_EDITOR_HANDLES
       
  1322     QRectF a = rectForPosition(d->cursor.anchor());
       
  1323     QRectF c = rectForPosition(d->cursor.position());
       
  1324 
       
  1325     painter->setPen(Qt::blue);
       
  1326     painter->drawRect(a);
       
  1327     painter->setPen(Qt::green);
       
  1328     painter->drawRect(c);
       
  1329     painter->setPen(Qt::red);
       
  1330     painter->drawRect(d->cursorRect());
       
  1331 #endif
       
  1332 }
       
  1333 
       
  1334 /*!
       
  1335     Returns the used scroll area if edit is set as scrollable;
       
  1336     otherwise returns null pointer.
       
  1337 */
       
  1338 HbScrollArea *HbAbstractEdit::scrollArea() const
       
  1339 {
       
  1340     Q_D(const HbAbstractEdit);
       
  1341     return d->scrollArea;
       
  1342 }
       
  1343 
       
  1344 /*!
       
  1345     Creates a context menu. Default implementation returns 0.
       
  1346 */
       
  1347 HbMenu* HbAbstractEdit::createContextMenu()
       
  1348 {
       
  1349     return 0;
       
  1350 }
       
  1351 
       
  1352 /*!
       
  1353     Shows context menu at given \a position. Inheriting class can implement its own context menu instance using createContextMenu function. 
       
  1354 
       
  1355     These actions are added to the context menu when appropriate: cut, copy, paste, select, select all, deselect, format.
       
  1356 
       
  1357     \sa createContextMenu
       
  1358 */
       
  1359 void HbAbstractEdit::showContextMenu(QPointF position)
       
  1360 {
       
  1361     Q_D(HbAbstractEdit);
       
  1362     HbMenu *menu = createContextMenu();
       
  1363 
       
  1364     if (!menu) {
       
  1365         menu = new HbMenu();
       
  1366     }
       
  1367 
       
  1368     menu->setAttribute(Hb::InputMethodNeutral);
       
  1369 
       
  1370     if (d->cursor.hasSelection() && d->canCopy()) {
       
  1371         connect(
       
  1372             menu->addAction("Cut"), SIGNAL(triggered()),
       
  1373             this, SLOT(cut()));
       
  1374         connect(
       
  1375             menu->addAction("Copy"), SIGNAL(triggered()),
       
  1376             this, SLOT(copy()));
       
  1377     }
       
  1378     else if (!d->doc->isEmpty() && d->canCopy()){
       
  1379         connect(
       
  1380             menu->addAction("Select"), SIGNAL(triggered()),
       
  1381             this, SLOT(selectClickedWord()));
       
  1382         connect(
       
  1383             menu->addAction("Select all"), SIGNAL(triggered()),
       
  1384             this, SLOT(selectAll()));
       
  1385     }
       
  1386     if (d->canPaste()) {
       
  1387         connect(
       
  1388             menu->addAction("Paste"), SIGNAL(triggered()), 
       
  1389             this, SLOT(paste()));
       
  1390     }
       
  1391     if (d->cursor.hasSelection()) {
       
  1392         connect(
       
  1393             menu->addAction("Deselect"), SIGNAL(triggered()), 
       
  1394             this, SLOT(deselect()));
       
  1395     }
       
  1396     if (d->canFormat()) {
       
  1397         connect(
       
  1398             menu->addAction("Format"), SIGNAL(triggered()), 
       
  1399             this, SLOT(format()));
       
  1400     }
       
  1401 
       
  1402     emit aboutToShowContextMenu(menu, d->mousePressPos);
       
  1403 
       
  1404     d->minimizeInputPanel();
       
  1405 
       
  1406     if(menu->actions().count() > 0){
       
  1407         menu->setPreferredPos(position);
       
  1408         menu->show();
       
  1409     }
       
  1410 }
       
  1411 
       
  1412 /*!
       
  1413     Returns the validator currently in use.
       
  1414 
       
  1415     \sa setValidator HbValidator
       
  1416 */
       
  1417 HbValidator *HbAbstractEdit::validator() const
       
  1418 {
       
  1419     Q_D(const HbAbstractEdit);
       
  1420     return d->validator;
       
  1421 }
       
  1422 
       
  1423 /*!
       
  1424     \reimp
       
  1425 */
       
  1426 int HbAbstractEdit::type() const
       
  1427 {
       
  1428     return Type;
       
  1429 }
       
  1430 
       
  1431 /*!
       
  1432     \reimp
       
  1433 */
       
  1434 void HbAbstractEdit::updateGeometry()
       
  1435 {
       
  1436     Q_D(HbAbstractEdit);
       
  1437     d->updateEditingSize();
       
  1438     HbWidget::updateGeometry();
       
  1439 }
       
  1440 /*!
       
  1441     Sets text alignment to \a alignment to the current text cursor.
       
  1442 
       
  1443     \sa alignment textCursor setTextCursor
       
  1444 */
       
  1445 void HbAbstractEdit::setAlignment(Qt::Alignment alignment)
       
  1446 {
       
  1447     Q_D(HbAbstractEdit);
       
  1448     d->acceptSignalContentsChanged = false; // no text content changes.
       
  1449     QTextBlockFormat fmt;
       
  1450     fmt.setAlignment(alignment);
       
  1451     QTextCursor cursor = d->cursor;
       
  1452     cursor.mergeBlockFormat(fmt);
       
  1453     d->acceptSignalContentsChanged = true;
       
  1454     setTextCursor(cursor);
       
  1455     d->mApiProtectionFlags |= HbWidgetBasePrivate::AC_TextAlign;
       
  1456 }
       
  1457 
       
  1458 /*!
       
  1459     Returns text alignment at the current text cursor.
       
  1460 
       
  1461     \sa setAlignment()
       
  1462 */
       
  1463 Qt::Alignment HbAbstractEdit::alignment() const
       
  1464 {
       
  1465     Q_D(const HbAbstractEdit);
       
  1466     return d->cursor.blockFormat().alignment();
       
  1467 
       
  1468 }
       
  1469 
       
  1470 /*!
       
  1471     Returns current flags describing on which events context menu is shown
       
  1472 
       
  1473     \sa Hb::TextContextMenuFlag
       
  1474  */
       
  1475 Hb::TextContextMenuFlags HbAbstractEdit::contextMenuFlags() const
       
  1476 {
       
  1477     Q_D(const HbAbstractEdit);
       
  1478 
       
  1479     return d->contextMenuShownOn;
       
  1480 }
       
  1481 
       
  1482 /*!
       
  1483     Sets \a flags describing on which events context menu is shown
       
  1484     \sa Hb::TextContextMenuFlag
       
  1485  */
       
  1486 void HbAbstractEdit::setContextMenuFlags(Hb::TextContextMenuFlags flags)
       
  1487 {
       
  1488     Q_D(HbAbstractEdit);
       
  1489     d->contextMenuShownOn = flags;
       
  1490 }
       
  1491 
       
  1492 /*!
       
  1493     Sets single \a flag on which event context menu is shown
       
  1494     (other flags remain unchanged)
       
  1495     \sa Hb::TextContextMenuFlag
       
  1496  */
       
  1497 void HbAbstractEdit::setContextMenuFlag(Hb::TextContextMenuFlag flag)
       
  1498 {
       
  1499     Q_D(HbAbstractEdit);
       
  1500     d->contextMenuShownOn|=flag;
       
  1501 }
       
  1502 
       
  1503 /*!
       
  1504     Clears single \a flag on which event context menu is shown
       
  1505     (other flags remain unchanged)
       
  1506     \sa Hb::TextContextMenuFlag
       
  1507  */
       
  1508 void HbAbstractEdit::clearContextMenuFlag(Hb::TextContextMenuFlag flag)
       
  1509 {
       
  1510     Q_D(HbAbstractEdit);
       
  1511     d->contextMenuShownOn&=~flag;
       
  1512 }
       
  1513 
       
  1514 /*!
       
  1515     Returns the reference of the anchor at the given position,
       
  1516     or an empty string if no anchor exists at that point.
       
  1517  */
       
  1518 QString HbAbstractEdit::anchorAt(const QPointF &pos) const
       
  1519 {
       
  1520     Q_D(const HbAbstractEdit);
       
  1521     return d->doc->documentLayout()->anchorAt(pos);
       
  1522 }
       
  1523 
       
  1524 /*!
       
  1525     Returns the reference of the anchor the given cursor position,
       
  1526     or an empty string if no anchor exists at that position.
       
  1527  */
       
  1528 QString HbAbstractEdit::anchorAt(int pos) const
       
  1529 {
       
  1530     Q_D(const HbAbstractEdit);
       
  1531     QTextCursor newCursor = QTextCursor(d->doc);
       
  1532     newCursor.setPosition(pos);
       
  1533     newCursor.movePosition(QTextCursor::NextCharacter);
       
  1534     return newCursor.charFormat().anchorHref();
       
  1535 }
       
  1536 
       
  1537 /*!
       
  1538     Sets the smiley theme to be used with the editor.
       
  1539     \sa HbSmileyTheme smileyTheme()
       
  1540  */
       
  1541 void HbAbstractEdit::setSmileyTheme(const HbSmileyTheme& theme)
       
  1542 {
       
  1543     Q_D(HbAbstractEdit);
       
  1544     d->smileyEngineInstance()->setTheme(theme);
       
  1545 
       
  1546     HbEditorInterface editorInterface(this);
       
  1547     editorInterface.setSmileyTheme(theme);
       
  1548 }
       
  1549 
       
  1550 
       
  1551 /*!
       
  1552     Returns the smiley theme which is used by the editor.
       
  1553     \sa HbSmileyTheme setSmileyTheme()
       
  1554  */
       
  1555 HbSmileyTheme HbAbstractEdit::smileyTheme() const
       
  1556 {
       
  1557     Q_D(const HbAbstractEdit);
       
  1558     return d->smileyEngineInstance()->theme();
       
  1559 }
       
  1560 
       
  1561 /*!
       
  1562     Returns the default smiley theme.
       
  1563     \sa HbSmileyTheme resetSmileyTheme()
       
  1564  */
       
  1565 HbSmileyTheme HbAbstractEdit::defaultSmileyTheme() const
       
  1566 {
       
  1567     Q_D(const HbAbstractEdit);
       
  1568     return d->smileyEngineInstance()->defaultTheme();
       
  1569 }
       
  1570 
       
  1571 /*!
       
  1572     Convenience method to reset the smiley theme to the default.
       
  1573     \sa HbSmileyTheme defaultSmileyTheme()
       
  1574  */
       
  1575 void HbAbstractEdit::resetSmileyTheme()
       
  1576 {
       
  1577     HbSmileyTheme theme = defaultSmileyTheme();
       
  1578     setSmileyTheme(theme);
       
  1579     HbEditorInterface editorInterface(this);
       
  1580     editorInterface.setSmileyTheme(theme);
       
  1581 
       
  1582 }
       
  1583 
       
  1584 /*!
       
  1585     Activates or deactivates the smiley recognition in the editor.
       
  1586     \sa HbLineEdit::setText() HbLineEdit::text()
       
  1587     \sa HbTextEdit::setPlainText() HbTextEdit::toPlainText()
       
  1588     \sa HbTextEdit::setHtml() HbTextEdit::toHtml()
       
  1589  */
       
  1590 void HbAbstractEdit::setSmileysEnabled(bool enabled)
       
  1591 {
       
  1592     Q_D(HbAbstractEdit);
       
  1593     if(d->smileysEnabled != enabled) {
       
  1594         d->smileysEnabled = enabled;
       
  1595         HbEditorInterface editorInterface(this);
       
  1596         if(enabled) {
       
  1597             editorInterface.setSmileyTheme(d->smileyEngineInstance()->theme());
       
  1598         } else {
       
  1599             editorInterface.setSmileyTheme(HbSmileyTheme());
       
  1600         }
       
  1601     }
       
  1602 }
       
  1603 
       
  1604 /*!
       
  1605     Return true if smiley recognition is enabled in the editor otherwise returns false.
       
  1606  */
       
  1607 bool HbAbstractEdit::isSmileysEnabled() const
       
  1608 {
       
  1609     Q_D(const HbAbstractEdit);
       
  1610     return d->smileysEnabled;
       
  1611 }
       
  1612 
       
  1613 /*!
       
  1614     Sets the format dialog for the editor. If it is set zero no format menu item shown 
       
  1615  */
       
  1616 void HbAbstractEdit::setFormatDialog(HbFormatDialogPointer dialog)
       
  1617 {
       
  1618     Q_D(HbAbstractEdit);
       
  1619     d->formatDialog = dialog;
       
  1620 }
       
  1621 
       
  1622 /*!
       
  1623     \reimp
       
  1624  */
       
  1625 void HbAbstractEdit::polish( HbStyleParameters& params )
       
  1626 {
       
  1627     Q_D(HbAbstractEdit);
       
  1628     const QString KTextAlignmentCSSName = "text-align";
       
  1629     const QString KTextColorCSSName = "color";
       
  1630 
       
  1631     // ------ adding css parameters ------
       
  1632     params.addParameter(KTextAlignmentCSSName);
       
  1633 
       
  1634     QPalette cssPalette = palette();
       
  1635     params.addParameter(KTextColorCSSName, cssPalette.color(QPalette::Text));
       
  1636 
       
  1637     HbWidget::polish(params);
       
  1638 
       
  1639     // ------ interpreting css parameters ------
       
  1640     QVariant param = params.value(KTextAlignmentCSSName);
       
  1641     if(param.canConvert(QVariant::String)) {
       
  1642         Qt::Alignment align = HbAbstractEditPrivate::alignmentFromString(param.toString());
       
  1643         if( align != 0 ) {
       
  1644             if (!(d->mApiProtectionFlags & HbWidgetBasePrivate::AC_TextAlign)) {
       
  1645                 setAlignment(align);
       
  1646                 d->mApiProtectionFlags &= ~HbWidgetBasePrivate::AC_TextAlign;
       
  1647             }
       
  1648         } else {
       
  1649             qWarning("Unable to read CSS parameter \"text-alignment\" in editor");
       
  1650         }
       
  1651     }
       
  1652 
       
  1653     param = params.value(KTextColorCSSName);
       
  1654     if(param.canConvert(QVariant::Color)) {
       
  1655         cssPalette.setColor(QPalette::Text, param.value<QColor>());
       
  1656     }
       
  1657 
       
  1658     setPalette(cssPalette);
       
  1659 }
       
  1660 
       
  1661 /*!
       
  1662     \reimp
       
  1663  */
       
  1664 QVariant HbAbstractEdit::itemChange(GraphicsItemChange change, const QVariant &value)
       
  1665 {
       
  1666     Q_D(const HbAbstractEdit);
       
  1667     if (change == QGraphicsItem::ItemScenePositionHasChanged) {
       
  1668         if (d->selectionControl) {
       
  1669             d->selectionControl->updatePrimitives();
       
  1670         }
       
  1671     }
       
  1672     return HbWidget::itemChange(change, value);
       
  1673 }
       
  1674 
       
  1675 /*!
       
  1676   Returns the character at position pos, or a null character if the position is out of range.
       
  1677 */
       
  1678 QChar HbAbstractEdit::characterAt(int pos) const
       
  1679 {
       
  1680     return document()->characterAt(pos);
       
  1681 }