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