Properly enable and disable "View/Expand Subtrees". Get rid
[metze/wireshark/wip.git] / ui / qt / main_status_bar.cpp
1 /* main_status_bar.cpp
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <glib.h>
29
30 #include "main_status_bar.h"
31
32 #include "wireshark_application.h"
33
34 #include "globals.h"
35
36 #include "epan/expert.h"
37
38 #include "ui/main_statusbar.h"
39 #include "ui/utf8_entities.h"
40
41 #include <QSplitter>
42 #include <QHBoxLayout>
43
44 #ifdef HAVE_LIBPCAP
45 #define DEF_READY_MESSAGE QObject::tr(" Ready to load or capture")
46 #else
47 #define DEF_READY_MESSAGE QObject::tr(" Ready to load file")
48 #endif
49
50 // XXX - The GTK+ code assigns priorities to these and pushes/pops accordingly.
51
52 enum StatusContext {
53     STATUS_CTX_MAIN,
54     STATUS_CTX_FILE,
55     STATUS_CTX_FIELD,
56     STATUS_CTX_FILTER,
57     STATUS_CTX_TEMPORARY
58 };
59
60 // If we ever add support for multiple windows this will need to be replaced.
61 // See also: main_window.cpp
62 static MainStatusBar *cur_main_status_bar = NULL;
63
64 /*
65  * Push a formatted temporary message onto the statusbar.
66  */
67 void
68 statusbar_push_temporary_msg(const gchar *msg_format, ...)
69 {
70     va_list ap;
71     gchar *msg;
72     QString pushMsg;
73
74     if (!cur_main_status_bar) return;
75
76     va_start(ap, msg_format);
77     msg = g_strdup_vprintf(msg_format, ap);
78     va_end(ap);
79
80     pushMsg.fromUtf8(msg);
81     g_free(msg);
82
83     cur_main_status_bar->pushTemporaryStatus(pushMsg);
84 }
85
86 /*
87  * Update the packets statusbar to the current values
88  */
89 void
90 packets_bar_update(void)
91 {
92     QString packetsStr = QString("");
93
94     if (!cur_main_status_bar) return;
95
96     cur_main_status_bar->popPacketStatus();
97
98     /* Do we have any packets? */
99     if (cfile.count) {
100         packetsStr.append(QString("Packets: %1 " UTF8_MIDDLE_DOT " Displayed: %2 " UTF8_MIDDLE_DOT " Marked: %3")
101 //        packetsStr.append(QString(QObject::tr("Packets: %1 Displayed: %2 Marked: %3"))
102                           .arg(cfile.count)
103                           .arg(cfile.displayed_count)
104                           .arg(cfile.marked_count));
105         if(cfile.drops_known) {
106             packetsStr.append(QString(" " UTF8_MIDDLE_DOT " Dropped: %1")).arg(cfile.drops);
107         }
108         if(cfile.ignored_count > 0) {
109             packetsStr.append(QString(" " UTF8_MIDDLE_DOT " Ignored: %1").arg(cfile.ignored_count));
110         }
111         if(!cfile.is_tempfile) {
112             /* Loading an existing file */
113             gulong computed_elapsed = cf_get_computed_elapsed();
114             packetsStr.append(QString(" " UTF8_MIDDLE_DOT " Load time: %1:%2.%3")
115                                         .arg(computed_elapsed/60000)
116                                         .arg(computed_elapsed%60000/1000)
117                                         .arg(computed_elapsed%1000));
118             /*packetsStr.append(QString().sprintf(QObject::tr(" Load time: %lu:%02lu.%03lu",
119                                         computed_elapsed/60000,
120                                         computed_elapsed%60000/1000,
121                                         computed_elapsed%1000)));
122             */
123         }
124     } else {
125         packetsStr.append(QObject::tr("No Packets"));
126     }
127
128     cur_main_status_bar->pushPacketStatus(packetsStr);
129 }
130
131 MainStatusBar::MainStatusBar(QWidget *parent) :
132     QStatusBar(parent)
133 {
134     QSplitter *splitter = new QSplitter(this);
135     QString readyMsg(DEF_READY_MESSAGE);
136     QWidget *infoProgress = new QWidget(this);
137     QHBoxLayout *infoProgressHB = new QHBoxLayout(infoProgress);
138
139 #if defined(Q_WS_WIN)
140     // Handles are the same color as widgets, at least on Windows 7.
141     splitter->setHandleWidth(3);
142     splitter->setStyleSheet(QString(
143                                 "QSplitter::handle {"
144                                 "  border-left: 1px solid palette(mid);"
145                                 "  border-right: 1px solid palette(mid);"
146                                 "}"
147                                 ));
148 #elif defined(Q_WS_MAC)
149     m_expertStatus.setAttribute(Qt::WA_MacSmallSize, true);
150 #endif
151
152 //    infoProgress->setStyleSheet("QWidget { border: 0.5px dotted red; }"); // Debug layout
153     m_expertStatus.setTextFormat(Qt::RichText);
154     m_expertStatus.hide();
155
156     // XXX Add the comment icon
157
158     infoProgressHB->setMargin(0);
159     infoProgressHB->setContentsMargins(0, 0, 0, 0);
160
161     m_infoStatus.setTemporaryContext(STATUS_CTX_TEMPORARY);
162
163     infoProgressHB->addWidget(&m_expertStatus);
164     infoProgressHB->addWidget(&m_infoStatus);
165     infoProgressHB->addWidget(&m_progressBar);
166     infoProgressHB->addStretch(10);
167
168     splitter->addWidget(infoProgress);
169     splitter->addWidget(&m_packetStatus);
170     splitter->addWidget(&m_profileStatus);
171
172     splitter->setStretchFactor(0, 3);
173     splitter->setStretchFactor(1, 3);
174     splitter->setStretchFactor(2, 1);
175
176     addWidget(splitter, 1);
177
178     cur_main_status_bar = this;
179
180     m_infoStatus.pushText(readyMsg, STATUS_CTX_MAIN);
181     packets_bar_update();
182 }
183
184 void MainStatusBar::showExpert() {
185     expertUpdate();
186 }
187
188 void MainStatusBar::hideExpert() {
189     m_expertStatus.hide();
190 }
191
192 void MainStatusBar::expertUpdate() {
193     QString imgText = "<img src=\":/expert/expert_";
194     QString ttText = " is the highest expert info level";
195
196     switch(expert_get_highest_severity()) {
197     case(PI_ERROR):
198         imgText.append("error");
199         ttText.prepend("ERROR");
200         break;
201     case(PI_WARN):
202         imgText.append("warn");
203         ttText.prepend("WARNING");
204         break;
205     case(PI_NOTE):
206         imgText.append("note");
207         ttText.prepend("NOTE");
208         break;
209     case(PI_CHAT):
210         imgText.append("chat");
211         ttText.prepend("CHAT");
212         break;
213 //    case(PI_COMMENT):
214 //        m_expertStatus.setText("<img src=\":/expert/expert_comment.png\"></img>");
215 //        break;
216     default:
217         imgText.append("none");
218         ttText = "No expert info";
219         break;
220     }
221
222     imgText.append(".png\"></img>");
223     m_expertStatus.setText(imgText);
224     m_expertStatus.setToolTip(ttText);
225     m_expertStatus.show();
226 }
227
228 void MainStatusBar::pushTemporaryStatus(QString &message) {
229     m_infoStatus.pushText(message, STATUS_CTX_TEMPORARY);
230 }
231
232 void MainStatusBar::popTemporaryStatus() {
233     m_infoStatus.popText(STATUS_CTX_TEMPORARY);
234 }
235
236 void MainStatusBar::pushFileStatus(QString &message) {
237     m_infoStatus.pushText(message, STATUS_CTX_FILE);
238     expertUpdate();
239 }
240
241 void MainStatusBar::popFileStatus() {
242     m_infoStatus.popText(STATUS_CTX_FILE);
243 }
244
245 void MainStatusBar::pushFieldStatus(QString &message) {
246     if (message.isNull()) {
247         popFieldStatus();
248     } else {
249         m_infoStatus.pushText(message, STATUS_CTX_FIELD);
250     }
251 }
252
253 void MainStatusBar::popFieldStatus() {
254     m_infoStatus.popText(STATUS_CTX_FIELD);
255 }
256
257 void MainStatusBar::pushFilterStatus(QString &message) {
258     m_infoStatus.pushText(message, STATUS_CTX_FILTER);
259     expertUpdate();
260 }
261
262 void MainStatusBar::popFilterStatus() {
263     m_infoStatus.popText(STATUS_CTX_FILTER);
264 }
265
266 void MainStatusBar::pushPacketStatus(QString &message) {
267     m_packetStatus.pushText(message, STATUS_CTX_MAIN);
268 }
269
270 void MainStatusBar::popPacketStatus() {
271     m_packetStatus.popText(STATUS_CTX_MAIN);
272 }
273
274 void MainStatusBar::pushProfileStatus(QString &message) {
275     m_profileStatus.pushText(message, STATUS_CTX_MAIN);
276 }
277
278 void MainStatusBar::popProfileStatus() {
279     m_profileStatus.popText(STATUS_CTX_MAIN);
280 }
281