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 ui.lstMessages->sortItems(LogTreeWidget::TimeColumn,
00086 Qt::AscendingOrder);
00087 }
00088
00089
00090
00091 MessageLog::~MessageLog()
00092 {
00093 _logFile.close();
00094 }
00095
00096
00097 void
00098 MessageLog::resizeEvent(QResizeEvent *event)
00099 {
00100 Q_UNUSED(event);
00101
00102
00103 ui.lstMessages->adjustMessageColumn();
00104 }
00105
00106
00107 void
00108 MessageLog::createActions()
00109 {
00110 connect(ui.actionSave_Selected, SIGNAL(triggered()),
00111 this, SLOT(saveSelected()));
00112
00113 connect(ui.actionSave_All, SIGNAL(triggered()),
00114 this, SLOT(saveAll()));
00115
00116 connect(ui.actionCopy, SIGNAL(triggered()),
00117 this, SLOT(copy()));
00118
00119 connect(ui.actionFind, SIGNAL(triggered()),
00120 this, SLOT(find()));
00121
00122 connect(ui.actionHelp, SIGNAL(triggered()),
00123 this, SLOT(help()));
00124
00125 connect(ui.btnSaveSettings, SIGNAL(clicked()),
00126 this, SLOT(saveSettings()));
00127
00128 connect(ui.btnCancelSettings, SIGNAL(clicked()),
00129 this, SLOT(cancelChanges()));
00130
00131 connect(ui.btnBrowse, SIGNAL(clicked()),
00132 this, SLOT(browse()));
00133
00134 #if defined(Q_WS_MAC)
00135 ui.actionHelp->setShortcut(QString("Ctrl+?"));
00136 #endif
00137 #if !defined(Q_WS_WIN)
00138 ui.actionClose->setShortcut(QString("Ctrl+W"));
00139 #endif
00140 }
00141
00142
00143
00144 void
00145 MessageLog::setToolTips()
00146 {
00147 ui.chkTorErr->setToolTip(tr("Messages that appear when something has \n"
00148 "gone very wrong and Tor cannot proceed."));
00149 ui.chkTorWarn->setToolTip(tr("Messages that only appear when \n"
00150 "something has gone wrong with Tor."));
00151 ui.chkTorNote->setToolTip(tr("Messages that appear infrequently \n"
00152 "during normal Tor operation and are \n"
00153 "not considered errors, but you may \n"
00154 "care about."));
00155 ui.chkTorInfo->setToolTip(tr("Messages that appear frequently \n"
00156 "during normal Tor operation."));
00157 ui.chkTorDebug->setToolTip(tr("Hyper-verbose messages primarily of \n"
00158 "interest to Tor developers."));
00159 }
00160
00161
00162 void
00163 MessageLog::loadSettings()
00164 {
00165
00166 uint maxMsgCount = getSetting(SETTING_MAX_MSG_COUNT,
00167 DEFAULT_MAX_MSG_COUNT).toUInt();
00168 ui.spnbxMaxCount->setValue(maxMsgCount);
00169 ui.lstMessages->setMaximumMessageCount(maxMsgCount);
00170
00171
00172 _enableLogging = getSetting(SETTING_ENABLE_LOGFILE,
00173 DEFAULT_ENABLE_LOGFILE).toBool();
00174 QString logfile = getSetting(SETTING_LOGFILE,
00175 DEFAULT_LOGFILE).toString();
00176 ui.lineFile->setText(QDir::convertSeparators(logfile));
00177 rotateLogFile(logfile);
00178 ui.chkEnableLogFile->setChecked(_logFile.isOpen());
00179
00180
00181 _filter = getSetting(SETTING_MSG_FILTER, DEFAULT_MSG_FILTER).toUInt();
00182 ui.chkTorErr->setChecked(_filter & LogEvent::Error);
00183 ui.chkTorWarn->setChecked(_filter & LogEvent::Warn);
00184 ui.chkTorNote->setChecked(_filter & LogEvent::Notice);
00185 ui.chkTorInfo->setChecked(_filter & LogEvent::Info);
00186 ui.chkTorDebug->setChecked(_filter & LogEvent::Debug);
00187 registerLogEvents();
00188
00189
00190 QApplication::setOverrideCursor(Qt::WaitCursor);
00191 ui.lstMessages->filter(_filter);
00192 QApplication::restoreOverrideCursor();
00193 }
00194
00195
00196
00197 void
00198 MessageLog::registerLogEvents()
00199 {
00200 QString errmsg;
00201 _filter = getSetting(SETTING_MSG_FILTER, DEFAULT_MSG_FILTER).toUInt();
00202 if (!_torControl->setLogEvents(_filter, this, &errmsg)) {
00203 VMessageBox::warning(this, tr("Error Setting Filter"),
00204 p(tr("Vidalia was unable to register for Tor's log events.")) + p(errmsg),
00205 VMessageBox::Ok);
00206 }
00207 }
00208
00209
00210
00211
00212
00213 bool
00214 MessageLog::rotateLogFile(QString filename)
00215 {
00216 QString errmsg;
00217 if (_enableLogging) {
00218 if (!_logFile.open(filename, &errmsg)) {
00219 VMessageBox::warning(this, tr("Error Opening Log File"),
00220 p(tr("Vidalia was unable to open the specified log file."))+p(errmsg),
00221 VMessageBox::Ok);
00222 return false;
00223 }
00224 } else {
00225
00226 _logFile.close();
00227 }
00228 return true;
00229 }
00230
00231
00232
00233 void
00234 MessageLog::saveSettings()
00235 {
00236
00237 _enableLogging = ui.chkEnableLogFile->isChecked();
00238 if (_enableLogging && ui.lineFile->text().isEmpty()) {
00239
00240
00241 VMessageBox::warning(this, tr("Log Filename Required"),
00242 p(tr("You must enter a filename to be able to save log "
00243 "messages to a file.")), VMessageBox::Ok);
00244 return;
00245 }
00246 if (rotateLogFile(ui.lineFile->text())) {
00247 saveSetting(SETTING_LOGFILE, ui.lineFile->text());
00248 saveSetting(SETTING_ENABLE_LOGFILE, _logFile.isOpen());
00249 }
00250 ui.lineFile->setText(QDir::convertSeparators(ui.lineFile->text()));
00251 ui.chkEnableLogFile->setChecked(_logFile.isOpen());
00252
00253
00254 saveSetting(SETTING_MAX_MSG_COUNT, ui.spnbxMaxCount->value());
00255 ui.lstMessages->setMaximumMessageCount(ui.spnbxMaxCount->value());
00256
00257
00258 uint filter = 0;
00259 ADD_TO_FILTER(filter, LogEvent::Error, ui.chkTorErr->isChecked());
00260 ADD_TO_FILTER(filter, LogEvent::Warn, ui.chkTorWarn->isChecked());
00261 ADD_TO_FILTER(filter, LogEvent::Notice, ui.chkTorNote->isChecked());
00262 ADD_TO_FILTER(filter, LogEvent::Info, ui.chkTorInfo->isChecked());
00263 ADD_TO_FILTER(filter, LogEvent::Debug, ui.chkTorDebug->isChecked());
00264 saveSetting(SETTING_MSG_FILTER, filter);
00265 registerLogEvents();
00266
00267
00268 QApplication::setOverrideCursor(Qt::WaitCursor);
00269 ui.lstMessages->filter(_filter);
00270 QApplication::restoreOverrideCursor();
00271
00272
00273 ui.actionSettings->toggle();
00274 }
00275
00276
00277
00278 void
00279 MessageLog::cancelChanges()
00280 {
00281
00282 ui.actionSettings->toggle();
00283
00284 loadSettings();
00285 }
00286
00287
00288 void
00289 MessageLog::browse()
00290 {
00291
00292 QString filename = QDir::convertSeparators(
00293 QFileDialog::getSaveFileName(this,
00294 tr("Select Log File"), "tor-log.txt"));
00295 if (!filename.isEmpty()) {
00296 ui.lineFile->setText(filename);
00297 }
00298 }
00299
00300
00301
00302
00303 void
00304 MessageLog::save(QStringList messages)
00305 {
00306 if (!messages.size()) {
00307 return;
00308 }
00309
00310 QString fileName = QFileDialog::getSaveFileName(this,
00311 tr("Save Log Messages"),
00312 "VidaliaLog-" +
00313 QDateTime::currentDateTime().toString("MM.dd.yyyy")
00314 + ".txt", tr("Text Files (*.txt)"));
00315
00316
00317 if (!fileName.isEmpty()) {
00318 LogFile logFile;
00319 QString errmsg;
00320
00321
00322 if (!logFile.open(fileName, &errmsg)) {
00323 VMessageBox::warning(this, tr("Vidalia"),
00324 p(tr("Cannot write file %1\n\n%2."))
00325 .arg(fileName)
00326 .arg(errmsg),
00327 VMessageBox::Ok);
00328 return;
00329 }
00330
00331
00332 QApplication::setOverrideCursor(Qt::WaitCursor);
00333 foreach (QString msg, messages) {
00334 logFile << msg;
00335 }
00336 QApplication::restoreOverrideCursor();
00337 }
00338 }
00339
00340
00341 void
00342 MessageLog::saveSelected()
00343 {
00344 save(ui.lstMessages->selectedMessages());
00345 }
00346
00347
00348 void
00349 MessageLog::saveAll()
00350 {
00351 save(ui.lstMessages->allMessages());
00352 }
00353
00354
00355 void
00356 MessageLog::copy()
00357 {
00358 QString contents = ui.lstMessages->selectedMessages().join("");
00359 if (!contents.isEmpty()) {
00360
00361 QApplication::clipboard()->clear();
00362
00363 QApplication::clipboard()->setText(contents);
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00372 void
00373 MessageLog::find()
00374 {
00375 bool ok;
00376 QString text = QInputDialog::getText(this, tr("Find in Message Log"),
00377 tr("Find:"), QLineEdit::Normal, QString(), &ok);
00378
00379 if (ok && !text.isEmpty()) {
00380
00381 QList<LogTreeItem *> results = ui.lstMessages->find(text);
00382 if (!results.size()) {
00383 VMessageBox::information(this, tr("Not Found"),
00384 p(tr("Search found 0 matches.")),
00385 VMessageBox::Ok);
00386 } else {
00387
00388 ui.lstMessages->scrollToItem(results.at(0));
00389 }
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398 void
00399 MessageLog::log(LogEvent::Severity type, QString message)
00400 {
00401
00402 if (_filter & (uint)type) {
00403
00404 LogTreeItem *item = ui.lstMessages->log(type, message);
00405
00406
00407
00408 QString currStatusTip = ui.statusbar->currentMessage();
00409 if (!currStatusTip.isEmpty()) {
00410 currStatusTip = ui.lstMessages->statusTip();
00411 ui.statusbar->showMessage(currStatusTip);
00412 }
00413
00414
00415 if (_enableLogging) {
00416 _logFile << item->toString();
00417 }
00418 }
00419 }
00420
00421
00422
00423
00424
00425 void
00426 MessageLog::customEvent(QEvent *event)
00427 {
00428 if (event->type() == CustomEventType::LogEvent) {
00429 LogEvent *e = (LogEvent *)event;
00430 log(e->severity(), e->message());
00431 e->accept();
00432 }
00433 }
00434
00435
00436 void
00437 MessageLog::help()
00438 {
00439 Vidalia::help("log");
00440 }
00441