src/hbwidgets/editors/hbabstractedit_p.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 //
       
    27 //  W A R N I N G
       
    28 //  -------------
       
    29 //
       
    30 // This file is not part of the Hb API.  It exists purely as an
       
    31 // implementation detail.  This file may change from version to
       
    32 // version without notice, or even be removed.
       
    33 //
       
    34 // We mean it.
       
    35 //
       
    36 
       
    37 #include "hbabstractedit_p.h"
       
    38 #include "hbabstractedit.h"
       
    39 #include "hbstyleoption.h"
       
    40 #include "hbscrollarea.h"
       
    41 #include "hbvalidator.h"
       
    42 #include "hbmeshlayout_p.h"
       
    43 #include "hbmenu.h"
       
    44 #include "hbselectioncontrol_p.h"
       
    45 #include "hbcolorscheme.h"
       
    46 #include "hbsmileyengine.h"
       
    47 #include "hbtextmeasurementutility_p.h"
       
    48 #include "hbfeaturemanager_p.h"
       
    49 #include "hbinputeditorinterface.h"
       
    50 #include "hbinputvkbhost.h"
       
    51 
       
    52 #include <QValidator>
       
    53 #include <QTextLayout>
       
    54 #include <QTextBlock>
       
    55 #include <QTextList>
       
    56 #include <QTextTable>
       
    57 #include <QApplication>
       
    58 #include <QGraphicsSceneMouseEvent>
       
    59 #include <QPainter>
       
    60 #include <QtDebug>
       
    61 #include <QClipboard>
       
    62 #include <QInputContext>
       
    63 #include <QRegExp>
       
    64 
       
    65 static inline bool firstFramePosLessThanCursorPos(QTextFrame *frame, int position)
       
    66 {
       
    67     return frame->firstPosition() < position;
       
    68 }
       
    69 
       
    70 static inline bool cursorPosLessThanLastFramePos(int position, QTextFrame *frame)
       
    71 {
       
    72     return position < frame->lastPosition();
       
    73 }
       
    74 
       
    75 static QRectF boundingRectOfFloatsInSelection(const QTextCursor &cursor)
       
    76 {
       
    77     QRectF r;
       
    78     QTextFrame *frame = cursor.currentFrame();
       
    79     const QList<QTextFrame *> children = frame->childFrames();
       
    80 
       
    81     const QList<QTextFrame *>::ConstIterator firstFrame = qLowerBound(children.constBegin(), children.constEnd(),
       
    82                                                                       cursor.selectionStart(), firstFramePosLessThanCursorPos);
       
    83     const QList<QTextFrame *>::ConstIterator lastFrame = qUpperBound(children.constBegin(), children.constEnd(),
       
    84                                                                      cursor.selectionEnd(), cursorPosLessThanLastFramePos);
       
    85     for (QList<QTextFrame *>::ConstIterator it = firstFrame; it != lastFrame; ++it) {
       
    86         if ((*it)->frameFormat().position() != QTextFrameFormat::InFlow)
       
    87             r |= frame->document()->documentLayout()->frameBoundingRect(*it);
       
    88     }
       
    89     return r;
       
    90 }
       
    91 
       
    92 class HbEditItem : public HbWidget
       
    93 {
       
    94 public:
       
    95 
       
    96     HbEditItem(HbAbstractEdit *parent) : HbWidget(parent), edit(parent)
       
    97     {
       
    98     };
       
    99 
       
   100     virtual ~HbEditItem() {};
       
   101 
       
   102     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
       
   103     {
       
   104         Q_UNUSED(widget)
       
   105 
       
   106         painter->save();
       
   107 #ifdef HB_DEBUG_EDITOR_DRAW_RECTS
       
   108         painter->setPen(Qt::yellow);
       
   109         painter->drawRect(boundingRect().adjusted(3,3,-3,-3));
       
   110 #endif
       
   111         if ( option) {
       
   112             edit->drawContents(painter, *option);
       
   113         }
       
   114 
       
   115         painter->restore();
       
   116     };
       
   117 
       
   118     HbAbstractEdit *edit;
       
   119 };
       
   120 
       
   121 static QTextLine currentTextLine(const QTextCursor &cursor)
       
   122 {
       
   123     const QTextBlock block = cursor.block();
       
   124     if (!block.isValid())
       
   125         return QTextLine();
       
   126 
       
   127     const QTextLayout *layout = block.layout();
       
   128     if (!layout)
       
   129         return QTextLine();
       
   130 
       
   131     const int relativePos = cursor.position() - block.position();
       
   132     return layout->lineForTextPosition(relativePos);
       
   133 }
       
   134 
       
   135 
       
   136 /*
       
   137  * HbEditScrollArea
       
   138  */
       
   139 
       
   140 HbEditScrollArea::HbEditScrollArea(HbAbstractEdit* edit, QGraphicsItem* parent)
       
   141     : HbScrollArea(parent),
       
   142       mEdit(edit)
       
   143 {
       
   144     setFlag(QGraphicsItem::ItemIsFocusable, false);
       
   145 }
       
   146 
       
   147 void HbEditScrollArea::updateScrollMetrics() {
       
   148     Q_D(HbScrollArea);
       
   149     d->updateScrollMetrics();
       
   150 }
       
   151 
       
   152 void HbEditScrollArea::resizeEvent(QGraphicsSceneResizeEvent *event) {
       
   153     HbScrollArea::resizeEvent(event);
       
   154     emit scrollAreaSizeChanged();
       
   155 }
       
   156 
       
   157 #ifdef HB_DEBUG_EDITOR_DRAW_RECTS
       
   158 void HbEditScrollArea::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
       
   159 {
       
   160     Q_UNUSED(widget);
       
   161     Q_UNUSED(option);
       
   162 
       
   163     painter->save();
       
   164     painter->setPen(Qt::red);
       
   165     painter->drawRect(boundingRect().adjusted(1,1,-1,-1));
       
   166 
       
   167     painter->restore();
       
   168 }
       
   169 #endif//HB_DEBUG_EDITOR_DRAW_RECTS
       
   170 
       
   171 
       
   172 void HbEditScrollArea::longPressGesture(const QPointF &point)
       
   173 {
       
   174     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   175     HbAbstractEditPrivate::d_ptr(mEdit)->longPressGesture(point);
       
   176 }
       
   177 
       
   178 void HbEditScrollArea::upGesture(int value){
       
   179     HbScrollArea::upGesture(value);
       
   180     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   181 }
       
   182 
       
   183 void HbEditScrollArea::downGesture(int value){
       
   184     HbScrollArea::downGesture(value);
       
   185     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   186 }
       
   187 
       
   188 void HbEditScrollArea::leftGesture(int value){
       
   189     HbScrollArea::leftGesture(value);
       
   190     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   191 }
       
   192 
       
   193 void HbEditScrollArea::rightGesture(int value){
       
   194     HbScrollArea::rightGesture(value);
       
   195     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   196 }
       
   197 
       
   198 void HbEditScrollArea::panGesture(const QPointF &point){
       
   199     HbScrollArea::panGesture(point);
       
   200     HbAbstractEditPrivate::d_ptr(mEdit)->gestureReceived();
       
   201 }
       
   202 
       
   203 QStringList HbAbstractEditMimeData::formats() const
       
   204 {
       
   205     if (!fragment.isEmpty())
       
   206         return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html");
       
   207     else
       
   208         return QMimeData::formats();
       
   209 }
       
   210 
       
   211 QVariant HbAbstractEditMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
       
   212 {
       
   213     if (!fragment.isEmpty())
       
   214         setup();
       
   215     return QMimeData::retrieveData(mimeType, type);
       
   216 }
       
   217 
       
   218 void HbAbstractEditMimeData::setup() const
       
   219 {
       
   220     HbAbstractEditMimeData *that = const_cast<HbAbstractEditMimeData *>(this);
       
   221 #ifndef QT_NO_TEXTHTMLPARSER
       
   222     that->setData(QLatin1String("text/html"), fragment.toHtml("utf-8").toUtf8());
       
   223 #endif
       
   224     that->setText(fragment.toPlainText());
       
   225     fragment = QTextDocumentFragment();
       
   226 }
       
   227 
       
   228 HbAbstractEditPrivate::HbAbstractEditPrivate () :
       
   229     HbWidgetPrivate(),
       
   230     doc(0),
       
   231     validator(0),
       
   232     imEditInProgress(false),
       
   233     imPosition(0),
       
   234     imAdded(0),
       
   235     imRemoved(0),
       
   236     interactionFlags(Qt::TextEditorInteraction),
       
   237     mousePressPos(-1, -1),
       
   238     cursorOn(false),
       
   239     preeditCursor(0),
       
   240     preeditCursorVisible(true),
       
   241     apiCursorVisible(true),
       
   242     canvas(0),
       
   243     scrollArea(0),
       
   244     scrollable(false),
       
   245     hadSelectionOnMousePress(false),
       
   246     selectionControl(0),
       
   247     acceptSignalContentsChange(true),
       
   248     acceptSignalContentsChanged(true),
       
   249     validRevision(0),
       
   250     wasGesture(false),
       
   251     smileysEnabled(false),
       
   252     smileyEngine(0),
       
   253     formatDialog(0)
       
   254 {
       
   255 }
       
   256 
       
   257 HbAbstractEditPrivate::~HbAbstractEditPrivate ()
       
   258 {
       
   259 }
       
   260 
       
   261 void HbAbstractEditPrivate::init()
       
   262 {
       
   263     Q_Q(HbAbstractEdit);
       
   264 
       
   265     canvas = new HbEditItem(q);
       
   266 
       
   267     setContent(Qt::RichText, QString());
       
   268 
       
   269     QTextOption textOption = doc->defaultTextOption();
       
   270     textOption.setTextDirection(q->layoutDirection());
       
   271     doc->setDefaultTextOption(textOption);
       
   272     doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable);
       
   273 
       
   274     updatePaletteFromTheme();
       
   275 
       
   276     scrollArea = new HbEditScrollArea(q, q);
       
   277     //scrollArea->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
       
   278     scrollArea->setClampingStyle(HbScrollArea::StrictClamping);
       
   279     scrollArea->setFrictionEnabled(true);
       
   280     scrollArea->setScrollDirections(Qt::Vertical);
       
   281     scrollArea->setVerticalScrollBarPolicy(HbScrollArea::ScrollBarAlwaysOff);
       
   282     scrollArea->setContentWidget(canvas);
       
   283     scrollArea->installEventFilter(q);
       
   284     scrollArea->setLongPressEnabled(true);
       
   285     scrollArea->setFlag(QGraphicsItem::ItemIsFocusable, false);
       
   286     QObject::connect(scrollArea, SIGNAL(scrollAreaSizeChanged()), q, SLOT(updatePrimitives()));
       
   287     QObject::connect(q, SIGNAL(selectionChanged(QTextCursor,QTextCursor)), q, SLOT(_q_selectionChanged()));
       
   288     HbStyle::setItemName(scrollArea, QString("text"));
       
   289 
       
   290     // These are the default values which are then overridden in subclasses
       
   291     // and when different options are enabled.
       
   292     q->setFlag(QGraphicsItem::ItemIsFocusable);
       
   293     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
       
   294     q->setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
       
   295     q->setFocusPolicy(Qt::StrongFocus);
       
   296     q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
       
   297 
       
   298     contextMenuShownOn = Hb::ShowTextContextMenuOnSelectionClicked | Hb::ShowTextContextMenuOnLongPress;
       
   299 
       
   300 }
       
   301 
       
   302 void HbAbstractEditPrivate::updatePaletteFromTheme()
       
   303 {
       
   304     Q_Q(HbAbstractEdit);
       
   305 
       
   306     // TODO: remove once these color dissapear from hbcolorgroup.css
       
   307     QColor textColor = HbColorScheme::color("qtc_editor_normal");
       
   308     QColor selectedColor = HbColorScheme::color("qtc_editor_selected");
       
   309     QColor selectedBackground = HbColorScheme::color("qtc_editor_marker_normal");
       
   310     QPalette pal = q->palette();
       
   311 
       
   312     if (textColor.isValid()) {
       
   313         pal.setColor(QPalette::Text, textColor);
       
   314     }
       
   315 
       
   316     if (selectedColor.isValid()) {
       
   317         pal.setColor(QPalette::HighlightedText, selectedColor);
       
   318     }
       
   319 
       
   320     if (selectedBackground.isValid()) {
       
   321         pal.setColor(QPalette::Highlight, selectedBackground);
       
   322     }
       
   323     q->setPalette(pal);
       
   324 
       
   325 
       
   326     // The link color is used from application's palette
       
   327     QColor linkColor = HbColorScheme::color("qtc_view_link_normal");
       
   328     QColor linkVisitedColor = HbColorScheme::color("qtc_view_visited_normal");
       
   329     QPalette appPal = qApp->palette();
       
   330     if (linkColor.isValid()) {
       
   331         appPal.setColor(QPalette::Link, linkColor);
       
   332     }
       
   333 
       
   334     if (linkVisitedColor.isValid()) {
       
   335         appPal.setColor(QPalette::LinkVisited, linkVisitedColor);
       
   336     }
       
   337     qApp->setPalette(appPal);
       
   338 
       
   339 }
       
   340 
       
   341 void HbAbstractEditPrivate::setContent(Qt::TextFormat format, const QString &text)
       
   342 {
       
   343     Q_Q(HbAbstractEdit);
       
   344 
       
   345     // for localization text support
       
   346     QString txt( text );
       
   347 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
   348     if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
       
   349         if (text.endsWith(QChar(LOC_TEST_END))) {
       
   350             int index = text.indexOf(QChar(LOC_TEST_START));
       
   351             q->setProperty( HbTextMeasurementUtilityNameSpace::textIdPropertyName,
       
   352                     text.mid(index + 1, text.indexOf(QChar(LOC_TEST_END)) - index - 1) );
       
   353             txt = text.left(index);
       
   354         }
       
   355     }
       
   356 #endif
       
   357 
       
   358     // for use when called from setPlainText. we may want to re-use the currently
       
   359     // set char format then.
       
   360     const QTextCharFormat charFormatForInsertion = cursor.charFormat();
       
   361 
       
   362     const QTextCursor oldSelection = cursor;
       
   363 
       
   364     bool clearDocument = true;
       
   365     if (!doc) {
       
   366         connectToNewDocument(new QTextDocument(q));
       
   367     }
       
   368 
       
   369     bool previousUndoRedoState = doc->isUndoRedoEnabled();
       
   370     doc->setUndoRedoEnabled(false);
       
   371 
       
   372     // avoid multiple textChanged() signals being emitted
       
   373     acceptSignalContentsChanged = false;
       
   374 
       
   375     if (!txt.isEmpty()) {
       
   376         // clear 'our' cursor for insertion to prevent
       
   377         // the emission of the cursorPositionChanged() signal.
       
   378         // instead we emit it only once at the end instead of
       
   379         // at the end of the document after loading and when
       
   380         // positioning the cursor again to the start of the
       
   381         // document.
       
   382         cursor = QTextCursor();
       
   383 
       
   384         if (format == Qt::PlainText) {
       
   385             QTextCursor formatCursor(doc);
       
   386             formatCursor.beginEditBlock();
       
   387             // put the setPlainText and the setCharFormat into one edit block,
       
   388             // so that the syntax highlight triggers only /once/ for the entire
       
   389             // document, not twice.
       
   390             doc->setPlainText(txt);
       
   391             formatCursor.select(QTextCursor::Document);
       
   392             formatCursor.setCharFormat(charFormatForInsertion);
       
   393             formatCursor.endEditBlock();
       
   394         } else {
       
   395 #ifndef QT_NO_TEXTHTMLPARSER
       
   396             doc->setHtml(txt);
       
   397 #else
       
   398             doc->setPlainText(txt);
       
   399 #endif
       
   400         }
       
   401         cursor = QTextCursor(doc);
       
   402     } else if (clearDocument) {
       
   403         doc->clear();
       
   404     }
       
   405     cursor.setCharFormat(charFormatForInsertion);
       
   406 
       
   407     doc->setUndoRedoEnabled(previousUndoRedoState);
       
   408 
       
   409     acceptSignalContentsChanged = true;
       
   410 
       
   411     updateCurrentCharFormat();
       
   412 
       
   413     emit q->contentsChanged();
       
   414 
       
   415     cursorChanged(HbValidator::CursorChangeFromContentSet);
       
   416 
       
   417     doc->setModified(false);
       
   418 
       
   419     ensureCursorVisible();
       
   420 
       
   421     smileyEngineInstance()->setDocument(doc);
       
   422     if(q->isSmileysEnabled()) {
       
   423         smileyEngineInstance()->insertSmileys();
       
   424     }
       
   425 }
       
   426 
       
   427 bool HbAbstractEditPrivate::setFocusToAnchor(const QTextCursor &newCursor)
       
   428 {
       
   429     Q_UNUSED(newCursor);
       
   430     return false;
       
   431 }
       
   432 bool HbAbstractEditPrivate::setFocusToNextOrPreviousAnchor(bool next)
       
   433 {
       
   434     Q_UNUSED(next);
       
   435     return false;
       
   436 }
       
   437 
       
   438 bool HbAbstractEditPrivate::findNextPrevAnchor(const QTextCursor& from, bool next, QTextCursor& newAnchor)
       
   439 {
       
   440     Q_UNUSED(from);
       
   441     Q_UNUSED(next);
       
   442     Q_UNUSED(newAnchor);
       
   443     return false;
       
   444 }
       
   445 
       
   446 void HbAbstractEditPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode)
       
   447 {
       
   448     cursor.setPosition(pos, mode);
       
   449 
       
   450     cursorChanged(HbValidator::CursorChangeFromMouse);
       
   451 }
       
   452 
       
   453 bool HbAbstractEditPrivate::cursorMoveKeyEvent(QKeyEvent *e)
       
   454 {
       
   455 #ifdef QT_NO_SHORTCUT
       
   456     Q_UNUSED(e);
       
   457 #endif
       
   458 
       
   459     if (cursor.isNull())
       
   460         return false;
       
   461 
       
   462     QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
       
   463     QTextCursor::MoveOperation op = QTextCursor::NoMove;
       
   464 
       
   465     if (false) {
       
   466     }
       
   467 #ifndef QT_NO_SHORTCUT
       
   468     if (e == QKeySequence::MoveToNextChar) {
       
   469             op = QTextCursor::Right;
       
   470     }
       
   471     else if (e == QKeySequence::MoveToPreviousChar) {
       
   472             op = QTextCursor::Left;
       
   473     }
       
   474     else if (e == QKeySequence::SelectNextChar) {
       
   475            op = QTextCursor::Right;
       
   476            mode = QTextCursor::KeepAnchor;
       
   477     }
       
   478     else if (e == QKeySequence::SelectPreviousChar) {
       
   479             op = QTextCursor::Left;
       
   480             mode = QTextCursor::KeepAnchor;
       
   481     }
       
   482     else if (e == QKeySequence::SelectNextWord) {
       
   483             op = QTextCursor::WordRight;
       
   484             mode = QTextCursor::KeepAnchor;
       
   485     }
       
   486     else if (e == QKeySequence::SelectPreviousWord) {
       
   487             op = QTextCursor::WordLeft;
       
   488             mode = QTextCursor::KeepAnchor;
       
   489     }
       
   490     else if (e == QKeySequence::SelectStartOfLine) {
       
   491             op = QTextCursor::StartOfLine;
       
   492             mode = QTextCursor::KeepAnchor;
       
   493     }
       
   494     else if (e == QKeySequence::SelectEndOfLine) {
       
   495             op = QTextCursor::EndOfLine;
       
   496             mode = QTextCursor::KeepAnchor;
       
   497     }
       
   498     else if (e == QKeySequence::SelectStartOfBlock) {
       
   499             op = QTextCursor::StartOfBlock;
       
   500             mode = QTextCursor::KeepAnchor;
       
   501     }
       
   502     else if (e == QKeySequence::SelectEndOfBlock) {
       
   503             op = QTextCursor::EndOfBlock;
       
   504             mode = QTextCursor::KeepAnchor;
       
   505     }
       
   506     else if (e == QKeySequence::SelectStartOfDocument) {
       
   507             op = QTextCursor::Start;
       
   508             mode = QTextCursor::KeepAnchor;
       
   509     }
       
   510     else if (e == QKeySequence::SelectEndOfDocument) {
       
   511             op = QTextCursor::End;
       
   512             mode = QTextCursor::KeepAnchor;
       
   513     }
       
   514     else if (e == QKeySequence::SelectPreviousLine) {
       
   515             op = QTextCursor::Up;
       
   516             mode = QTextCursor::KeepAnchor;
       
   517     }
       
   518     else if (e == QKeySequence::SelectNextLine) {
       
   519             op = QTextCursor::Down;
       
   520             mode = QTextCursor::KeepAnchor;
       
   521             {
       
   522                 QTextBlock block = cursor.block();
       
   523                 QTextLine line = currentTextLine(cursor);
       
   524                 if (!block.next().isValid()
       
   525                     && line.isValid()
       
   526                     && line.lineNumber() == block.layout()->lineCount() - 1)
       
   527                     op = QTextCursor::End;
       
   528             }
       
   529     }
       
   530     else if (e == QKeySequence::MoveToNextWord) {
       
   531             op = QTextCursor::WordRight;
       
   532     }
       
   533     else if (e == QKeySequence::MoveToPreviousWord) {
       
   534             op = QTextCursor::WordLeft;
       
   535     }
       
   536     else if (e == QKeySequence::MoveToEndOfBlock) {
       
   537             op = QTextCursor::EndOfBlock;
       
   538     }
       
   539     else if (e == QKeySequence::MoveToStartOfBlock) {
       
   540             op = QTextCursor::StartOfBlock;
       
   541     }
       
   542     else if (e == QKeySequence::MoveToNextLine) {
       
   543             op = QTextCursor::Down;
       
   544     }
       
   545     else if (e == QKeySequence::MoveToPreviousLine) {
       
   546             op = QTextCursor::Up;
       
   547     }
       
   548     else if (e == QKeySequence::MoveToPreviousLine) {
       
   549             op = QTextCursor::Up;
       
   550     }
       
   551     else if (e == QKeySequence::MoveToStartOfLine) {
       
   552             op = QTextCursor::StartOfLine;
       
   553     }
       
   554     else if (e == QKeySequence::MoveToEndOfLine) {
       
   555             op = QTextCursor::EndOfLine;
       
   556     }
       
   557     else if (e == QKeySequence::MoveToStartOfDocument) {
       
   558             op = QTextCursor::Start;
       
   559     }
       
   560     else if (e == QKeySequence::MoveToEndOfDocument) {
       
   561             op = QTextCursor::End;
       
   562     }
       
   563 #endif // QT_NO_SHORTCUT
       
   564     else {
       
   565         return false;
       
   566     }
       
   567 
       
   568     const QTextCursor oldCursor = cursor;
       
   569     bool visualNavigation = cursor.visualNavigation();
       
   570     cursor.setVisualNavigation(true);
       
   571     cursor.movePosition(op, mode);
       
   572     cursor.setVisualNavigation(visualNavigation);
       
   573     cursorChanged(HbValidator::CursorChangeFromOperation);
       
   574     repaintOldAndNewSelection(oldCursor);
       
   575 
       
   576     return true;
       
   577 }
       
   578 
       
   579 void HbAbstractEditPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection)
       
   580 {
       
   581     //Q_Q(HbAbstractEdit);
       
   582     if (cursor.hasSelection()
       
   583         && oldSelection.hasSelection()
       
   584         && cursor.currentFrame() == oldSelection.currentFrame()
       
   585         && !cursor.hasComplexSelection()
       
   586         && !oldSelection.hasComplexSelection()
       
   587         && cursor.anchor() == oldSelection.anchor()
       
   588         ) {
       
   589         QTextCursor differenceSelection(doc);
       
   590         differenceSelection.setPosition(oldSelection.position());
       
   591         differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor);
       
   592         canvas->update(selectionRect(differenceSelection));
       
   593     } else {
       
   594         if (!oldSelection.isNull())
       
   595             canvas->update(selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection.position()));
       
   596         canvas->update(selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor.position()));
       
   597     }
       
   598 }
       
   599 
       
   600 void HbAbstractEditPrivate::updateCurrentCharFormat()
       
   601 {
       
   602     QTextCharFormat fmt = cursor.charFormat();
       
   603     if (fmt == lastCharFormat)
       
   604         return;
       
   605     lastCharFormat = fmt;
       
   606 }
       
   607 
       
   608 QRectF HbAbstractEditPrivate::cursorRectPlusUnicodeDirectionMarkers(int position) const
       
   609 {
       
   610     return rectForPositionInCanvasCoords(position,QTextLine::Leading).adjusted(-4, 0, 4, 0);
       
   611 }
       
   612 
       
   613 void HbAbstractEditPrivate::setBlinkingCursorEnabled(bool enable)
       
   614 {
       
   615     Q_Q(HbAbstractEdit);
       
   616 
       
   617     if (enable && QApplication::cursorFlashTime() > 0)
       
   618         cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q);
       
   619     else
       
   620         cursorBlinkTimer.stop();
       
   621 
       
   622     cursorOn = enable;
       
   623 
       
   624     repaintCursor();
       
   625 }
       
   626 
       
   627 void HbAbstractEditPrivate::repaintCursor()
       
   628 {
       
   629     canvas->update(cursorRectPlusUnicodeDirectionMarkers(cursor.position()));
       
   630 }
       
   631 
       
   632 void HbAbstractEditPrivate::ensurePositionVisible(int position)
       
   633 {
       
   634     if (scrollArea && scrollable) {
       
   635         QRectF rect = rectForPositionInCanvasCoords(position, QTextLine::Leading);
       
   636         // TODO: it seems that scrollArea->ensureVisible() expects the point
       
   637         //       in its content coordinates. Probably it should use viewport
       
   638         //       coordinates i.e. its own item coordinate system
       
   639         //QRectF recScroll = canvas->mapToItem(scrollArea, rect).boundingRect();
       
   640         scrollArea->ensureVisible(rect.center(), rect.width(), rect.height()/2);
       
   641     }
       
   642 }
       
   643 
       
   644 void HbAbstractEditPrivate::ensureCursorVisible()
       
   645 {
       
   646     ensurePositionVisible(cursor.position());
       
   647 }
       
   648 
       
   649 void HbAbstractEditPrivate::setTextInteractionFlags(Qt::TextInteractionFlags flags)
       
   650 {
       
   651     Q_Q(HbAbstractEdit);
       
   652 
       
   653     if (flags == interactionFlags)
       
   654         return;
       
   655     interactionFlags = flags;
       
   656 
       
   657     if (q->hasFocus()) {
       
   658         setBlinkingCursorEnabled(flags & Qt::TextEditable);
       
   659     }
       
   660 }
       
   661 
       
   662 void HbAbstractEditPrivate::_q_updateRequest(QRectF rect)
       
   663 {
       
   664     canvas->update(rect);
       
   665 }
       
   666 
       
   667 void HbAbstractEditPrivate::_q_updateBlock(QTextBlock block)
       
   668 {
       
   669     Q_Q(HbAbstractEdit);
       
   670     _q_updateRequest(q->blockBoundingRect(block));
       
   671 }
       
   672 
       
   673 void HbAbstractEditPrivate::_q_contentsChanged()
       
   674 {
       
   675     Q_Q(HbAbstractEdit);
       
   676     if(acceptSignalContentsChanged) {
       
   677         acceptSignalContentsChanged = false; // prevent recurence
       
   678 
       
   679         if(imPosition>=0) {
       
   680             validateAndCorrect();
       
   681         }
       
   682         updateCurrentCharFormat();
       
   683 
       
   684         emit q->contentsChanged();
       
   685 
       
   686         acceptSignalContentsChanged = true; // end of prevent recurence
       
   687     }
       
   688 }
       
   689 
       
   690 void HbAbstractEditPrivate::_q_contentsChange(int position, int charsRemoved, int charsAdded)
       
   691 {
       
   692     if(acceptSignalContentsChange) {
       
   693         imPosition = position;
       
   694         imRemoved = charsRemoved;
       
   695         imAdded = charsAdded;
       
   696     }
       
   697 }
       
   698 
       
   699 void HbAbstractEditPrivate::_q_selectionChanged()
       
   700 {
       
   701     Q_Q(HbAbstractEdit);
       
   702 
       
   703     if (cursor.hasSelection()) {
       
   704         if (!selectionControl) {
       
   705             selectionControl = new HbSelectionControl(q);
       
   706         }
       
   707         selectionControl->showHandles();
       
   708         q->update();
       
   709     } else if (selectionControl){
       
   710         selectionControl->hideHandles();
       
   711         q->update();
       
   712     }
       
   713 }
       
   714 
       
   715 void HbAbstractEditPrivate::validateAndCorrect()
       
   716 {
       
   717     if (validator && !imEditInProgress) {
       
   718         QValidator::State state = validateContent(imPosition, imRemoved, imAdded);
       
   719         if (state == QValidator::Invalid) {
       
   720             // workaround (undo doesn't decreases revision number in Qt 4.6 and it does in Qt 4.5.2):
       
   721             int undoCount = doc->revision() - validRevision;
       
   722             for( ;undoCount>0 && doc->isUndoRedoEnabled(); --undoCount) {
       
   723                  doc->undo();
       
   724             }
       
   725             validRevision = doc->revision();
       
   726         } else if(state == QValidator::Acceptable) {
       
   727             doc->setModified(false); // store information to use undo in case Invalid values
       
   728             validRevision = doc->revision();
       
   729         }
       
   730     }
       
   731 }
       
   732 
       
   733 QValidator::State HbAbstractEditPrivate::validateContent(int position, int charsRemoved, int charsAdded)
       
   734 {
       
   735 #ifdef HBVALIDATOR_DEBUG_ENABLE
       
   736     qDebug() << "HbAbstractEditPrivate::validateContent"
       
   737             << "Pos: " << position
       
   738             << "[-]: " << charsRemoved
       
   739             << "[+]: " << charsAdded;
       
   740 #endif
       
   741     // acceptSignalContentsChange = false; // not needed afrer corection
       
   742     QValidator::State state = validator->validateContent(cursor, position, charsRemoved, charsAdded);
       
   743     validator->updateTextCursor(cursor);
       
   744     // acceptSignalContentsChange = true; // not needed afrer corection
       
   745 #ifdef HBVALIDATOR_DEBUG_ENABLE
       
   746     qDebug() << "HbAbstractEditPrivate::validateContent"
       
   747             << ((state == QValidator::Acceptable) ? "Acceptable  " : ((state == QValidator::Intermediate) ? "Intermediate" : "Invalid     "));
       
   748 #endif
       
   749     return state;
       
   750 }
       
   751 
       
   752 void HbAbstractEditPrivate::initValidator()
       
   753 {
       
   754     doc->setUndoRedoEnabled(true);
       
   755     doc->setPlainText(validator->defaultValue());
       
   756 }
       
   757 
       
   758 void HbAbstractEditPrivate::cursorChanged(CursorChange origin)
       
   759 {
       
   760     Q_Q(HbAbstractEdit);
       
   761     if (previousCursorPosition != cursor.position()
       
   762             || previousCursorAnchor != cursor.anchor()) {
       
   763 
       
   764         if (validator && !imEditInProgress) {
       
   765             QTextCursor previousCursor(cursor);
       
   766             previousCursor.setPosition(previousCursorAnchor);
       
   767             previousCursor.setPosition(previousCursorPosition, QTextCursor::KeepAnchor);
       
   768             validator->validateCursorPosition(previousCursor, cursor, origin);
       
   769 
       
   770             if (previousCursorPosition == cursor.position() && previousCursorAnchor == cursor.anchor()) {
       
   771                 // validator can cancel cursor position change
       
   772                 return;
       
   773             }
       
   774         } // if validator
       
   775 
       
   776         // repaint the old cursor position
       
   777         canvas->update(cursorRectPlusUnicodeDirectionMarkers(previousCursorPosition));
       
   778 
       
   779         emit q->cursorPositionChanged(previousCursorPosition, cursor.position());
       
   780         previousCursorAnchor = cursor.anchor();
       
   781         previousCursorPosition = cursor.position();
       
   782         nextCharCursor = cursor;
       
   783         selectionChanged();
       
   784     }
       
   785 }
       
   786 
       
   787 void HbAbstractEditPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/)
       
   788 {
       
   789     Q_Q(HbAbstractEdit);
       
   790     if (!forceEmitSelectionChanged) {
       
   791         if (selectionCursor.position() == cursor.position()
       
   792             && selectionCursor.anchor() == cursor.anchor()) {
       
   793             return;
       
   794         }
       
   795         if (!selectionCursor.hasSelection() && !cursor.hasSelection()) {
       
   796             return;
       
   797         }
       
   798     }
       
   799 
       
   800     emit q->selectionChanged(selectionCursor, cursor);
       
   801     selectionCursor = cursor;
       
   802 }
       
   803 
       
   804 void HbAbstractEditPrivate::acceptKeyPressEvent(QKeyEvent *event)
       
   805 {
       
   806     event->accept();
       
   807     cursorOn = true;
       
   808     ensureCursorVisible();
       
   809 
       
   810     updateCurrentCharFormat();
       
   811 }
       
   812 
       
   813 QAbstractTextDocumentLayout::PaintContext HbAbstractEditPrivate::getPaintContext() const
       
   814 {
       
   815     Q_Q(const HbAbstractEdit);
       
   816 
       
   817     QAbstractTextDocumentLayout::PaintContext ctx;
       
   818 
       
   819     ctx.palette = q->palette();
       
   820     if (cursorOn && q->isEnabled()) {
       
   821         if (!isCursorVisible())
       
   822             ctx.cursorPosition = -1;
       
   823         else if (preeditCursor != 0)
       
   824             ctx.cursorPosition = - (preeditCursor + 2);
       
   825         else
       
   826             ctx.cursorPosition = cursor.position();
       
   827     }
       
   828 
       
   829     if (cursor.hasSelection()) {
       
   830         QAbstractTextDocumentLayout::Selection selection;
       
   831         selection.cursor = cursor;
       
   832         QPalette::ColorGroup cg = q->hasFocus() ? QPalette::Active : QPalette::Inactive;
       
   833         selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
       
   834         selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText));
       
   835 
       
   836         HbStyleOption opt;
       
   837         q->initStyleOption(&opt);
       
   838 
       
   839 		if (qApp->style()->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, 0)) {
       
   840             selection.format.setProperty(QTextFormat::FullWidthSelection, true);
       
   841         }
       
   842         ctx.selections.append(selection);
       
   843     }
       
   844 
       
   845     return ctx;
       
   846 }
       
   847 
       
   848 int HbAbstractEditPrivate::hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const
       
   849 {
       
   850     Q_Q(const HbAbstractEdit);
       
   851     return doc->documentLayout()->hitTest(q->mapToItem(canvas, point), accuracy);
       
   852 }
       
   853 
       
   854 QRectF HbAbstractEditPrivate::cursorRect(const QTextCursor &cursor) const
       
   855 {
       
   856     Q_Q(const HbAbstractEdit);
       
   857     if (cursor.isNull())
       
   858         return QRectF();
       
   859 
       
   860     return q->rectForPosition(cursor.position());
       
   861 }
       
   862 
       
   863 QRectF HbAbstractEditPrivate::cursorRect() const
       
   864 {
       
   865     return cursorRect(cursor);
       
   866 }
       
   867 
       
   868 QRectF HbAbstractEditPrivate::selectionRect(const QTextCursor &cursor) const
       
   869 {
       
   870     Q_Q(const HbAbstractEdit);
       
   871 
       
   872     QRectF r = q->rectForPosition(cursor.selectionStart());
       
   873 
       
   874     if (cursor.hasComplexSelection() && cursor.currentTable()) {
       
   875         QTextTable *table = cursor.currentTable();
       
   876         r = doc->documentLayout()->frameBoundingRect(table);
       
   877     } else if (cursor.hasSelection()) {
       
   878         const int position = cursor.selectionStart();
       
   879         const int anchor = cursor.selectionEnd();
       
   880         const QTextBlock posBlock = doc->findBlock(position);
       
   881         const QTextBlock anchorBlock = doc->findBlock(anchor);
       
   882         if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) {
       
   883             const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position());
       
   884             const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position());
       
   885 
       
   886             const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber());
       
   887             const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber());
       
   888             const QTextLayout *layout = posBlock.layout();
       
   889             r = QRectF();
       
   890             for (int i = firstLine; i <= lastLine; ++i) {
       
   891                 r |= layout->lineAt(i).rect();
       
   892                 r |= layout->lineAt(i).naturalTextRect(); // might be bigger in the case of wrap not enabled
       
   893             }
       
   894             r.translate(q->blockBoundingRect(posBlock).topLeft());
       
   895         } else {
       
   896             QRectF anchorRect = q->rectForPosition(cursor.selectionEnd());
       
   897             r |= anchorRect;
       
   898             r |= boundingRectOfFloatsInSelection(cursor);
       
   899             QRectF frameRect(doc->documentLayout()->frameBoundingRect(cursor.currentFrame()));
       
   900             r.setLeft(frameRect.left());
       
   901             r.setRight(frameRect.right());
       
   902         }
       
   903         if (r.isValid())
       
   904             r.adjust(-1, -1, 1, 1);
       
   905     }
       
   906 
       
   907     return r;
       
   908 }
       
   909 
       
   910 QRectF HbAbstractEditPrivate::selectionRect() const
       
   911 {
       
   912     return selectionRect(selectionCursor);
       
   913 }
       
   914 
       
   915 QRectF HbAbstractEditPrivate::rectForPositionInCanvasCoords(int position, QTextLine::Edge edge) const
       
   916 {
       
   917     Q_Q(const HbAbstractEdit);
       
   918 
       
   919     const QTextBlock block = doc->findBlock(position);
       
   920     if (!block.isValid())
       
   921         return QRectF();
       
   922     const QAbstractTextDocumentLayout *docLayout = doc->documentLayout();
       
   923     const QTextLayout *layout = block.layout();
       
   924     const QPointF layoutPos = q->blockBoundingRect(block).topLeft();
       
   925     int relativePos = position - block.position();
       
   926     if (preeditCursor != 0) {
       
   927         int preeditPos = layout->preeditAreaPosition();
       
   928         if (relativePos == preeditPos)
       
   929             relativePos += preeditCursor;
       
   930         else if (relativePos > preeditPos)
       
   931             relativePos += layout->preeditAreaText().length();
       
   932     }
       
   933     QTextLine line = layout->lineForTextPosition(relativePos);
       
   934 
       
   935     int cursorWidth;
       
   936     {
       
   937         bool ok = false;
       
   938 #ifndef QT_NO_PROPERTIES
       
   939         cursorWidth = docLayout->property("cursorWidth").toInt(&ok);
       
   940 #endif
       
   941         if (!ok)
       
   942             cursorWidth = 1;
       
   943     }
       
   944 
       
   945     QRectF r;
       
   946 
       
   947     if (line.isValid()) {
       
   948         qreal x = line.cursorToX(relativePos, edge);
       
   949         qreal w = 0;
       
   950         r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(),
       
   951                    cursorWidth + w, line.height());
       
   952     } else {
       
   953         r = QRectF(layoutPos.x(), layoutPos.y(), cursorWidth, 10); // #### correct height
       
   954     }
       
   955 
       
   956     return r;
       
   957 }
       
   958 
       
   959 int HbAbstractEditPrivate::contentLength() const
       
   960 {
       
   961     QTextBlock block = doc->lastBlock();
       
   962     return block.position() + block.length() - 1;
       
   963 }
       
   964 
       
   965 bool HbAbstractEditPrivate::hasAcceptableInput() const
       
   966 {
       
   967     QTextCursor cursorCopy = cursor;
       
   968     if (validator &&
       
   969         validator->validateContent(cursorCopy, 0, 0, 0) != QValidator::Acceptable) {
       
   970         return false;
       
   971     }
       
   972     return true;
       
   973 }
       
   974 
       
   975 bool HbAbstractEditPrivate::canPaste() const
       
   976 {
       
   977 #ifndef QT_NO_CLIPBOARD
       
   978     Q_Q(const HbAbstractEdit);
       
   979     if (interactionFlags & Qt::TextEditable) {
       
   980         const QMimeData *md = QApplication::clipboard()->mimeData();
       
   981         return md && q->canInsertFromMimeData(md);
       
   982     }
       
   983 #endif//QT_NO_CLIPBOARD
       
   984     return false;
       
   985 }
       
   986 
       
   987 bool HbAbstractEditPrivate::canCopy() const
       
   988 {
       
   989 #ifndef QT_NO_CLIPBOARD
       
   990     return true;
       
   991 #else
       
   992     return false;
       
   993 #endif//QT_NO_CLIPBOARD
       
   994 }
       
   995 
       
   996 bool HbAbstractEditPrivate::canFormat() const
       
   997 {
       
   998     return formatDialog != 0;
       
   999 }
       
  1000 
       
  1001 bool HbAbstractEditPrivate::isCursorVisible() const
       
  1002 {
       
  1003     return preeditCursorVisible && apiCursorVisible;
       
  1004 }
       
  1005 
       
  1006 void HbAbstractEditPrivate::sendMouseEventToInputContext(const QGraphicsSceneMouseEvent *e) const
       
  1007 {
       
  1008     QPointF pos = e->pos();
       
  1009     int cursorPos = hitTest(pos, Qt::FuzzyHit);
       
  1010     if (cursorPos == -1)
       
  1011         return;
       
  1012 
       
  1013     QTextLayout *layout = cursor.block().layout();
       
  1014     if (layout && !layout->preeditAreaText().isEmpty()) {
       
  1015         QInputContext *ctx = qApp->inputContext();
       
  1016         if (ctx) {
       
  1017             QMouseEvent ev(QEvent::MouseButtonPress, pos.toPoint(), e->scenePos().toPoint(),
       
  1018                            e->button(), e->buttons(), e->modifiers());
       
  1019             ctx->mouseHandler(cursorPos - cursor.position(), &ev);
       
  1020         }
       
  1021     }
       
  1022 }
       
  1023 
       
  1024 void HbAbstractEditPrivate::updateEditingSize()
       
  1025 {
       
  1026 }
       
  1027 
       
  1028 void HbAbstractEditPrivate::removeCurrentDocument()
       
  1029 {
       
  1030     Q_Q(HbAbstractEdit);
       
  1031 
       
  1032     if( doc ) {
       
  1033         doc->disconnect(q);
       
  1034         doc->documentLayout()->disconnect(q);
       
  1035         doc->documentLayout()->setPaintDevice(0);
       
  1036 
       
  1037         if (doc->parent() == q) {
       
  1038             delete doc;
       
  1039         }
       
  1040 
       
  1041         doc = 0;
       
  1042     }
       
  1043 }
       
  1044 
       
  1045 void HbAbstractEditPrivate::connectToNewDocument(QTextDocument *newDoc)
       
  1046 {
       
  1047     Q_Q(HbAbstractEdit);
       
  1048 
       
  1049     doc = newDoc;
       
  1050     cursor = QTextCursor(doc);
       
  1051 
       
  1052     QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_contentsChanged()));
       
  1053     QObject::connect(doc, SIGNAL(contentsChange(int, int, int)), q, SLOT(_q_contentsChange(int, int, int)));
       
  1054 
       
  1055     //QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(emitCursorPosChanged(QTextCursor)));
       
  1056     QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(documentLayoutChanged()));
       
  1057 
       
  1058     QObject::connect(doc, SIGNAL(blockCountChanged(int)), q, SLOT(blockCountChanged(int)));
       
  1059 
       
  1060     doc->setModified(false);
       
  1061 
       
  1062     q->documentLayoutChanged();
       
  1063 }
       
  1064 
       
  1065 void HbAbstractEditPrivate::longPressGesture(const QPointF &point)
       
  1066 {
       
  1067     Q_Q(HbAbstractEdit);
       
  1068 
       
  1069     if(contextMenuShownOn.testFlag(Hb::ShowTextContextMenuOnLongPress)) {
       
  1070         mousePressPos = q->mapFromScene(point);
       
  1071 
       
  1072         int cursorPos = hitTest(mousePressPos, Qt::FuzzyHit);
       
  1073         if (cursorPos == -1)
       
  1074             return;
       
  1075 
       
  1076         // don't do anything if longpress inside the selection
       
  1077         if (cursor.hasSelection()
       
  1078             && cursorPos >= cursor.selectionStart()
       
  1079             && cursorPos <= cursor.selectionEnd()){
       
  1080             return;
       
  1081         }
       
  1082         q->showContextMenu(point);
       
  1083     }
       
  1084 
       
  1085     //TODO:
       
  1086     // this call is needed because now the panStarted is called in mousePressEvent
       
  1087     // and panFinished is called in mouseReleaseEvent, but in longPress case the mouseRelease is not called
       
  1088     // Once the this gesture bug is fixed this needs to be removed!
       
  1089     if (selectionControl) {
       
  1090         selectionControl->panFinished();
       
  1091     }
       
  1092 }
       
  1093 
       
  1094 void HbAbstractEditPrivate::gestureReceived()
       
  1095 {
       
  1096     wasGesture = true;
       
  1097 }
       
  1098 
       
  1099 
       
  1100 void HbAbstractEditPrivate::hideSelectionHandles()
       
  1101 {
       
  1102     Q_Q(HbAbstractEdit);
       
  1103     if (selectionControl){
       
  1104         selectionControl->hideHandles();
       
  1105     }
       
  1106     q->update();
       
  1107 }
       
  1108 
       
  1109 
       
  1110 void HbAbstractEditPrivate::drawSelectionEdges(QPainter *painter, QAbstractTextDocumentLayout::PaintContext ctx)
       
  1111 {
       
  1112     if (cursor.hasSelection() && selectionControl && selectionControl->isVisible()){
       
  1113         painter->setPen(ctx.palette.color(QPalette::Text));
       
  1114         painter->setBrush(ctx.palette.color(QPalette::Text));
       
  1115         painter->drawRect(rectForPositionInCanvasCoords(cursor.selectionStart(), QTextLine::Leading));
       
  1116         painter->drawRect(rectForPositionInCanvasCoords(cursor.selectionEnd(), QTextLine::Trailing));
       
  1117     }
       
  1118 }
       
  1119 
       
  1120 /*
       
  1121  * Prepares the document for pasting. Derived classes can override this method,
       
  1122  * e.g. HbLineEdit clears the document before pasting when in password edit mode
       
  1123  */
       
  1124 void HbAbstractEditPrivate::prepDocForPaste()
       
  1125 {
       
  1126 }
       
  1127 
       
  1128 /*
       
  1129  * this method should draw text background. it is temporary solution until
       
  1130  * HbTexdDocumentlayout will be implemented
       
  1131  *
       
  1132  * this method is reimplemented by HbTextEdit to draw text base lines
       
  1133  */
       
  1134 void HbAbstractEditPrivate::drawContentBackground(QPainter *,
       
  1135                                                   const QStyleOptionGraphicsItem &) const
       
  1136 {
       
  1137     // no implementation is needed
       
  1138 }
       
  1139 
       
  1140 HbSmileyEngine* HbAbstractEditPrivate::smileyEngineInstance() const
       
  1141 {
       
  1142     Q_Q(const HbAbstractEdit);
       
  1143     if(smileyEngine == 0) {
       
  1144         smileyEngine = new HbSmileyEngine(const_cast <HbAbstractEdit*>(q));
       
  1145         smileyEngine->setDocument(doc);
       
  1146 
       
  1147         HbEditorInterface editorInterface(const_cast<HbAbstractEdit*>(q));
       
  1148 
       
  1149         if(smileysEnabled) {
       
  1150             editorInterface.setSmileyTheme(smileyEngine->theme());
       
  1151         } else {
       
  1152             editorInterface.setSmileyTheme(HbSmileyTheme());
       
  1153         }
       
  1154     }
       
  1155     return smileyEngine;
       
  1156 }
       
  1157 
       
  1158 Qt::Alignment HbAbstractEditPrivate::alignmentFromString(const QString &text)
       
  1159 {
       
  1160     Qt::Alignment align(0);
       
  1161     static const struct {
       
  1162         Qt::Alignment align;
       
  1163         const char* pattern;
       
  1164     } stringToAlign[] = {
       
  1165         { Qt::AlignLeft,      "\\bleft\\b" },
       
  1166         { Qt::AlignRight,     "\\bright\\b" },
       
  1167         { Qt::AlignHCenter,   "\\bhcenter\\b" },
       
  1168         { Qt::AlignAbsolute,  "\\babsolute\\b" },
       
  1169         { Qt::AlignJustify,   "\\bjustify\\b" },
       
  1170         { Qt::AlignTop,       "\\btop\\b" },
       
  1171         { Qt::AlignBottom,    "\\bbottom\\b" },
       
  1172         { Qt::AlignVCenter,   "\\bvcenter\\b" },
       
  1173         { Qt::AlignCenter,    "\\bcenter\\b" }
       
  1174     };
       
  1175     static const int count = sizeof(stringToAlign)/sizeof(stringToAlign[0]);
       
  1176 
       
  1177 
       
  1178     QRegExp regExp;
       
  1179     regExp.setCaseSensitivity(Qt::CaseInsensitive);
       
  1180 
       
  1181     for(int i=0; i<count; ++i) {
       
  1182         regExp.setPattern(stringToAlign[i].pattern);
       
  1183         if(text.indexOf(regExp)>=0) {
       
  1184             align |= stringToAlign[i].align;
       
  1185         }
       
  1186     }
       
  1187     return align;
       
  1188 }
       
  1189 
       
  1190 // Send open input panel event.
       
  1191 void HbAbstractEditPrivate::sendInputPanelEvent(QEvent::Type type)
       
  1192 {
       
  1193 #if QT_VERSION >= 0x040600
       
  1194     QInputContext *ic = qApp->inputContext();
       
  1195     if (ic) {
       
  1196         QEvent *openEvent = new QEvent(type);
       
  1197         ic->filterEvent(openEvent);
       
  1198         delete openEvent;
       
  1199     }
       
  1200 #endif
       
  1201 }
       
  1202 
       
  1203 // Send open input panel event.
       
  1204 void HbAbstractEditPrivate::openInputPanel()
       
  1205 {
       
  1206     sendInputPanelEvent(QEvent::RequestSoftwareInputPanel);
       
  1207 }
       
  1208 
       
  1209 // Send close input panel event.
       
  1210 void HbAbstractEditPrivate::closeInputPanel()
       
  1211 {
       
  1212     sendInputPanelEvent(QEvent::CloseSoftwareInputPanel);
       
  1213 }
       
  1214 
       
  1215 #include "hbinputeditorinterface.h"
       
  1216 #include "hbinputvkbhost.h"
       
  1217 
       
  1218 void HbAbstractEditPrivate::minimizeInputPanel()
       
  1219 {
       
  1220     Q_Q(HbAbstractEdit);
       
  1221 
       
  1222     HbEditorInterface ei(q);
       
  1223     HbVkbHost* vkbHost = ei.vkbHost();
       
  1224     vkbHost->minimizeKeypad();
       
  1225 }
       
  1226 
       
  1227 #include "moc_hbabstractedit.cpp"