Initial commit
[tietoopcom] / src / TocUi / TocChatWidget.cpp
1 /** \file TocChatWidget.cpp
2  * \brief Implementation of TocChatWidget class
3  * 
4  * Tieto Open Communicator - Client for the Telepathy communications framework.
5  * Copyright (c) 2010, Tieto Corporation
6  *
7  * All rights reserved.
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted provided that the following conditions are met:
10  *
11  *      Redistributions of source code must retain the above copyright notice,
12  *      this list of conditions and the following disclaimer.
13  *      Redistributions in binary form must reproduce the above copyright notice,
14  *      this list of conditions and the following disclaimer in the documentation
15  *      and/or other materials provided with the distribution.
16  *      Neither the name of the Tieto Corporation nor the names of its contributors 
17  *      may be used to endorse or promote products derived from this software without
18  *      specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  * 
30  */
31  
32 #include <QDateTime>
33 #include <QKeyEvent>
34
35 #include "ui_TocChatWidget.h"
36 #include "TocEmoticonsDialog"
37 #include "TocChatWidget"
38 #include "uidefs.h"
39 #include "macros.h"
40
41 TocChatWidget::TocChatWidget( const QString& uid, const QString& name, Presence presence, QWidget * parent, const Message& message )
42         : QWidget(parent) 
43 {
44         ui = new Ui_TocChatWidgetClass();
45         ui->setupUi( this );
46         setContentsMargins( -10, -10, -10, -10 );
47         
48         CONNECT(ui->smileButton,SIGNAL(clicked()),this,SLOT(showEmoticonsDialog()));
49         
50         _uid = uid;
51         _name = name;
52         
53         switch(presence)
54         {
55         case Available:
56                 ui->frame->setStyleSheet(STYLESHEET_ONLINE);
57                 break;
58         case XA:
59         case Away:
60                 ui->frame->setStyleSheet(STYLESHEET_AWAY);
61                 break;
62         case Busy:
63                 ui->frame->setStyleSheet(STYLESHEET_BUSY);
64                 break;
65         case Hidden:    
66         case Offline:  
67                 ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
68                 break;
69         default:
70                 ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
71         }
72
73         appendMessage(message);
74         
75         //Event filter for sending on Enter support  
76         ui->messageTextEdit->installEventFilter(this);
77         ui->messageTextEdit->setFocus();
78 }
79
80 TocChatWidget::~TocChatWidget() {
81         delete ui;
82 }
83
84 void TocChatWidget::onContactPresenceUpdate(Presence presence, const QString& description) {
85         QFont font = ui->chatTextEdit->currentFont();
86         QFont smallFont;
87         smallFont.setPointSize(static_cast<int>( font.pointSize() * 0.85) );
88         smallFont.setItalic(true);
89         ui->chatTextEdit->setCurrentFont(smallFont);
90         ui->chatTextEdit->setTextColor( Qt::darkGreen );
91         
92         QString status;
93         switch(presence)
94         {
95                 case Available:
96                         status = tr("Online");  
97                         ui->frame->setStyleSheet(STYLESHEET_ONLINE);
98                         break;
99                 case XA:
100                 case Away:
101                         status = tr("Away"); 
102                         ui->frame->setStyleSheet(STYLESHEET_AWAY);
103                         break;
104                 case Busy:
105                         status = tr("Do not Disturb"); 
106                         ui->frame->setStyleSheet(STYLESHEET_BUSY);
107                         break;
108                 case Hidden:
109                 case Offline:
110                         status = tr("Offline"); 
111                         ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
112                         break;
113                 default:
114                         status = tr("Unknown"); 
115                         ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
116         }
117         
118         if(description.size())
119                 ui->chatTextEdit->append(tr("%1 changed status to %2 (%3)").arg(_name).arg(status).arg(description));
120         else
121                 ui->chatTextEdit->append(tr("%1 changed status to %2").arg(_name).arg(status));
122         
123         ui->chatTextEdit->moveCursor(QTextCursor::End);
124         ui->chatTextEdit->setCurrentFont(font);
125 }
126
127 void TocChatWidget::updateContactPresence(Presence presence) {
128         switch(presence)
129         {
130         case Available:
131                 ui->frame->setStyleSheet(STYLESHEET_ONLINE);
132                 break;
133         case XA:
134         case Away:
135                 ui->frame->setStyleSheet(STYLESHEET_AWAY);
136                 break;
137         case Busy:
138                 ui->frame->setStyleSheet(STYLESHEET_BUSY);
139                 break;
140         case Hidden:    
141         case Offline:  
142                 ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
143                 break;
144         default:
145                 ui->frame->setStyleSheet(STYLESHEET_OFFLINE);
146         }
147 }
148
149 void TocChatWidget::appendMessage(const Message& message) {
150         if(message.contents.isEmpty())
151                 return;
152
153         QDateTime messageTime( QDateTime::fromTime_t( message.timestamp ) );
154         QDateTime currentTime( QDateTime::currentDateTime() );
155
156         QString format;
157         if( messageTime.date() < currentTime.date() )
158                 format = "ddd: yyyy-MM-dd hh:mm:ss";
159         else
160                 format = "hh:mm:ss";
161         
162         if(message.error == NoError) {
163
164                 ui->chatTextEdit->setTextColor(Qt::blue);
165                 ui->chatTextEdit->setFontItalic(true);
166                 ui->chatTextEdit->append( _name + " " + currentTime.toString("hh:mm:ss")
167                                 + " (" + messageTime.toString(format) + "): ");
168                 ui->chatTextEdit->setFontItalic(false);
169                 insertEmoticons(message.contents);
170                 
171         } else { 
172                 
173                 // If error occured
174                 ui->chatTextEdit->setTextColor(Qt::red);
175                 ui->chatTextEdit->setFontItalic(true);
176                 ui->chatTextEdit->append( tr("Message \"%1\" sent on %2 was not delivered %3"
177                                 ).arg(message.contents).arg(messageTime.toString(format)).arg(errorString(message.error)));
178         }
179         
180         ui->chatTextEdit->moveCursor(QTextCursor::End);
181 }
182
183 QString TocChatWidget::errorString(MessageDeliveryError error) {
184         
185         switch(error) {
186         case Unknown:
187                 return tr("because of unknown error.");
188
189         case ContactOffline:
190                 return tr("because contact was offline.");
191
192         case InvalidContact:
193                 return tr("because contact is invalid.");
194
195         case PermissionDenied:
196                 return tr("because permission was denied.");
197
198         case MessageTooLong:
199                 return tr("because message was too long.");
200
201         case UserOffline:
202                 return tr("because You are offline, connect to be able to send messages.");
203
204         case NotOnContactList:
205                 return tr("because the contact is not on Your contact list.");
206         
207         case CannotCreateChannel:
208                 return tr("because the channel with the contact could not be created.");
209
210         case NoError:
211                 return tr("because there was no error :).");
212
213         default:
214                 return tr("because of unknown error.");
215         }
216 }
217
218 void TocChatWidget::pressedSendButton() {
219         
220         if(ui->messageTextEdit->toPlainText().size()) {
221                 QDateTime time(QDateTime::currentDateTime());
222
223                 ui->chatTextEdit->setTextColor(Qt::black);
224                 ui->chatTextEdit->setFontItalic(true);
225                 ui->chatTextEdit->append( tr("me") + " (" + time.toString("hh:mm:ss") + "): " );
226                 ui->chatTextEdit->setFontItalic(false);
227                 
228                 insertEmoticons(ui->messageTextEdit->toPlainText());
229                 
230                 Message message;
231                 message.contents = ui->messageTextEdit->toPlainText();
232                 message.timestamp = time.toTime_t();
233                 emit newMessageReady(_uid, message);
234                 ui->messageTextEdit->clear();
235                 
236                 ui->chatTextEdit->moveCursor(QTextCursor::End);
237         }
238
239
240 bool TocChatWidget::eventFilter(QObject *object, QEvent *event) {
241         
242         if (object == ui->messageTextEdit) {
243                 
244                 if (event->type() == QEvent::KeyPress) {
245                         
246                         QKeyEvent *k = static_cast<QKeyEvent*>(event);                          
247                         if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return) {
248                                 
249                                 if ((!(k->modifiers() == (Qt::KeypadModifier | Qt::ShiftModifier)))     && 
250                                         (!(k->modifiers() == Qt::ShiftModifier))) {
251                                         
252                                         pressedSendButton();                    
253                                         return true;
254                                 }
255                         }
256                 }
257         }
258         return false;
259 }
260
261 void TocChatWidget::insertEmoticons(const QString& message) {
262         
263     int pos = 0, last = 0, delta = 1;
264     QString emot;
265    
266     while (pos+1 < message.length()) {
267         
268         // checking for ":)" or ":-)" type smilies...
269         if(message.at(pos) == ':') {
270
271             if(message.at(pos+1) == '-' && pos+2 < message.length()) { // checking for :-) type...
272                 delta = 2;
273             }
274             if(message.at(pos+delta) == ')') {
275                 delta++; emot = emotSmile_24x24;
276             } 
277             else if(message.at(pos+delta) == '(') {
278                 delta++; emot = emotSad_24x24;
279             }
280             else if(message.at(pos+delta) == '|') {
281                 delta++; emot = emotPlain_24x24;
282             }
283             else if(message.at(pos+delta) == 'D') {
284                 delta++; emot = emotGrin_24x24;
285             }
286             else if(message.at(pos+delta) == 'O') {
287                 delta++; emot = emotSurprise_24x24;
288             }
289             else if(message.at(pos+delta) == '*') {
290                 delta++; emot = emotKiss_24x24;
291             }
292             else
293                 delta = 1;
294         }
295         
296         // checking for ";)" or ";-)" type smilies...
297         else if(message.at(pos) == ';') {
298                 
299             if(message.at(pos+1) == '-' && pos+2 < message.length()) { // checking for ;-) type...
300                 delta = 2;
301             }
302             if(message.at(pos+delta) == ')') {
303                 delta++; emot = emotWink_24x24;
304             }
305             else
306                 delta = 1;
307         }
308         
309         // checking for "<emoticon>" type smilies...
310         else if(message.at(pos) == '<') {
311                 
312             if(message.right(message.length()-pos).startsWith("<angel>")) {
313                 delta = 7; emot = emotAngel_24x24;
314             }
315             else if(message.right(message.length()-pos).startsWith("<devil>")) {
316                 delta = 7; emot = emotDevil_24x24;
317             }
318             else if(message.right(message.length()-pos).startsWith("<monkey>")) {
319                 delta = 8; emot = emotMonkey_24x24;
320             } 
321             else if(message.right(message.length()-pos).startsWith("<crying>")) {
322                 delta = 8; emot = emotCrying_24x24;
323             }   
324             else if(message.right(message.length()-pos).startsWith("<glasses>")) {
325                 delta = 9; emot = emotGlasses_24x24;
326             }   
327             else if(message.right(message.length()-pos).startsWith("<bigsmile>")) {
328                 delta = 10; emot = emotSmileBig_24x24;
329             }   
330             else
331                 delta = 1;
332         }
333         
334         //OK, emoticon found ... inserting into chatView
335         if(delta>1) {
336             ui->chatTextEdit->insertPlainText(message.mid(last, pos-last));
337             ui->chatTextEdit->insertHtml("<img source=\"" + emot + "\">");
338             pos += delta; last = pos; delta = 1;
339         }
340         else {
341             pos += delta;
342         }
343     }
344     ui->chatTextEdit->insertPlainText(message.mid(last));
345 }
346
347 void TocChatWidget::showEmoticonsDialog() {
348         
349         TocEmoticonsDialog* emoticonsDialog = TocEmoticonsDialog::getInstance(this);
350
351         if ((*emoticonsDialog).exec() == QDialog::Accepted) {
352         
353                 QString alias = emoticonsDialog->getSelectedEmoticonAlias();    
354                 ui->messageTextEdit->insertPlainText(alias);
355         }
356         ui->messageTextEdit->setFocus();
357 }
358
359 void TocChatWidget::showEvent( QShowEvent* event ) {
360         ui->messageTextEdit->setFocus();
361         event->accept();
362 }