/*! @file @id $Id$ */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 #ifndef QBROWSERLIB_LOG #define QBROWSERLIB_LOG #ifdef QT_GUI_LIB #include #include #endif #include #include #include #include // supported Qt logging types #include #include #include #include namespace qbrowserlib { #ifndef LOG #define LOG \ QBROWSERLIB_LOCAL_TRACER // #define LOG // qbrowserlib::Log(1, __PRETTY_FUNCTION__, __FILE__, __LINE__) #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 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 LogDialog& append(const Log& log, TYPE* arg) { std::ostringstream ss; ss<<"("< 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 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 Log& Log::operator<<(TYPE arg) { if (!_debug) return *this; std::stringstream ss; init(ss); indent(ss)<<" → "<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