You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
6.6 KiB
237 lines
6.6 KiB
/*! @file |
|
|
|
@id $Id$ |
|
*/ |
|
// 1 2 3 4 5 6 7 8 |
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890 |
|
|
|
#ifndef QBROWSERLIB_LOG |
|
#define QBROWSERLIB_LOG |
|
|
|
#include <qbrowserlib/ui_log.hxx> |
|
#include <QDialog> |
|
|
|
#include <stdexcept> |
|
#include <sstream> |
|
#include <iostream> |
|
#include <iomanip> |
|
#include <typeinfo> |
|
|
|
// supported Qt logging types |
|
#include <QtCore/QString> |
|
#include <QtCore/QStringList> |
|
#include <QtCore/QUrl> |
|
#include <QtCore/QByteArray> |
|
|
|
namespace qbrowserlib { |
|
|
|
#ifndef LOG |
|
#define LOG \ |
|
qbrowserlib::Log(this, __PRETTY_FUNCTION__, __FILE__, __LINE__, false) |
|
#endif |
|
|
|
#ifndef LOG_FN |
|
#define LOG_FN \ |
|
qbrowserlib::Log(0, __PRETTY_FUNCTION__, __FILE__, __LINE__, false) |
|
#endif |
|
|
|
#ifndef TRC |
|
#define TRC \ |
|
qbrowserlib::Log __TRC_LOCAL(this, __PRETTY_FUNCTION__, __FILE__, __LINE__) |
|
#endif |
|
|
|
#ifndef TRC_FN |
|
#define TRC_FN \ |
|
qbrowserlib::Log __TRC_LOCAL(0, __PRETTY_FUNCTION__, __FILE__, __LINE__) |
|
#endif |
|
|
|
#ifdef CRYPTOLOG |
|
#undef CRYPTOLOG |
|
#endif |
|
#define CRYPTOLOG(X) \ |
|
qbrowserlib::Log(0, __PRETTY_FUNCTION__, __FILE__, __LINE__, false)<<X; |
|
|
|
#ifdef OPENSSL_CHECK |
|
#undef OPENSSL_CHECK |
|
#endif |
|
#define OPENSSL_CHECK(X) \ |
|
if (!(X)) { \ |
|
ERR_load_ENGINE_strings(); \ |
|
qbrowserlib::Log ss(0, __PRETTY_FUNCTION__, __FILE__, __LINE__, false); \ |
|
for (unsigned int err(0); err=ERR_get_error();) { \ |
|
ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; \ |
|
} \ |
|
ss<<"Command "<<#X<<" failed in function "<<__PRETTY_FUNCTION__ \ |
|
<<" in file "<<__FILE__<<":"<<__LINE__; \ |
|
throw std::runtime_error(ss.str()); \ |
|
} |
|
|
|
class LogDialog; |
|
|
|
#ifdef DEBUG |
|
#undef DEBUG |
|
#endif |
|
|
|
class Log { |
|
|
|
public: |
|
|
|
static bool DEBUG; |
|
|
|
public: |
|
|
|
Log(); |
|
|
|
Log(const void* addr, const std::string& name, |
|
const std::string& file, unsigned long line, |
|
bool traceOpenClose=true); |
|
|
|
template<typename TYPE> Log& operator<<(TYPE arg); |
|
|
|
~Log() throw(); |
|
|
|
static void show(QWidget* p); |
|
|
|
std::string str() { |
|
return _ss.str(); |
|
} |
|
|
|
private: |
|
|
|
std::ostream& init(std::ostream& ss); |
|
|
|
std::ostream& indent(std::ostream& ss); |
|
|
|
std::ostream& close(std::ostream& ss); |
|
|
|
private: |
|
|
|
friend class LogDialog; |
|
|
|
static LogDialog* _dialog; |
|
static unsigned int _level; |
|
bool _debug; |
|
bool _close; |
|
const void* _addr; |
|
const std::string _name; |
|
const std::string _file; |
|
unsigned long _line; |
|
std::stringstream _ss; |
|
bool _clean; |
|
}; |
|
|
|
class LogDialog: public QDialog, public Ui::LogDialog { |
|
|
|
Q_OBJECT; |
|
|
|
public: |
|
|
|
LogDialog(QWidget* p=0): QDialog(p) { |
|
setupUi(this); |
|
} |
|
|
|
template<typename TYPE> LogDialog& append(const Log& log, TYPE* arg) { |
|
std::ostringstream ss; |
|
ss<<"("<<typeid(TYPE*).name()<<")"<<arg; |
|
return append(log, ss.str()); |
|
} |
|
|
|
template<typename TYPE> LogDialog& append(const Log& log, TYPE arg) { |
|
int pos(_logs->rowCount()); |
|
_logs->insertRow(pos); |
|
_logs->setItem |
|
(pos, FILE, |
|
new QTableWidgetItem(QString::fromStdString(log._file))); |
|
_logs->setItem |
|
(pos, LINE, new QTableWidgetItem(QString::number(log._line))); |
|
if (log._addr) _logs->setItem |
|
(pos, INSTANCE, |
|
new QTableWidgetItem |
|
(QString::number((qulonglong)log._addr))); |
|
_logs->setItem |
|
(pos, FUNCTION, |
|
new QTableWidgetItem(QString::fromStdString(log._name))); |
|
_logs->setItem |
|
(pos, MESSAGE, |
|
new QTableWidgetItem(QVariant(arg).toString())); |
|
return *this; |
|
} |
|
|
|
protected Q_SLOTS: |
|
|
|
void on__fileLine_toggled(bool checked) { |
|
if (checked) { |
|
_logs->showColumn(FILE); |
|
_logs->showColumn(LINE); |
|
} else { |
|
_logs->hideColumn(FILE); |
|
_logs->hideColumn(LINE); |
|
} |
|
} |
|
|
|
void on__instance_toggled(bool checked) { |
|
if (checked) { |
|
_logs->showColumn(INSTANCE); |
|
} else { |
|
_logs->hideColumn(INSTANCE); |
|
} |
|
} |
|
|
|
void on__function_toggled(bool checked) { |
|
if (checked) { |
|
_logs->showColumn(FUNCTION); |
|
} else { |
|
_logs->hideColumn(FUNCTION); |
|
} |
|
} |
|
|
|
void on__buttons_clicked(QAbstractButton* button) { |
|
if (_buttons->buttonRole(button)==QDialogButtonBox::ResetRole) |
|
for (int i(_logs->rowCount()); i>1; --i) |
|
_logs->removeRow(i-1); |
|
} |
|
|
|
void on__find_clicked(bool) { |
|
setCursor(QCursor(Qt::BusyCursor)); |
|
QList<QTableWidgetItem*> items |
|
(_logs->findItems(_search->text(), |
|
Qt::MatchWrap|Qt::MatchContains |
|
|Qt::MatchFixedString)); |
|
_logs->clearSelection(); |
|
for(QList<QTableWidgetItem*>::iterator item(items.begin()); |
|
item!=items.end(); ++item) { |
|
(*item)->setSelected(true); |
|
} |
|
if (!items.isEmpty()) _logs->scrollToItem(items[0]); |
|
unsetCursor(); |
|
} |
|
|
|
private: |
|
|
|
friend class Log; |
|
enum {FILE, LINE, INSTANCE, FUNCTION, MESSAGE} Columns; |
|
|
|
}; |
|
|
|
// note: template class method must be defined in the header |
|
template<typename TYPE> Log& Log::operator<<(TYPE arg) { |
|
if (!_debug) return *this; |
|
_clean = false; |
|
_ss<<" "<<arg; |
|
return *this; |
|
} |
|
|
|
template<> LogDialog& LogDialog::append |
|
(const Log& log, const char* arg); |
|
template<> LogDialog& LogDialog::append |
|
(const Log& log, std::string arg); |
|
template<> LogDialog& LogDialog::append |
|
(const Log& log, unsigned long arg); |
|
|
|
std::ostream& operator<<(std::ostream& ss, QString arg); |
|
std::ostream& operator<<(std::ostream& ss, QStringList arg); |
|
std::ostream& operator<<(std::ostream& ss, QUrl arg); |
|
std::ostream& operator<<(std::ostream& ss, QByteArray arg); |
|
} |
|
|
|
#endif
|
|
|