messagingapp/msgui/unifiededitor/src/msgunifiededitorlineedit.cpp
changeset 23 238255e8b033
child 25 84d9eb65b26f
equal deleted inserted replaced
5:4697dfb2d7ad 23:238255e8b033
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:
       
    15  *
       
    16  */
       
    17 
       
    18 #include <QGraphicsSceneMouseEvent>
       
    19 #include "msgunifiededitorlineedit.h"
       
    20 
       
    21 const QRegExp expr("[,;\n]$");
       
    22 const QRegExp sepAtEnd("; $");
       
    23 const QRegExp sepAtMiddle("; ");
       
    24 
       
    25 const QString replacementStr("; ");
       
    26 const QString labelSeperator(": ");
       
    27 
       
    28 const int fadedAlpha(125);
       
    29 const int solidAlpha(255);
       
    30 
       
    31 const int SNAP_DELAY = 350;
       
    32 
       
    33 MsgUnifiedEditorLineEdit::MsgUnifiedEditorLineEdit(const QString& label,QGraphicsItem *parent):
       
    34 HbLineEdit(parent),
       
    35 mSelectionStart(-1),
       
    36 mSelectionEnd(-1)
       
    37 {
       
    38     QTextCursor cursor(this->textCursor());
       
    39     QTextCharFormat colorFormat(cursor.charFormat());
       
    40    
       
    41     QColor fgColor = colorFormat.foreground().color();     
       
    42     fgColor.setAlpha(fadedAlpha);
       
    43     colorFormat.setForeground(fgColor);
       
    44     cursor.insertText(label , colorFormat);
       
    45 
       
    46     fgColor.setAlpha(solidAlpha);
       
    47     colorFormat.setForeground(fgColor);
       
    48 
       
    49     cursor.insertText(" ",colorFormat);    
       
    50 
       
    51     mLabelExpr.setPattern(QString("^"+label+" $"));
       
    52     mLabel = label+" ";
       
    53 
       
    54     connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
       
    55             this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
       
    56     connect(this, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
       
    57 }
       
    58 
       
    59 MsgUnifiedEditorLineEdit::~MsgUnifiedEditorLineEdit()
       
    60 {
       
    61 }
       
    62 
       
    63 void MsgUnifiedEditorLineEdit::inputMethodEvent(QInputMethodEvent *event)
       
    64 {
       
    65     if (!event->commitString().isEmpty() || event->replacementLength())
       
    66     {
       
    67         if (event->commitString().contains(expr))
       
    68         {
       
    69             if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
       
    70             {
       
    71                 event->accept();
       
    72                 return;
       
    73             }
       
    74 
       
    75             this->setCursorPosition(this->text().length());
       
    76 
       
    77             QString str = event->commitString();
       
    78             str.replace(expr, replacementStr);            
       
    79 
       
    80             event->setCommitString(str, event->replacementStart(), event->replacementLength());            
       
    81         }
       
    82         else if(this->hasSelectedText())
       
    83         {// all user inputs get appended at the end
       
    84             this->setCursorPosition(this->text().length());
       
    85         }
       
    86 
       
    87         HbAbstractEdit::inputMethodEvent(event);
       
    88         event->accept();
       
    89     }
       
    90 }
       
    91 
       
    92 void MsgUnifiedEditorLineEdit::keyPressEvent(QKeyEvent *event)
       
    93 {
       
    94     QString str = event->text();
       
    95 
       
    96     if(event->key()== Qt::Key_Enter || event->key()== Qt::Key_Return)
       
    97     {
       
    98         if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
       
    99         {
       
   100             event->accept();
       
   101             return;
       
   102         }
       
   103         this->setCursorPosition(this->text().length());
       
   104         str = replacementStr;
       
   105         QKeyEvent eve(event->type(), Qt::Key_Any, event->modifiers(), str);
       
   106         HbAbstractEdit::keyPressEvent(&eve);
       
   107         event->accept();
       
   108         return;
       
   109     }
       
   110 
       
   111     if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete )
       
   112     {
       
   113         int pos = this->cursorPosition();
       
   114         bool pbkContact = true;
       
   115 
       
   116         if(!this->hasSelectedText())
       
   117         {
       
   118             this->setCursorPosition(pos-2);
       
   119             pbkContact = this->textCursor().charFormat().fontUnderline();
       
   120             this->setCursorPosition(pos);
       
   121         }
       
   122 
       
   123         QString text = this->text();
       
   124         text = text.left(pos);
       
   125 
       
   126         if(text.contains(mLabelExpr))
       
   127         {
       
   128             event->accept();
       
   129             return;
       
   130         }
       
   131 
       
   132         if(pbkContact)
       
   133         {
       
   134             //if already selected delete it.
       
   135             if(this->hasSelectedText())
       
   136             {
       
   137                 HbLineEdit::keyPressEvent(event);
       
   138                 event->accept();
       
   139 
       
   140                 //delete seperator (i.e."; ").
       
   141                 QKeyEvent eve(event->type(), Qt::Key_Delete, Qt::NoModifier);
       
   142                 HbLineEdit::keyPressEvent(&eve);
       
   143                 HbLineEdit::keyPressEvent(&eve);
       
   144 
       
   145             }
       
   146             else //make it selected
       
   147             {                
       
   148                 this->setCursorPosition(pos-3);
       
   149                 setHighlight(pos-3);
       
   150             }
       
   151         }
       
   152         else
       
   153         {
       
   154             QString str = text.right(2);
       
   155             if(str == replacementStr)
       
   156             {
       
   157                 //delete seperator (i.e."; ").
       
   158                 QKeyEvent eve(event->type(), Qt::Key_Backspace, Qt::NoModifier);
       
   159                 HbLineEdit::keyPressEvent(&eve);
       
   160                 HbLineEdit::keyPressEvent(&eve);
       
   161             }
       
   162             else
       
   163             {
       
   164                 HbLineEdit::keyPressEvent(event);
       
   165             }
       
   166             event->accept();
       
   167         }
       
   168         
       
   169         event->accept();
       
   170         return;
       
   171 
       
   172     }
       
   173 
       
   174     if (event->key() == Qt::Key_Left )
       
   175     {
       
   176         bool selectedText = this->hasSelectedText();
       
   177 
       
   178         //look ahead left.
       
   179         int pos = this->cursorPosition();
       
   180 
       
   181         QString text = this->text();
       
   182         text = text.left(pos);
       
   183 
       
   184         //no text other than label;
       
   185         if(text.contains(mLabelExpr))
       
   186         {
       
   187             event->accept();
       
   188             return;
       
   189         }
       
   190 
       
   191         //look for next seperator while going left.
       
   192         int newPos = text.lastIndexOf(sepAtMiddle);
       
   193 
       
   194         if(newPos < 0 && selectedText)
       
   195         {
       
   196             event->accept();
       
   197             return;
       
   198         }
       
   199 
       
   200         bool pbkContact = true;
       
   201 
       
   202         if(!selectedText)
       
   203         {
       
   204             this->setCursorPosition(pos-2);
       
   205             pbkContact = this->textCursor().charFormat().fontUnderline();
       
   206             this->setCursorPosition(pos);
       
   207         }
       
   208         else
       
   209         {
       
   210             this->setCursorPosition(newPos);
       
   211             pbkContact = this->textCursor().charFormat().fontUnderline();
       
   212             this->setCursorPosition(pos);
       
   213         }
       
   214 
       
   215 
       
   216         if(pbkContact && newPos >0)
       
   217         {
       
   218 
       
   219             setHighlight(newPos-1);
       
   220         }
       
   221         else
       
   222         {
       
   223             //move left, char by char. if seperator met jump over it.
       
   224             if( (newPos > 0 && selectedText) || (pos-2  == newPos))
       
   225             {
       
   226                 this->setCursorPosition(newPos+1);
       
   227             }
       
   228 
       
   229             HbLineEdit::keyPressEvent(event);
       
   230 
       
   231         }
       
   232         event->accept();
       
   233         return;
       
   234     }
       
   235 
       
   236     if (event->key() == Qt::Key_Right)
       
   237     {
       
   238         bool selectedText = this->hasSelectedText();
       
   239 
       
   240         //look ahead.
       
   241         int pos = this->cursorPosition();
       
   242         this->setCursorPosition(pos+3);
       
   243         bool pbkContact = this->textCursor().charFormat().fontUnderline();
       
   244         this->setCursorPosition(pos);
       
   245 
       
   246         //look for next seperator.
       
   247         QString text = this->text();
       
   248         int newPos = text.indexOf(sepAtMiddle,pos+2);
       
   249 
       
   250         if(pbkContact && newPos >0)
       
   251         {
       
   252             this->setCursorPosition(newPos-1);
       
   253             setHighlight(newPos-1);
       
   254         }
       
   255         else
       
   256         {            
       
   257             int seperatorPos = text.indexOf(sepAtMiddle,pos);
       
   258 
       
   259             if(selectedText || seperatorPos == pos)
       
   260             {
       
   261                 this->setCursorPosition(pos+1);
       
   262                 this->deselect();
       
   263             }
       
   264             HbAbstractEdit::keyPressEvent(event);
       
   265         }
       
   266         event->accept();
       
   267         return;
       
   268     }
       
   269 
       
   270     if(!str.isEmpty())
       
   271     {
       
   272         if (str.contains(expr))
       
   273         {
       
   274             if(this->text().isEmpty() || this->text().contains(sepAtEnd) || this->text().contains(mLabelExpr))
       
   275             {
       
   276                 event->accept();
       
   277                 return;
       
   278             }
       
   279 
       
   280             // auto-complete the last incomplete word
       
   281             int contentLength = this->text().length();
       
   282             int pos = this->cursorPosition();
       
   283             QString incompleteWord(this->text().right(contentLength-(pos-1)));
       
   284             if(!incompleteWord.contains(sepAtMiddle))
       
   285             {
       
   286                 this->setCursorPosition(this->text().length());
       
   287             }
       
   288 
       
   289             str.replace(expr, replacementStr);
       
   290             QKeyEvent eve(event->type(), event->key(), event->modifiers(), str);
       
   291             HbAbstractEdit::keyPressEvent(&eve);
       
   292         }
       
   293         else
       
   294         {
       
   295             HbAbstractEdit::keyPressEvent(event);
       
   296             event->accept();
       
   297             return;
       
   298         }
       
   299     }
       
   300 }
       
   301 
       
   302 void MsgUnifiedEditorLineEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
       
   303 {
       
   304     HbAbstractEdit::mouseReleaseEvent(event);
       
   305 
       
   306     int currentPos = this->cursorPosition();
       
   307 
       
   308     QString txt = this->text();
       
   309 
       
   310     QString tempTxt = txt.left(currentPos+2);
       
   311     int seperatorPos = tempTxt.lastIndexOf(sepAtMiddle,currentPos);
       
   312 
       
   313     txt = txt.right(txt.length() - currentPos);
       
   314     int labelPos = txt.indexOf(labelSeperator);
       
   315 
       
   316     if(labelPos >= 0 )//pressed on label.
       
   317     {
       
   318         this->setCursorPosition(currentPos + labelPos + 2);
       
   319     }
       
   320     else if(seperatorPos == currentPos-1 || seperatorPos == currentPos)//pressed just on seperator.
       
   321     {
       
   322         this->setCursorPosition(seperatorPos+2);
       
   323     }
       
   324     else
       
   325     {
       
   326         this->setCursorPosition(currentPos+1);
       
   327         bool pbkContact = this->textCursor().charFormat().fontUnderline();
       
   328         if(pbkContact)
       
   329         {
       
   330             setHighlight(currentPos);
       
   331         }
       
   332     }
       
   333 
       
   334     this->update();
       
   335     event->accept();
       
   336 }
       
   337 
       
   338 void MsgUnifiedEditorLineEdit::setText(const QString& text)
       
   339 {
       
   340     QInputMethodEvent e;
       
   341     //make sure previous text is complete.
       
   342     e.setCommitString(";");
       
   343     this->inputMethodEvent(&e);
       
   344     this->setCursorPosition(this->text().length());
       
   345 
       
   346     QTextCursor cursor(this->textCursor());
       
   347     QTextCharFormat colorFormat(cursor.charFormat());
       
   348     QColor fgColor = colorFormat.foreground().color();     
       
   349     fgColor.setAlpha(fadedAlpha);
       
   350     colorFormat.setUnderlineColor(fgColor);
       
   351 
       
   352     colorFormat.setFontUnderline(true);  
       
   353     cursor.insertText(text , colorFormat);
       
   354     colorFormat.setFontUnderline(false);
       
   355     
       
   356     cursor.insertText(replacementStr,colorFormat);
       
   357     
       
   358     this->setCursorVisibility(Hb::TextCursorHidden);
       
   359 }
       
   360 
       
   361 QStringList MsgUnifiedEditorLineEdit::addresses()
       
   362 {    
       
   363     QString text = this->text();
       
   364     text = text.remove(mLabel);
       
   365     QStringList list = text.split(replacementStr,QString::SkipEmptyParts);
       
   366     //list.removeDuplicates();
       
   367     return list;
       
   368 }
       
   369 
       
   370 void MsgUnifiedEditorLineEdit::focusInEvent(QFocusEvent* event)
       
   371 {    
       
   372     HbAbstractEdit::focusInEvent(event);
       
   373     this->setCursorVisibility(Hb::TextCursorVisible);
       
   374 }
       
   375 
       
   376 void MsgUnifiedEditorLineEdit::setHighlight(int currentPos)
       
   377 {
       
   378     QString txt = this->text();    
       
   379 
       
   380     int endPos = qMax(txt.indexOf(sepAtMiddle,currentPos),
       
   381                       txt.indexOf(labelSeperator,currentPos));
       
   382 
       
   383     int startPos = qMax(txt.lastIndexOf(sepAtMiddle,currentPos),
       
   384                         txt.lastIndexOf(labelSeperator,currentPos));
       
   385 
       
   386     disconnect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
       
   387                this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
       
   388 
       
   389     //highlight if pbk contact.
       
   390     if(startPos > 0 && endPos > 0 && startPos != endPos)
       
   391     {
       
   392         this->setSelection(startPos + 2, endPos - startPos - 2);
       
   393         this->update();
       
   394     }
       
   395     else
       
   396     {
       
   397         this->deselect();
       
   398     }
       
   399 
       
   400     this->update();
       
   401 
       
   402     connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
       
   403             this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
       
   404 }
       
   405 
       
   406 void MsgUnifiedEditorLineEdit::cut()
       
   407 {
       
   408     HbLineEdit::cut();
       
   409     //after cut delete seperator (i.e."; ").
       
   410     QKeyEvent eve(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
       
   411     HbLineEdit::keyPressEvent(&eve);
       
   412     HbLineEdit::keyPressEvent(&eve);
       
   413 }
       
   414 
       
   415 void MsgUnifiedEditorLineEdit::selectAll()
       
   416 {
       
   417     //don't allow user to select every thing.
       
   418     //do nothing.
       
   419 }
       
   420 
       
   421 void MsgUnifiedEditorLineEdit::selectionChanged(const QTextCursor &oldCursor, const QTextCursor& newCursor)
       
   422 {
       
   423 
       
   424     if(mSelectionSnapTimer.isActive())
       
   425     {
       
   426         mSelectionSnapTimer.stop();
       
   427     }
       
   428 
       
   429     if(newCursor.selectionStart() < mLabel.length())
       
   430     {
       
   431         this->setTextCursor(oldCursor);
       
   432         return;
       
   433     }
       
   434 
       
   435     mSelectionStart  = newCursor.selectionStart();
       
   436     mSelectionEnd    = newCursor.selectionEnd();
       
   437 
       
   438     if(mSelectionStart == mSelectionEnd )
       
   439     {
       
   440         return;
       
   441     }
       
   442 
       
   443     mSelectionSnapTimer.start(SNAP_DELAY,this);
       
   444 
       
   445 }
       
   446 
       
   447 void MsgUnifiedEditorLineEdit::timerEvent(QTimerEvent *event)
       
   448 {
       
   449     //passing event to base class.
       
   450     HbLineEdit::timerEvent(event);
       
   451 
       
   452     if (event->timerId() == mSelectionSnapTimer.timerId())
       
   453     {
       
   454         mSelectionSnapTimer.stop();
       
   455 
       
   456         disconnect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
       
   457                    this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
       
   458 
       
   459         QString txt = this->text();
       
   460 
       
   461         int startPos = qMax(txt.lastIndexOf(sepAtMiddle,mSelectionStart),
       
   462                             txt.lastIndexOf(labelSeperator,mSelectionStart));
       
   463 
       
   464         int endPos = qMax(txt.indexOf(sepAtMiddle,mSelectionEnd),
       
   465                           txt.indexOf(labelSeperator,mSelectionEnd));
       
   466 
       
   467         if(endPos < 0 )
       
   468         {
       
   469             endPos = mSelectionEnd;
       
   470         }
       
   471 
       
   472         this->setSelection(startPos + 2, endPos - startPos - 2);
       
   473 
       
   474         connect(this,SIGNAL(selectionChanged(QTextCursor,QTextCursor)),
       
   475                 this,SLOT(selectionChanged(QTextCursor,QTextCursor)));
       
   476 
       
   477         event->accept();
       
   478     }
       
   479 }
       
   480 
       
   481 void MsgUnifiedEditorLineEdit::onTextChanged(const QString& text)
       
   482 {
       
   483     const QString changedText = const_cast<QString&>(text).remove(mLabel);
       
   484     emit addressTextChanged(changedText);
       
   485 }
       
   486 
       
   487 // eof