Vidalia 0.3.1
LogTreeWidget.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file LogTreeWidget.cpp
13** \brief Contains a collection of log messages as LogTreeItems
14*/
15
16#include "LogTreeWidget.h"
17#include "LogHeaderView.h"
19
20#include <QScrollBar>
21
22
23/** Default constructor. */
25 : QTreeWidget(parent)
26{
27 setHeader(new LogHeaderView(this));
28
29 /* Tor's log messages are always in English, so stop Qt from futzing with
30 * the message text if we're currently using a non-English RTL layout. */
31 if (layoutDirection() == Qt::RightToLeft) {
32 setItemDelegateForColumn(LogTreeWidget::MessageColumn,
33 new LogMessageColumnDelegate(this));
34 }
35
36 /* Explicitly default to sorting messages chronologically */
37 sortItems(LogTreeWidget::TimeColumn, Qt::AscendingOrder);
38
39 /* Default to always scrolling to the most recent item added */
40 _scrollOnNewItem = true;
41 setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
42 connect(verticalScrollBar(), SIGNAL(sliderReleased()),
43 this, SLOT(verticalSliderReleased()));
44}
45
46/** Called when the user moves the vertical scrollbar. If the user has the
47 * scrollbar at within one step of its maximum, then always scroll to new
48 * items when added. Otherwise, leave the scrollbar alone since they are
49 * probably looking at something in their history. */
50void
52{
53 QScrollBar *scrollBar = verticalScrollBar();
54 if (header()->sortIndicatorOrder() == Qt::AscendingOrder)
55 _scrollOnNewItem = (scrollBar->value() == scrollBar->maximum());
56 else
57 _scrollOnNewItem = (scrollBar->value() == scrollBar->minimum());
58}
59
60/** Cast a QList of QTreeWidgetItem pointers to a list of LogTreeWidget
61 * pointers. There really must be a better way to do this. */
62QList<LogTreeItem *>
63LogTreeWidget::qlist_cast(QList<QTreeWidgetItem *> inlist)
64{
65 QList<LogTreeItem *> outlist;
66 foreach (QTreeWidgetItem *item, inlist) {
67 outlist << (LogTreeItem *)item;
68 }
69 return outlist;
70}
71
72/** Sorts the list of pointers to log tree items by timestamp. */
73QList<LogTreeItem *>
74LogTreeWidget::qlist_sort(QList<LogTreeItem *> inlist)
75{
76 QMap<quint32, LogTreeItem *> outlist;
77 foreach (LogTreeItem *item, inlist) {
78 outlist.insert(item->id(), item);
79 }
80 return outlist.values();
81}
82
83/** The first time the log tree is shown, we need to set the default column
84 * widths. */
85void
86LogTreeWidget::showEvent(QShowEvent *event)
87{
88 static bool shown = false;
89 QTreeWidget::showEvent(event);
90 if (!shown) {
91 /* Set the default column widths the first time this is shown */
92 ((LogHeaderView *)header())->resetColumnWidths();
93 shown = true;
94 }
95}
96
97/** Clears all items from the message log and resets the counter in the status
98 * bar. */
99void
101{
102 /* Clear the messages */
103 _itemHistory.clear();
104 clear();
105}
106
107/** Returns a list of all currently selected items. */
108QStringList
110{
111 QStringList messages;
112
113 /* Get all selected log items */
114 QList<LogTreeItem *> items =
115 qlist_cast(selectedItems());
116
117 /* Format the message items as strings and put them in a list */
118 foreach (LogTreeItem *item, qlist_sort(items)) {
119 messages << item->toString();
120 }
121 return messages;
122}
123
124/** Returns a list of all items in the tree. */
125QStringList
127{
128 QStringList messages;
129
130 /* Format the message items as strings and put them in a list */
131 foreach (LogTreeItem *item, _itemHistory) {
132 messages << item->toString();
133 }
134 return messages;
135}
136
137/** Returns the number of items currently shown. */
138int
140{
141 return topLevelItemCount();
142}
143
144/** Sets the maximum number of items in the tree. */
145void
147{
148 while (max < messageCount() && _itemHistory.size() > 0) {
149 /* If the new max is less than the currently displayed number of
150 * items, then we'll get rid of some. */
151 int index = indexOfTopLevelItem(_itemHistory.takeFirst());
152 if (index != -1)
153 delete takeTopLevelItem(index);
154 }
155 _maxItemCount = max;
156}
157
158/** Deselects all currently selected items. */
159void
161{
162 foreach(QTreeWidgetItem *item, selectedItems()) {
163 item->setSelected(false);
164 }
165}
166
167/** Adds a log item to the tree and returns a pointer to the new item. */
169LogTreeWidget::log(tc::Severity type, const QString &message)
170{
171 int oldScrollValue;
172 QScrollBar *scrollBar = verticalScrollBar();
173 LogTreeItem *item = new LogTreeItem(type, message);
174
175 /* Remember the current scrollbar position */
176 oldScrollValue = scrollBar->value();
177
178 /* If we need to make room, then make some room */
179 if (messageCount() >= _maxItemCount && _itemHistory.size()) {
180 int index = indexOfTopLevelItem(_itemHistory.takeFirst());
181 if (index != -1)
182 delete takeTopLevelItem(index);
183 }
184
185 /* Add the new message item.
186 * NOTE: We disable sorting, add the new item, and then re-enable sorting
187 * to force the result to be sorted immediately. Otherwise, the new
188 * message is not sorted until the message log has focus again. This
189 * is totally lame.
190 */
191 setSortingEnabled(false);
192 addLogTreeItem(item);
193 setSortingEnabled(true);
194
195 /* The intended vertical scrolling behavior is as follows:
196 *
197 * 1) If the message log is sorted in chronological order, and the user
198 * previously had the vertical scroll bar at its maximum position, then
199 * reposition the vertical scroll bar to the new maximum value.
200 *
201 * 2) If the message log is sorted in reverse chronological order, and the
202 * user previously had the vertical scroll bar at its minimum position,
203 * then reposition the vertical scroll bar to the new minimum value
204 * (which is always just 0 anyway).
205 *
206 * 3) If the message log is sorted by severity level or lexicographically
207 * by log message, or if the user manually repositioned the scroll bar,
208 * then leave the vertical scroll bar at its previous position.
209 */
210 if (_scrollOnNewItem && sortColumn() == LogTreeWidget::TimeColumn) {
211 if (header()->sortIndicatorOrder() == Qt::AscendingOrder)
212 scrollBar->setValue(scrollBar->maximum());
213 else
214 scrollBar->setValue(scrollBar->minimum());
215 } else {
216 scrollBar->setValue(oldScrollValue);
217 }
218
219 return item;
220}
221
222/** Adds <b>item</b> as a top-level item in the tree. */
223void
225{
226 addTopLevelItem(item);
227 _itemHistory.append(item);
228}
229
230/** Filters the message log based on the given filter. */
231void
233{
234 int itemsShown = 0;
235 for (int i = _itemHistory.size()-1; i >= 0; i--) {
236 LogTreeItem *item = _itemHistory.at(i);
237 if ((itemsShown < _maxItemCount) && (filter & item->severity())) {
238 itemsShown++;
239 } else {
240 int itemIndex = indexOfTopLevelItem(item);
241 if (itemIndex != -1)
242 delete takeTopLevelItem(itemIndex);
243 _itemHistory.removeAt(i);
244 }
245 }
246}
247
248/** Searches the log for entries that contain the given text. */
249QList<LogTreeItem *>
250LogTreeWidget::find(QString text, bool highlight)
251{
252 QList<LogTreeItem *> items =
253 qlist_cast(findItems(text, Qt::MatchContains|Qt::MatchWrap, MessageColumn));
254
255 if (highlight) {
256 /* Deselect all items before highlighting our search results. */
257 deselectAll();
258 foreach (LogTreeItem *item, items) {
259 /* Highlight a matched item */
260 item->setSelected(true);
261 }
262 }
263
264 /* Return the results, sorted by timestamp */
265 return qlist_sort(items);
266}
stop errmsg connect(const QHostAddress &address, quint16 port)
tc::Severity severity() const
Definition: LogTreeItem.cpp:99
QString toString() const
Definition: LogTreeItem.cpp:50
quint32 id() const
Definition: LogTreeItem.h:43
QList< LogTreeItem * > _itemHistory
Definition: LogTreeWidget.h:87
void showEvent(QShowEvent *event)
void addLogTreeItem(LogTreeItem *item)
QStringList allMessages()
void setMaximumMessageCount(int max)
void filter(uint filter)
QStringList selectedMessages()
QList< LogTreeItem * > find(QString text, bool highlight=true)
QList< LogTreeItem * > qlist_sort(QList< LogTreeItem * > inlist)
bool _scrollOnNewItem
Definition: LogTreeWidget.h:89
void verticalSliderReleased()
LogTreeWidget(QWidget *parent=0)
QList< LogTreeItem * > qlist_cast(QList< QTreeWidgetItem * > inlist)
LogTreeItem * log(tc::Severity severity, const QString &message)
QString i(QString str)
Definition: html.cpp:32
Severity
Definition: tcglobal.h:69