|
|
|
/*! @file
|
|
|
|
|
|
|
|
@id $Id$
|
|
|
|
*/
|
|
|
|
// 1 2 3 4 5 6 7 8
|
|
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
|
|
|
|
#ifndef QBROWSERLIB_LOG
|
|
|
|
#define QBROWSERLIB_LOG
|
|
|
|
|
|
|
|
#ifdef QT_GUI_LIB
|
|
|
|
#include <qbrowserlib/ui_log.h>
|
|
|
|
#include <QtGui/QDialog>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#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_LOCAL_TRACER
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef TRC
|
|
|
|
#define TRC \
|
|
|
|
qbrowserlib::Log QBROWSERLIB_LOCAL_TRACER \
|
|
|
|
(this, __PRETTY_FUNCTION__, __FILE__, __LINE__)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef TRC_FN
|
|
|
|
#define TRC_FN \
|
|
|
|
qbrowserlib::Log QBROWSERLIB_LOCAL_TRACER \
|
|
|
|
(0, __PRETTY_FUNCTION__, __FILE__, __LINE__)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class LogDialog;
|
|
|
|
|
|
|
|
class Log {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
static bool DEBUG;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Log(const void* addr, const std::string& name,
|
|
|
|
const std::string& file, unsigned long line);
|
|
|
|
|
|
|
|
template<typename TYPE> Log& operator<<(TYPE arg);
|
|
|
|
|
|
|
|
~Log() throw();
|
|
|
|
|
|
|
|
static void show(QWidget* p);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
std::stringstream& init(std::stringstream& ss);
|
|
|
|
|
|
|
|
std::stringstream& indent(std::stringstream& ss);
|
|
|
|
|
|
|
|
std::stringstream& close(std::stringstream& ss);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
friend class LogDialog;
|
|
|
|
|
|
|
|
static LogDialog* _dialog;
|
|
|
|
static unsigned int _level;
|
|
|
|
bool _debug;
|
|
|
|
const void* _addr;
|
|
|
|
const std::string _name;
|
|
|
|
const std::string _file;
|
|
|
|
unsigned long _line;
|
|
|
|
};
|
|
|
|
|
|
|
|
class LogDialog:
|
|
|
|
#ifdef QT_GUI_LIB
|
|
|
|
public QDialog, public Ui::LogDialog
|
|
|
|
#else
|
|
|
|
public QObject
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
|
|
|
|
Q_OBJECT;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
#ifdef QT_GUI_LIB
|
|
|
|
LogDialog(QWidget* p=0): QDialog(p) {
|
|
|
|
setupUi(this);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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) {
|
|
|
|
#ifdef QT_GUI_LIB
|
|
|
|
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()));
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected Q_SLOTS:
|
|
|
|
|
|
|
|
#ifdef QT_GUI_LIB
|
|
|
|
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();
|
|
|
|
foreach (QTableWidgetItem* item, items) {
|
|
|
|
item->setSelected(true);
|
|
|
|
}
|
|
|
|
if (!items.isEmpty()) _logs->scrollToItem(items[0]);
|
|
|
|
unsetCursor();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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;
|
|
|
|
std::stringstream ss;
|
|
|
|
init(ss);
|
|
|
|
indent(ss)<<" → "<<arg;
|
|
|
|
std::clog<<close(ss).str()<<std::endl;
|
|
|
|
if (!_dialog) _dialog = new LogDialog;
|
|
|
|
_dialog->append(*this, 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
|