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