messagingapp/msgui/unifiededitor/src/msgunifiededitorlineedit.cpp
changeset 23 238255e8b033
child 25 84d9eb65b26f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingapp/msgui/unifiededitor/src/msgunifiededitorlineedit.cpp	Fri Apr 16 14:56:15 2010 +0300
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:
+ *
+ */
+
+#include <QGraphicsSceneMouseEvent>
+#include "msgunifiededitorlineedit.h"
+
+const QRegExp expr("[,;\n]$");
+const QRegExp sepAtEnd("; $");
+const QRegExp sepAtMiddle("; ");
+
+const QString replacementStr("; ");
+const QString labelSeperator(": ");
+
+const int fadedAlpha(125);
+const int solidAlpha(255);
+
+const int SNAP_DELAY = 350;
+
+MsgUnifiedEditorLineEdit::MsgUnifiedEditorLineEdit(const QString& label,QGraphicsItem *parent):
+HbLineEdit(parent),
+mSelectionStart(-1),
+mSelectionEnd(-1)
+{
+    QTextCursor cursor(this->textCursor());
+    QTextCharFormat colorFormat(cursor.charFormat());
+   
+    QColor fgColor = colorFormat.foreground().color();     
+    fgColor.setAlpha(fadedAlpha);
+    colorFormat.setForeground(fgColor);
+    cursor.insertText(label , colorFormat);
+
+    fgColor.setAlpha(solidAlpha);
+    colorFormat.setForeground(fgColor);
+
+    cursor.insertText(" ",colorFormat);    
+
+    mLabelExpr.setPattern(QString("^"+label+" $"));
+    mLabel = label+" ";
+
+    connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
+            this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
+    connect(this, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
+}
+
+MsgUnifiedEditorLineEdit::~MsgUnifiedEditorLineEdit()
+{
+}
+
+void MsgUnifiedEditorLineEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+    if (!event->commitString().isEmpty() || event->replacementLength())
+    {
+        if (event->commitString().contains(expr))
+        {
+            if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
+            {
+                event->accept();
+                return;
+            }
+
+            this->setCursorPosition(this->text().length());
+
+            QString str = event->commitString();
+            str.replace(expr, replacementStr);            
+
+            event->setCommitString(str, event->replacementStart(), event->replacementLength());            
+        }
+        else if(this->hasSelectedText())
+        {// all user inputs get appended at the end
+            this->setCursorPosition(this->text().length());
+        }
+
+        HbAbstractEdit::inputMethodEvent(event);
+        event->accept();
+    }
+}
+
+void MsgUnifiedEditorLineEdit::keyPressEvent(QKeyEvent *event)
+{
+    QString str = event->text();
+
+    if(event->key()== Qt::Key_Enter || event->key()== Qt::Key_Return)
+    {
+        if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
+        {
+            event->accept();
+            return;
+        }
+        this->setCursorPosition(this->text().length());
+        str = replacementStr;
+        QKeyEvent eve(event->type(), Qt::Key_Any, event->modifiers(), str);
+        HbAbstractEdit::keyPressEvent(&eve);
+        event->accept();
+        return;
+    }
+
+    if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete )
+    {
+        int pos = this->cursorPosition();
+        bool pbkContact = true;
+
+        if(!this->hasSelectedText())
+        {
+            this->setCursorPosition(pos-2);
+            pbkContact = this->textCursor().charFormat().fontUnderline();
+            this->setCursorPosition(pos);
+        }
+
+        QString text = this->text();
+        text = text.left(pos);
+
+        if(text.contains(mLabelExpr))
+        {
+            event->accept();
+            return;
+        }
+
+        if(pbkContact)
+        {
+            //if already selected delete it.
+            if(this->hasSelectedText())
+            {
+                HbLineEdit::keyPressEvent(event);
+                event->accept();
+
+                //delete seperator (i.e."; ").
+                QKeyEvent eve(event->type(), Qt::Key_Delete, Qt::NoModifier);
+                HbLineEdit::keyPressEvent(&eve);
+                HbLineEdit::keyPressEvent(&eve);
+
+            }
+            else //make it selected
+            {                
+                this->setCursorPosition(pos-3);
+                setHighlight(pos-3);
+            }
+        }
+        else
+        {
+            QString str = text.right(2);
+            if(str == replacementStr)
+            {
+                //delete seperator (i.e."; ").
+                QKeyEvent eve(event->type(), Qt::Key_Backspace, Qt::NoModifier);
+                HbLineEdit::keyPressEvent(&eve);
+                HbLineEdit::keyPressEvent(&eve);
+            }
+            else
+            {
+                HbLineEdit::keyPressEvent(event);
+            }
+            event->accept();
+        }
+        
+        event->accept();
+        return;
+
+    }
+
+    if (event->key() == Qt::Key_Left )
+    {
+        bool selectedText = this->hasSelectedText();
+
+        //look ahead left.
+        int pos = this->cursorPosition();
+
+        QString text = this->text();
+        text = text.left(pos);
+
+        //no text other than label;
+        if(text.contains(mLabelExpr))
+        {
+            event->accept();
+            return;
+        }
+
+        //look for next seperator while going left.
+        int newPos = text.lastIndexOf(sepAtMiddle);
+
+        if(newPos < 0 && selectedText)
+        {
+            event->accept();
+            return;
+        }
+
+        bool pbkContact = true;
+
+        if(!selectedText)
+        {
+            this->setCursorPosition(pos-2);
+            pbkContact = this->textCursor().charFormat().fontUnderline();
+            this->setCursorPosition(pos);
+        }
+        else
+        {
+            this->setCursorPosition(newPos);
+            pbkContact = this->textCursor().charFormat().fontUnderline();
+            this->setCursorPosition(pos);
+        }
+
+
+        if(pbkContact && newPos >0)
+        {
+
+            setHighlight(newPos-1);
+        }
+        else
+        {
+            //move left, char by char. if seperator met jump over it.
+            if( (newPos > 0 && selectedText) || (pos-2  == newPos))
+            {
+                this->setCursorPosition(newPos+1);
+            }
+
+            HbLineEdit::keyPressEvent(event);
+
+        }
+        event->accept();
+        return;
+    }
+
+    if (event->key() == Qt::Key_Right)
+    {
+        bool selectedText = this->hasSelectedText();
+
+        //look ahead.
+        int pos = this->cursorPosition();
+        this->setCursorPosition(pos+3);
+        bool pbkContact = this->textCursor().charFormat().fontUnderline();
+        this->setCursorPosition(pos);
+
+        //look for next seperator.
+        QString text = this->text();
+        int newPos = text.indexOf(sepAtMiddle,pos+2);
+
+        if(pbkContact && newPos >0)
+        {
+            this->setCursorPosition(newPos-1);
+            setHighlight(newPos-1);
+        }
+        else
+        {            
+            int seperatorPos = text.indexOf(sepAtMiddle,pos);
+
+            if(selectedText || seperatorPos == pos)
+            {
+                this->setCursorPosition(pos+1);
+                this->deselect();
+            }
+            HbAbstractEdit::keyPressEvent(event);
+        }
+        event->accept();
+        return;
+    }
+
+    if(!str.isEmpty())
+    {
+        if (str.contains(expr))
+        {
+            if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
+            {
+                event->accept();
+                return;
+            }
+
+            // auto-complete the last incomplete word
+            int contentLength = this->text().length();
+            int pos = this->cursorPosition();
+            QString incompleteWord(this->text().right(contentLength-(pos-1)));
+            if(!incompleteWord.contains(sepAtMiddle))
+            {
+                this->setCursorPosition(this->text().length());
+            }
+
+            str.replace(expr, replacementStr);
+            QKeyEvent eve(event->type(), event->key(), event->modifiers(), str);
+            HbAbstractEdit::keyPressEvent(&eve);
+        }
+        else
+        {
+            HbAbstractEdit::keyPressEvent(event);
+            event->accept();
+            return;
+        }
+    }
+}
+
+void MsgUnifiedEditorLineEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+    HbAbstractEdit::mouseReleaseEvent(event);
+
+    int currentPos = this->cursorPosition();
+
+    QString txt = this->text();
+
+    QString tempTxt = txt.left(currentPos+2);
+    int seperatorPos = tempTxt.lastIndexOf(sepAtMiddle,currentPos);
+
+    txt = txt.right(txt.length() - currentPos);
+    int labelPos = txt.indexOf(labelSeperator);
+
+    if(labelPos >= 0 )//pressed on label.
+    {
+        this->setCursorPosition(currentPos + labelPos + 2);
+    }
+    else if(seperatorPos == currentPos-1 || seperatorPos == currentPos)//pressed just on seperator.
+    {
+        this->setCursorPosition(seperatorPos+2);
+    }
+    else
+    {
+        this->setCursorPosition(currentPos+1);
+        bool pbkContact = this->textCursor().charFormat().fontUnderline();
+        if(pbkContact)
+        {
+            setHighlight(currentPos);
+        }
+    }
+
+    this->update();
+    event->accept();
+}
+
+void MsgUnifiedEditorLineEdit::setText(const QString& text)
+{
+    QInputMethodEvent e;
+    //make sure previous text is complete.
+    e.setCommitString(";");
+    this->inputMethodEvent(&e);
+    this->setCursorPosition(this->text().length());
+
+    QTextCursor cursor(this->textCursor());
+    QTextCharFormat colorFormat(cursor.charFormat());
+    QColor fgColor = colorFormat.foreground().color();     
+    fgColor.setAlpha(fadedAlpha);
+    colorFormat.setUnderlineColor(fgColor);
+
+    colorFormat.setFontUnderline(true);  
+    cursor.insertText(text , colorFormat);
+    colorFormat.setFontUnderline(false);
+    
+    cursor.insertText(replacementStr,colorFormat);
+    
+    this->setCursorVisibility(Hb::TextCursorHidden);
+}
+
+QStringList MsgUnifiedEditorLineEdit::addresses()
+{    
+    QString text = this->text();
+    text = text.remove(mLabel);
+    QStringList list = text.split(replacementStr,QString::SkipEmptyParts);
+    //list.removeDuplicates();
+    return list;
+}
+
+void MsgUnifiedEditorLineEdit::focusInEvent(QFocusEvent* event)
+{    
+    HbAbstractEdit::focusInEvent(event);
+    this->setCursorVisibility(Hb::TextCursorVisible);
+}
+
+void MsgUnifiedEditorLineEdit::setHighlight(int currentPos)
+{
+    QString txt = this->text();    
+
+    int endPos = qMax(txt.indexOf(sepAtMiddle,currentPos),
+                      txt.indexOf(labelSeperator,currentPos));
+
+    int startPos = qMax(txt.lastIndexOf(sepAtMiddle,currentPos),
+                        txt.lastIndexOf(labelSeperator,currentPos));
+
+    disconnect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
+               this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
+
+    //highlight if pbk contact.
+    if(startPos > 0 && endPos > 0 && startPos != endPos)
+    {
+        this->setSelection(startPos + 2, endPos - startPos - 2);
+        this->update();
+    }
+    else
+    {
+        this->deselect();
+    }
+
+    this->update();
+
+    connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
+            this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
+}
+
+void MsgUnifiedEditorLineEdit::cut()
+{
+    HbLineEdit::cut();
+    //after cut delete seperator (i.e."; ").
+    QKeyEvent eve(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
+    HbLineEdit::keyPressEvent(&eve);
+    HbLineEdit::keyPressEvent(&eve);
+}
+
+void MsgUnifiedEditorLineEdit::selectAll()
+{
+    //don't allow user to select every thing.
+    //do nothing.
+}
+
+void MsgUnifiedEditorLineEdit::selectionChanged(const QTextCursor &oldCursor, const QTextCursor& newCursor)
+{
+
+    if(mSelectionSnapTimer.isActive())
+    {
+        mSelectionSnapTimer.stop();
+    }
+
+    if(newCursor.selectionStart() < mLabel.length())
+    {
+        this->setTextCursor(oldCursor);
+        return;
+    }
+
+    mSelectionStart  = newCursor.selectionStart();
+    mSelectionEnd    = newCursor.selectionEnd();
+
+    if(mSelectionStart == mSelectionEnd )
+    {
+        return;
+    }
+
+    mSelectionSnapTimer.start(SNAP_DELAY,this);
+
+}
+
+void MsgUnifiedEditorLineEdit::timerEvent(QTimerEvent *event)
+{
+    //passing event to base class.
+    HbLineEdit::timerEvent(event);
+
+    if (event->timerId() == mSelectionSnapTimer.timerId())
+    {
+        mSelectionSnapTimer.stop();
+
+        disconnect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
+                   this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
+
+        QString txt = this->text();
+
+        int startPos = qMax(txt.lastIndexOf(sepAtMiddle,mSelectionStart),
+                            txt.lastIndexOf(labelSeperator,mSelectionStart));
+
+        int endPos = qMax(txt.indexOf(sepAtMiddle,mSelectionEnd),
+                          txt.indexOf(labelSeperator,mSelectionEnd));
+
+        if(endPos < 0 )
+        {
+            endPos = mSelectionEnd;
+        }
+
+        this->setSelection(startPos + 2, endPos - startPos - 2);
+
+        connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
+                this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
+
+        event->accept();
+    }
+}
+
+void MsgUnifiedEditorLineEdit::onTextChanged(const QString& text)
+{
+    const QString changedText = const_cast<QString&>(text).remove(mLabel);
+    emit addressTextChanged(changedText);
+}
+
+// eof