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