1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 1999-2011 Licq developers
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "messagelist.h"
21 
22 #include "config.h"
23 
24 #include <QDateTime>
25 #include <QFile>
26 #include <QHeaderView>
27 #include <QPainter>
28 #include <QResizeEvent>
29 #include <QScrollBar>
30 
31 #include <licq/userevents.h>
32 
33 using namespace LicqQtGui;
34 /* TRANSLATOR LicqQtGui::MessageList */
35 /* TRANSLATOR LicqQtGui::MessageListItem */
36 
MessageListItem(const Licq::UserEvent * theMsg,QTreeWidget * parent)37 MessageListItem::MessageListItem(const Licq::UserEvent* theMsg, QTreeWidget* parent)
38   : QTreeWidgetItem(parent)
39 {
40   // Keep a copy of the event
41   myMsg = theMsg->Copy();
42 
43   myUnread = (myMsg->isReceiver());
44 
45   setText(0, myMsg->isReceiver() ? "*R" : "S");
46   setTextAlignment(0, Qt::AlignHCenter);
47   SetEventLine();
48   QString t =  "-----";
49 
50   if (myMsg->IsDirect())    t[0] = 'D';
51   if (myMsg->IsUrgent())    t[1] = 'U';
52   if (myMsg->IsMultiRec())  t[2] = 'M';
53   //if (myMsg->IsCancelled()) t[3] = 'C';
54   if (myMsg->IsLicq())      t[3] = 'L';
55   if (myMsg->IsEncrypted()) t[4] = 'E';
56 
57   setText(2, t);
58   setTextAlignment(2, Qt::AlignHCenter);
59 
60   QDateTime d;
61   d.setTime_t(myMsg->Time());
62   QString sd = d.toString();
63   sd.truncate(sd.length() - 5);
64   setText(3, sd);
65 
66   QColor foreColor;
67   if (!myMsg->isReceiver())
68     foreColor = QColor("blue");
69   else
70     foreColor = QColor("red");
71   setForeground(0, foreColor);
72   setForeground(1, foreColor);
73   setForeground(2, foreColor);
74   setForeground(3, foreColor);
75 
76   QFont f(font(0));
77   f.setBold(myUnread);
78   f.setItalic(myMsg->IsUrgent());
79   setFont(0, f);
80   setFont(1, f);
81   setFont(2, f);
82   setFont(3, f);
83 
84   // Add ourselves first in the list instead of last
85   int index = parent->indexOfTopLevelItem(this);
86   if (index > -1)
87     parent->takeTopLevelItem(index);
88   parent->insertTopLevelItem(0, this);
89 }
90 
~MessageListItem(void)91 MessageListItem::~MessageListItem(void)
92 {
93   delete myMsg;
94 }
95 
SetEventLine()96 void MessageListItem::SetEventLine()
97 {
98   QString s = myMsg->description().c_str();
99   QString text;
100 
101   switch (myMsg->eventType())
102   {
103     case Licq::UserEvent::TypeMessage:
104       text = QString::fromUtf8(dynamic_cast<Licq::EventMsg*>(myMsg)->message().c_str());
105       break;
106 
107     case Licq::UserEvent::TypeUrl:
108       text = QString::fromUtf8(dynamic_cast<Licq::EventUrl*>(myMsg)->url().c_str());
109       break;
110 
111     case Licq::UserEvent::TypeChat:
112       text = QString::fromUtf8(dynamic_cast<Licq::EventChat*>(myMsg)->reason().c_str());
113       break;
114 
115     case Licq::UserEvent::TypeFile:
116       text = QFile::decodeName(dynamic_cast<Licq::EventFile*>(myMsg)->filename().c_str());
117       break;
118 
119     case Licq::UserEvent::TypeEmailAlert:
120       text = QString::fromUtf8(dynamic_cast<Licq::EventEmailAlert*>(myMsg)->from().c_str());
121       break;
122 
123     default:
124       break;
125   }
126 
127   if (!text.trimmed().isEmpty())
128     s += " [" + text.trimmed().replace('\n', "   ") + "]";
129   setText(1, s);
130 }
131 
MarkRead()132 void MessageListItem::MarkRead()
133 {
134   myUnread = false;
135   QFont f(font(0));
136   f.setBold(false);
137   f.setItalic(myMsg->IsUrgent());
138   setFont(0, f);
139   setFont(1, f);
140   setFont(2, f);
141   setFont(3, f);
142 
143   setText(0, myMsg->isReceiver() ? "R" : "S");
144   SetEventLine();
145 }
146 
147 //-----MessageList::constructor------------------------------------------------------------------------
MessageList(QWidget * parent)148 MessageList::MessageList(QWidget* parent)
149   : QTreeWidget(parent)
150 {
151   setColumnCount(4);
152   QStringList headers;
153   headers << tr("D") << tr("Event Type") << tr("Options") << tr("Time");
154   setHeaderLabels(headers);
155   setAllColumnsShowFocus(true);
156   setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
157   setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
158   setSortingEnabled(false);
159   setIndentation(0);
160   header()->hide();
161 
162   QPalette pal(palette());
163   QColor c = pal.color(QPalette::Active, QPalette::Window);
164   pal.setColor(QPalette::Active, QPalette::Base, c);
165   pal.setColor(QPalette::Inactive, QPalette::Base, c);
166   pal.setColor(QPalette::Highlight, pal.color(QPalette::Mid));
167   setPalette(pal);
168 
169   setFrameStyle(Panel | Sunken);
170   setMinimumHeight(40);
171 }
172 
currentMsg()173 Licq::UserEvent* MessageList::currentMsg()
174 {
175   if (currentItem() == NULL)
176     return NULL;
177   return (dynamic_cast<MessageListItem*>(currentItem())->msg());
178 }
179 
sizeHint() const180 QSize MessageList::sizeHint() const
181 {
182   QSize s = QTreeWidget::sizeHint();
183   s.setHeight(minimumHeight());
184 
185   return s;
186 }
187 
getNumUnread() const188 int MessageList::getNumUnread() const
189 {
190   int num = 0;
191 
192   for (int i = 0; i < topLevelItemCount(); ++i)
193   {
194     MessageListItem* item = dynamic_cast<MessageListItem*>(topLevelItem(i));
195     if (item->isUnread())
196       num++;
197   }
198   return num;
199 }
200 
getNextUnread()201 MessageListItem* MessageList::getNextUnread()
202 {
203   MessageListItem* next = NULL;
204   for (int i = 0; i < topLevelItemCount(); ++i)
205   {
206     MessageListItem* item = dynamic_cast<MessageListItem*>(topLevelItem(i));
207     if (item->isUnread())
208       next = item;
209   }
210   return next;
211 }
212 
resizeEvent(QResizeEvent * e)213 void MessageList::resizeEvent(QResizeEvent* e)
214 {
215   QScrollBar* s = verticalScrollBar();
216   int ow = header()->sectionSize(1);
217   int nw = width() - 200 - s->width();
218   QTreeWidget::resizeEvent(e);
219   if (ow != nw)
220   {
221     header()->resizeSection(1, nw);
222     emit sizeChange(1, ow, nw);
223   }
224   SetEventLines();
225 }
226 
SetEventLines()227 void MessageList::SetEventLines()
228 {
229   for (int i = 0; i < topLevelItemCount(); ++i)
230   {
231     MessageListItem* item = dynamic_cast<MessageListItem*>(topLevelItem(i));
232     item->SetEventLine();
233   }
234 }
235 
event(QEvent * event)236 bool MessageList::event(QEvent* event)
237 {
238   if (event->type() == QEvent::ToolTip)
239   {
240     QHelpEvent* helpEvent = dynamic_cast<QHelpEvent*>(event);
241     MessageListItem* item = dynamic_cast<MessageListItem*>(itemAt(helpEvent->pos()));
242 
243     if (item != NULL)
244     {
245       QString s(item->msg()->IsDirect() ? tr("Direct") : tr("Server"));
246       if (item->msg()->IsUrgent())
247         s += QString(" / ") + tr("Urgent");
248       if (item->msg()->IsMultiRec())
249         s += QString(" / ") + tr("Multiple Recipients");
250       if (item->msg()->IsCancelled())
251         s += QString(" / ") + tr("Cancelled Event");
252       if (item->msg()->IsLicq())
253         s += QString(" / Licq ") + QString::fromLocal8Bit(item->msg()->licqVersionStr().c_str());
254 
255       setToolTip(s);
256     }
257   }
258 
259   return QTreeWidget::event(event);
260 }
261 
drawRow(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const262 void MessageList::drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
263 {
264   QStyleOptionViewItem option2(option);
265   // Make highlighted row have same text color as when it is not highlighted
266   option2.palette.setBrush(QPalette::HighlightedText, itemFromIndex(index)->foreground(0));
267 
268   QTreeWidget::drawRow(painter, option2, index);
269   QRect r = visualRect(index);
270 
271   painter->save();
272   painter->setPen(QPen(option2.palette.dark(), 1));
273   int right = 0;
274   for (int i = 0; i < columnCount(); ++i)
275   {
276     right += columnWidth(i);
277     painter->drawLine(right, r.top(), right, r.bottom());
278   }
279   painter->drawLine(r.left(), r.bottom(), right, r.bottom());
280   painter->restore();
281 }
282