ginebra2/TextEditItem.cpp
changeset 5 0f2326c2a325
parent 0 1450b09d0cfd
equal deleted inserted replaced
1:b0dd75e285d2 5:0f2326c2a325
     1 /*
     1 /*
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     4 *
     5 * under the terms of "Eclipse Public License v1.0"
     5 * This program is free software: you can redistribute it and/or modify
     6 * which accompanies this distribution, and is available
     6 * it under the terms of the GNU Lesser General Public License as published by
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 * the Free Software Foundation, version 2.1 of the License.
     8 *
     8 *
     9 * Initial Contributors:
     9 * This program is distributed in the hope that it will be useful,
    10 * Nokia Corporation - initial contribution.
    10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11 *
    11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12 * Contributors:
    12 * GNU Lesser General Public License for more details.
    13 *
    13 *
    14 * Description: 
    14 * You should have received a copy of the GNU Lesser General Public License
       
    15 * along with this program.  If not,
       
    16 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
    17 *
       
    18 * Description:
    15 *
    19 *
    16 */
    20 */
    17 
       
    18 
    21 
    19 #include <QGraphicsTextItem>
    22 #include <QGraphicsTextItem>
    20 #include "TextEditItem.h"
    23 #include "TextEditItem.h"
    21 #include "ChromeSnippet.h"
    24 #include "ChromeSnippet.h"
    22 #include "GreenChromeSnippet.h"
       
    23 
    25 
    24 namespace GVA {
    26 namespace GVA {
    25   EditorWidget::EditorWidget(QGraphicsItem * parent)
    27   EditorWidget::EditorWidget(QGraphicsItem * parent)
    26     : QGraphicsTextItem(parent)
    28     : QGraphicsTextItem(parent)
    27   {
    29   {
    40   // The editor document signals cursor movements when the document modified (because characters
    42   // The editor document signals cursor movements when the document modified (because characters
    41   // are being added or removed, but not when the cursor is simply being moved. Also, the
    43   // are being added or removed, but not when the cursor is simply being moved. Also, the
    42   // document's idea of cursor position is based on the character count, not the actual pixel
    44   // document's idea of cursor position is based on the character count, not the actual pixel
    43   // position. To implement scrolling, we need our own cursor change event that supplies the
    45   // position. To implement scrolling, we need our own cursor change event that supplies the
    44   // pixel change in all cases.
    46   // pixel change in all cases.
    45   
    47 
    46   void EditorWidget::keyPressEvent(QKeyEvent *event)
    48   void EditorWidget::keyPressEvent(QKeyEvent *event)
    47   {   
    49   {
    48     qreal oldX = cursorX();
    50     qreal oldX = cursorX();
    49     QGraphicsTextItem::keyPressEvent(event);
    51     QGraphicsTextItem::keyPressEvent(event);
    50     emit cursorXChanged(cursorX(), oldX);
    52     emit cursorXChanged(cursorX(), oldX);
    51   }
    53   }
    52  
    54 
    53   void EditorWidget::setText(const QString& text, bool html)
    55   void EditorWidget::setText(const QString& text, bool html)
    54   {
    56   {
    55     if(html)
    57     if (html)
    56       setHtml(text);
    58       setHtml(text);
    57     else
    59     else
    58       setPlainText(text);
    60       setPlainText(text);
    59     //All this just to get the first (and only) text line of the document!
    61     //All this just to get the first (and only) text line of the document!
    60     m_textLine = document()->begin().layout()->lineForTextPosition(0);
    62     m_textLine = document()->begin().layout()->lineForTextPosition(0);
    77     m_viewPort->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
    79     m_viewPort->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
    78     //The actual text editor item
    80     //The actual text editor item
    79     m_editor = new EditorWidget(m_viewPort);
    81     m_editor = new EditorWidget(m_viewPort);
    80     m_cursor = m_editor->textCursor();
    82     m_cursor = m_editor->textCursor();
    81     connect(m_editor, SIGNAL(cursorXChanged(qreal, qreal)), this, SLOT(onCursorXChanged(qreal, qreal)));
    83     connect(m_editor, SIGNAL(cursorXChanged(qreal, qreal)), this, SLOT(onCursorXChanged(qreal, qreal)));
    82  
    84 
    83     //Force the editor to be a single text line 
    85     //Force the editor to be a single text line
    84     m_textOption = m_editor->document()->defaultTextOption();
    86     m_textOption = m_editor->document()->defaultTextOption();
    85     m_textOption.setWrapMode(QTextOption::NoWrap);
    87     m_textOption.setWrapMode(QTextOption::NoWrap);
    86     m_editor->document()->setDefaultTextOption(m_textOption);
    88     m_editor->document()->setDefaultTextOption(m_textOption);
    87     
    89 
    88     //Not exactly well-documented, but this flag is needed to make cursor keys work
    90     //Not exactly well-documented, but this flag is needed to make cursor keys work
    89     m_editor->setTextInteractionFlags(Qt::TextEditorInteraction);
    91     m_editor->setTextInteractionFlags(Qt::TextEditorInteraction);
    90 
    92 
    91     //Non-default key handling for scrolling, etc.
    93     //Non-default key handling for scrolling, etc.
    92     m_editor->installEventFilter(this);
    94     m_editor->installEventFilter(this);
    93  
    95 
    94     //Set text and background colors from element css
    96     //Set text and background colors from element css
    95     QString cssVal = m_snippet->element().styleProperty("color", QWebElement::ComputedStyle);
    97     QString cssVal = m_snippet->element().styleProperty("color", QWebElement::ComputedStyle);
    96     CSSToQColor(cssVal, m_textColor);
    98     CSSToQColor(cssVal, m_textColor);
    97     m_editor->setDefaultTextColor(m_textColor);
    99     m_editor->setDefaultTextColor(m_textColor);
    98     cssVal = m_snippet->element().styleProperty("background-color", QWebElement::ComputedStyle);
   100     cssVal = m_snippet->element().styleProperty("background-color", QWebElement::ComputedStyle);
   119 
   121 
   120   TextEditItem::~TextEditItem()
   122   TextEditItem::~TextEditItem()
   121   {
   123   {
   122     delete m_editor;
   124     delete m_editor;
   123   }
   125   }
   124   
   126 
   125   void TextEditItem::resizeEvent(QGraphicsSceneResizeEvent * ev)
   127   void TextEditItem::resizeEvent(QGraphicsSceneResizeEvent * ev)
   126   {
   128   {
   127     NativeChromeItem::resizeEvent(ev);
   129     NativeChromeItem::resizeEvent(ev);
   128     m_viewPortWidth = boundingRect().width()-m_padding*2;
   130     m_viewPortWidth = boundingRect().width()-m_padding*2;
   129     m_viewPort->setGeometry(m_padding,(boundingRect().height()-m_editor->boundingRect().height())/2,m_viewPortWidth, m_editor->boundingRect().height() );
   131     m_viewPort->setGeometry(m_padding,(boundingRect().height()-m_editor->boundingRect().height())/2,m_viewPortWidth, m_editor->boundingRect().height() );
   130     m_editor->setTextWidth(m_viewPortWidth);
   132     m_editor->setTextWidth(m_viewPortWidth);
   131     //Make a rectangular background with a cut-out for the text. The width of the surrounding
   133     //Make a rectangular background with a cut-out for the text. The width of the surrounding
   132     //background is set by padding 
   134     //background is set by padding
   133     m_background.addRect(boundingRect());
   135     m_background.addRect(boundingRect());
   134     m_background.addRoundedRect(m_padding, m_padding, m_viewPortWidth, boundingRect().height()-m_padding*2,4,4);
   136     m_background.addRoundedRect(m_padding, m_padding, m_viewPortWidth, boundingRect().height()-m_padding*2,4,4);
   135  }
   137  }
   136 
   138 
   137   //Filter key events to emit activate signal absorb up, down keys
   139   //Filter key events to emit activate signal absorb up, down keys
   138 
   140 
   139   bool TextEditItem::eventFilter(QObject * obj, QEvent *ev)
   141   bool TextEditItem::eventFilter(QObject * obj, QEvent *ev)
   140   {
   142   {
   141     if(obj == m_editor){
   143     if (obj == m_editor){
   142       if(ev->type() == QEvent::KeyPress){
   144       if (ev->type() == QEvent::KeyPress){
   143 	QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
   145     QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
   144 	if(keyEvent->key() == Qt::Key_Select || keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
   146     if (keyEvent->key() == Qt::Key_Select || keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
   145           //Signal that a carriage return-like key-press happened
   147           //Signal that a carriage return-like key-press happened
   146 	  emit activated();
   148       emit activated();
   147 	  return true;
   149       return true;
   148 	}
   150     }
   149 	if(keyEvent->key() == Qt::Key_Down || keyEvent->key() == Qt::Key_Up)
   151     if (keyEvent->key() == Qt::Key_Down || keyEvent->key() == Qt::Key_Up)
   150 	  return true;
   152       return true;
   151         //Otherwise, pass keypress to the text editor
   153         //Otherwise, pass keypress to the text editor
   152 	return false;
   154     return false;
   153       }
   155       }
   154     }
   156     }
   155     return NativeChromeItem::eventFilter(obj, ev);
   157     return NativeChromeItem::eventFilter(obj, ev);
   156   }
   158   }
   157 
   159 
   158   void TextEditItem::internalScroll(qreal deltaX)
   160   void TextEditItem::internalScroll(qreal deltaX)
   159   {
   161   {
   160     if(deltaX > -m_scrollPos)
   162     if (deltaX > -m_scrollPos)
   161       m_editor->moveBy(-m_scrollPos,0);
   163       m_editor->moveBy(-m_scrollPos,0);
   162     else
   164     else
   163       m_editor->moveBy(deltaX,0);
   165       m_editor->moveBy(deltaX,0);
   164     m_scrollPos = m_editor->pos().x();
   166     m_scrollPos = m_editor->pos().x();
   165   }
   167   }
   169   //inserting! Rewrite as state machine?
   171   //inserting! Rewrite as state machine?
   170 
   172 
   171   void TextEditItem::onCursorXChanged(qreal newX, qreal oldX)
   173   void TextEditItem::onCursorXChanged(qreal newX, qreal oldX)
   172   {
   174   {
   173     qreal oldTextWidth = m_textWidth;
   175     qreal oldTextWidth = m_textWidth;
   174     m_textWidth = m_editor->document()->size().width(); 
   176     m_textWidth = m_editor->document()->size().width();
   175     if(oldTextWidth == 0)
   177     if (oldTextWidth == 0)
   176 	return;
   178     return;
   177     qreal textDelta = m_textWidth - oldTextWidth;
   179     qreal textDelta = m_textWidth - oldTextWidth;
   178     qreal deltaX = oldX - newX;
   180     qreal deltaX = oldX - newX;
   179     //Just moving the cursor, slide window as needed
   181     //Just moving the cursor, slide window as needed
   180     if(textDelta == 0){
   182     if (textDelta == 0){
   181       //NB: Currently slides by one character, in some browsers slides by multiple characters
   183       //NB: Currently slides by one character, in some browsers slides by multiple characters
   182       if((newX <= -m_scrollPos)||(newX >= (m_viewPortWidth - m_scrollPos))){
   184       if ((newX <= -m_scrollPos)||(newX >= (m_viewPortWidth - m_scrollPos))){
   183 	internalScroll(deltaX);
   185     internalScroll(deltaX);
   184       }
   186       }
   185     }
   187     }
   186     //Inserting characters
   188     //Inserting characters
   187     else if (textDelta > 0){
   189     else if (textDelta > 0){
   188       if(newX >= (m_viewPortWidth - m_scrollPos)){
   190       if (newX >= (m_viewPortWidth - m_scrollPos)){
   189         internalScroll(deltaX);
   191         internalScroll(deltaX);
   190       }
   192       }
   191     }
   193     }
   192     //Deleting characters. 
   194     //Deleting characters.
   193     else {
   195     else {
   194       if(m_scrollPos < 0){
   196       if (m_scrollPos < 0){
   195         //Delete may be a selected block, in which case the cursor movement may be
   197         //Delete may be a selected block, in which case the cursor movement may be
   196         //different from the text delta.
   198         //different from the text delta.
   197         internalScroll(-textDelta);
   199         internalScroll(-textDelta);
   198       }
   200       }
   199     }
   201     }
   205     NativeChromeItem::paint(painter, option,widget);
   207     NativeChromeItem::paint(painter, option,widget);
   206     QPainterPath path;
   208     QPainterPath path;
   207     painter->save();
   209     painter->save();
   208     painter->setRenderHint(QPainter::Antialiasing);
   210     painter->setRenderHint(QPainter::Antialiasing);
   209     painter->setBrush(m_backgroundColor);
   211     painter->setBrush(m_backgroundColor);
   210     if(m_border > 0){
   212     if (m_border > 0){
   211       QPen pen;
   213       QPen pen;
   212       pen.setWidth(m_border);
   214       pen.setWidth(m_border);
   213       pen.setBrush(m_borderColor);
   215       pen.setBrush(m_borderColor);
   214       painter->setPen(pen);
   216       painter->setPen(pen);
   215     }
   217     }
   220   //NB: Move these slots to the containing snippet so they can be exported to JS
   222   //NB: Move these slots to the containing snippet so they can be exported to JS
   221 
   223 
   222   QString TextEditItem::text(){
   224   QString TextEditItem::text(){
   223     return m_editor->toPlainText();
   225     return m_editor->toPlainText();
   224   }
   226   }
   225   
   227 
   226   void TextEditItem::setText(const QString & text){
   228   void TextEditItem::setText(const QString & text){
   227     m_editor->setText(text);
   229     m_editor->setText(text);
   228   }
   230   }
   229 
   231 
   230 }
   232 }