00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QMessageBox>
00029 #include <QFileDialog>
00030 #include <QInputDialog>
00031 #include <QMessageBox>
00032 #include <QClipboard>
00033 #include <vidalia.h>
00034 #include <util/html.h>
00035 #include <gui/common/vmessagebox.h>
00036
00037 #include "messagelog.h"
00038
00039
00040 #define SETTING_MSG_FILTER "MessageFilter"
00041 #define SETTING_MAX_MSG_COUNT "MaxMsgCount"
00042 #define SETTING_ENABLE_LOGFILE "EnableLogFile"
00043 #define SETTING_LOGFILE "LogFile"
00044 #define DEFAULT_MSG_FILTER \
00045 (LogEvent::Error|LogEvent::Warn|LogEvent::Notice)
00046 #define DEFAULT_MAX_MSG_COUNT 250
00047 #define DEFAULT_ENABLE_LOGFILE false
00048 #if defined(Q_OS_WIN32)
00049
00050
00051 #define DEFAULT_LOGFILE \
00052 (win32_program_files_folder()+"\\Tor\\tor-log.txt")
00053 #else
00054 #define DEFAULT_LOGFILE ("/var/log/tor/tor.log")
00055 #endif
00056
00057 #define ADD_TO_FILTER(f,v,b) (f = ((b) ? ((f) | (v)) : ((f) & ~(v))))
00058
00059
00060
00061
00062
00063
00064
00065
00066 MessageLog::MessageLog(QWidget *parent, Qt::WFlags flags)
00067 : VidaliaWindow("MessageLog", parent, flags)
00068 {
00069
00070 ui.setupUi(this);
00071
00072
00073 _torControl = Vidalia::torControl();
00074
00075
00076 createActions();
00077
00078
00079 setToolTips();
00080
00081
00082 loadSettings();
00083 }
00084
00085
00086
00087 MessageLog::~MessageLog()
00088 {
00089 _logFile.close();
00090 }
00091
00092
00093 void
00094 MessageLog::resizeEvent(QResizeEvent *event)
00095 {
00096 Q_UNUSED(event);
00097
00098
00099 ui.lstMessages->adjustMessageColumn();
00100 }
00101
00102
00103 void
00104 MessageLog::createActions()
00105 {
00106 connect(ui.actionSave_Selected, SIGNAL(triggered()),
00107 this, SLOT(saveSelected()));
00108
00109 connect(ui.actionSave_All, SIGNAL(triggered()),
00110 this, SLOT(saveAll()));
00111
00112 connect(ui.actionCopy, SIGNAL(triggered()),
00113 this, SLOT(copy()));
00114
00115 connect(ui.actionFind, SIGNAL(triggered()),
00116 this, SLOT(find()));
00117
00118 connect(ui.actionHelp, SIGNAL(triggered()),
00119 this, SLOT(help()));
00120
00121 connect(ui.btnSaveSettings, SIGNAL(clicked()),
00122 this, SLOT(saveSettings()));
00123
00124 connect(ui.btnCancelSettings, SIGNAL(clicked()),
00125 this, SLOT(cancelChanges()));
00126
00127 connect(ui.btnBrowse, SIGNAL(clicked()),
00128 this, SLOT(browse()));
00129
00130 #if defined(Q_WS_MAC)
00131 ui.actionHelp->setShortcut(QString("Ctrl+?"));
00132 ui.actionClose->setShortcut(QString("Ctrl+W"));
00133 #endif
00134 }
00135
00136
00137
00138 void
00139 MessageLog::setToolTips()
00140 {
00141 ui.chkTorErr->setToolTip(tr("Messages that appear when something has \n"
00142 "gone very wrong and Tor cannot proceed."));
00143 ui.chkTorWarn->setToolTip(tr("Messages that only appear when \n"
00144 "something has gone wrong with Tor."));
00145 ui.chkTorNote->setToolTip(tr("Messages that appear infrequently \n"
00146 "during normal Tor operation and are \n"
00147 "not considered errors, but you may \n"
00148 "care about."));
00149 ui.chkTorInfo->setToolTip(tr("Messages that appear frequently \n"
00150 "during normal Tor operation."));
00151 ui.chkTorDebug->setToolTip(tr("Hyper-verbose messages primarily of \n"
00152 "interest to Tor developers."));
00153 }
00154
00155
00156 void
00157 MessageLog::loadSettings()
00158 {
00159
00160 uint maxMsgCount = getSetting(SETTING_MAX_MSG_COUNT,
00161 DEFAULT_MAX_MSG_COUNT).toUInt();
00162 ui.spnbxMaxCount->setValue(maxMsgCount);
00163 ui.lstMessages->setMaximumMessageCount(maxMsgCount);
00164
00165
00166 _enableLogging = getSetting(SETTING_ENABLE_LOGFILE,
00167 DEFAULT_ENABLE_LOGFILE).toBool();
00168 QString logfile = getSetting(SETTING_LOGFILE,
00169 DEFAULT_LOGFILE).toString();
00170 ui.lineFile->setText(QDir::convertSeparators(logfile));
00171 rotateLogFile(logfile);
00172 ui.chkEnableLogFile->setChecked(_logFile.isOpen());
00173
00174
00175 _filter = getSetting(SETTING_MSG_FILTER, DEFAULT_MSG_FILTER).toUInt();
00176 ui.chkTorErr->setChecked(_filter & LogEvent::Error);
00177 ui.chkTorWarn->setChecked(_filter & LogEvent::Warn);
00178 ui.chkTorNote->setChecked(_filter & LogEvent::Notice);
00179 ui.chkTorInfo->setChecked(_filter & LogEvent::Info);
00180 ui.chkTorDebug->setChecked(_filter & LogEvent::Debug);
00181 registerLogEvents();
00182
00183
00184 QApplication::setOverrideCursor(Qt::WaitCursor);
00185 ui.lstMessages->filter(_filter);
00186 QApplication::restoreOverrideCursor();
00187 }
00188
00189
00190
00191 void
00192 MessageLog::registerLogEvents()
00193 {
00194 QString errmsg;
00195 _filter = getSetting(SETTING_MSG_FILTER, DEFAULT_MSG_FILTER).toUInt();
00196 if (!_torControl->setLogEvents(_filter, this, &errmsg)) {
00197 VMessageBox::warning(this, tr("Error Setting Filter"),
00198 p(tr("Vidalia was unable to register for Tor's log events.")) + p(errmsg),
00199 VMessageBox::Ok);
00200 }
00201 }
00202
00203
00204
00205
00206
00207 bool
00208 MessageLog::rotateLogFile(QString filename)
00209 {
00210 QString errmsg;
00211 if (_enableLogging) {
00212 if (!_logFile.open(filename, &errmsg)) {
00213 VMessageBox::warning(this, tr("Error Opening Log File"),
00214 p(tr("Vidalia was unable to open the specified log file."))+p(errmsg),
00215 VMessageBox::Ok);
00216 return false;
00217 }
00218 } else {
00219
00220 _logFile.close();
00221 }
00222 return true;
00223 }
00224
00225
00226
00227 void
00228 MessageLog::saveSettings()
00229 {
00230
00231 _enableLogging = ui.chkEnableLogFile->isChecked();
00232 if (rotateLogFile(ui.lineFile->text())) {
00233 saveSetting(SETTING_LOGFILE, ui.lineFile->text());
00234 saveSetting(SETTING_ENABLE_LOGFILE, _logFile.isOpen());
00235 }
00236 ui.lineFile->setText(QDir::convertSeparators(ui.lineFile->text()));
00237 ui.chkEnableLogFile->setChecked(_logFile.isOpen());
00238
00239
00240 saveSetting(SETTING_MAX_MSG_COUNT, ui.spnbxMaxCount->value());
00241 ui.lstMessages->setMaximumMessageCount(ui.spnbxMaxCount->value());
00242
00243
00244 uint filter = 0;
00245 ADD_TO_FILTER(filter, LogEvent::Error, ui.chkTorErr->isChecked());
00246 ADD_TO_FILTER(filter, LogEvent::Warn, ui.chkTorWarn->isChecked());
00247 ADD_TO_FILTER(filter, LogEvent::Notice, ui.chkTorNote->isChecked());
00248 ADD_TO_FILTER(filter, LogEvent::Info, ui.chkTorInfo->isChecked());
00249 ADD_TO_FILTER(filter, LogEvent::Debug, ui.chkTorDebug->isChecked());
00250 saveSetting(SETTING_MSG_FILTER, filter);
00251 registerLogEvents();
00252
00253
00254 QApplication::setOverrideCursor(Qt::WaitCursor);
00255 ui.lstMessages->filter(_filter);
00256 QApplication::restoreOverrideCursor();
00257
00258
00259 ui.actionSettings->toggle();
00260 }
00261
00262
00263
00264 void
00265 MessageLog::cancelChanges()
00266 {
00267
00268 ui.actionSettings->toggle();
00269
00270 loadSettings();
00271 }
00272
00273
00274 void
00275 MessageLog::browse()
00276 {
00277
00278 QString filename = QDir::convertSeparators(
00279 QFileDialog::getSaveFileName(this,
00280 tr("Select Log File"), "tor-log.txt"));
00281 if (!filename.isEmpty()) {
00282 ui.lineFile->setText(filename);
00283 }
00284 }
00285
00286
00287
00288
00289 void
00290 MessageLog::save(QList<LogTreeItem *> items)
00291 {
00292 if (!items.size()) {
00293 return;
00294 }
00295
00296 QString fileName = QFileDialog::getSaveFileName(this,
00297 tr("Save Log Messages"),
00298 "VidaliaLog-" +
00299 QDateTime::currentDateTime().toString("MM.dd.yyyy")
00300 + ".txt", tr("Text Files (*.txt)"));
00301
00302
00303 if (!fileName.isEmpty()) {
00304 LogFile logFile;
00305 QString errmsg;
00306
00307
00308 if (!logFile.open(fileName, &errmsg)) {
00309 VMessageBox::warning(this, tr("Vidalia"),
00310 p(tr("Cannot write file %1\n\n%2."))
00311 .arg(fileName)
00312 .arg(errmsg),
00313 VMessageBox::Ok);
00314 return;
00315 }
00316
00317
00318 QApplication::setOverrideCursor(Qt::WaitCursor);
00319 foreach (LogTreeItem *item, items) {
00320 logFile << item->toString();
00321 }
00322 QApplication::restoreOverrideCursor();
00323 }
00324 }
00325
00326
00327 void
00328 MessageLog::saveSelected()
00329 {
00330 save(ui.lstMessages->selectedMessages());
00331 }
00332
00333
00334 void
00335 MessageLog::saveAll()
00336 {
00337 save(ui.lstMessages->allMessages());
00338 }
00339
00340
00341 void
00342 MessageLog::copy()
00343 {
00344 QString contents = ui.lstMessages->selectedMessagesText();
00345 if (!contents.isEmpty()) {
00346
00347 QApplication::clipboard()->clear();
00348
00349 QApplication::clipboard()->setText(contents);
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358 void
00359 MessageLog::find()
00360 {
00361 bool ok;
00362 QString text = QInputDialog::getText(this, tr("Find in Message Log"),
00363 tr("Find:"), QLineEdit::Normal, QString(), &ok);
00364
00365 if (ok && !text.isEmpty()) {
00366
00367 QList<LogTreeItem *> results = ui.lstMessages->find(text);
00368 if (!results.size()) {
00369 VMessageBox::information(this, tr("Not Found"),
00370 p(tr("Search found 0 matches.")),
00371 VMessageBox::Ok);
00372 } else {
00373
00374 ui.lstMessages->scrollToItem(results.at(0));
00375 }
00376 }
00377 }
00378
00379
00380
00381
00382
00383
00384 void
00385 MessageLog::log(LogEvent::Severity type, QString message)
00386 {
00387
00388 if (_filter & (uint)type) {
00389
00390 LogTreeItem *item = ui.lstMessages->log(type, message);
00391
00392
00393
00394 QString currStatusTip = ui.statusbar->currentMessage();
00395 if (!currStatusTip.isEmpty()) {
00396 currStatusTip = ui.lstMessages->statusTip();
00397 ui.statusbar->showMessage(currStatusTip);
00398 }
00399
00400
00401 if (_enableLogging) {
00402 _logFile << item->toString();
00403 }
00404 }
00405 }
00406
00407
00408
00409
00410
00411 void
00412 MessageLog::customEvent(QEvent *event)
00413 {
00414 if (event->type() == CustomEventType::LogEvent) {
00415 LogEvent *e = (LogEvent *)event;
00416 log(e->severity(), e->message());
00417 e->accept();
00418 }
00419 }
00420
00421
00422 void
00423 MessageLog::help()
00424 {
00425 Vidalia::help("log");
00426 }
00427