From c788e6a1b174afd154e589a76885731c2fc19723 Mon Sep 17 00:00:00 2001
From: deva <deva>
Date: Tue, 17 Aug 2010 11:14:04 +0000
Subject: First shot at a debug console.

---
 client/client.pro        |   3 +
 client/debug.cc          | 167 +++++++++++++++++++++++++++++++++++++++++++++++
 client/debug.h           |  62 ++++++++++++++++++
 client/lua.cc            |  39 +++++------
 client/lua.h             |   2 -
 client/macrowindow.cc    |  16 ++---
 client/mainwindow.cc     |  17 +++++
 client/netcom.cc         |  18 +++--
 client/pracro.cc         |   5 ++
 client/widgets/widget.cc |   9 ++-
 10 files changed, 292 insertions(+), 46 deletions(-)
 create mode 100644 client/debug.cc
 create mode 100644 client/debug.h

(limited to 'client')

diff --git a/client/client.pro b/client/client.pro
index 8b2a130..e507c4e 100644
--- a/client/client.pro
+++ b/client/client.pro
@@ -13,6 +13,7 @@ QT += core gui network xml sql svg
 debug {
 	QMAKE_CXXFLAGS += -g -Wall -Werror
 	CONFIG += debug
+	DEFINES+=USE_DEBUG
 }
 
 DEFINES+=VERSION=\\\"2.0.0-beta2\\\"
@@ -33,6 +34,7 @@ unix {
 
 HEADERS += \
 	collapser.h \
+	debug.h \
 	formatparser.h \
 	lua.h \
 	luawidget.h \
@@ -69,6 +71,7 @@ HEADERS += \
 SOURCES += \
 	pracro.cc \
 	collapser.cc \
+	debug.cc \
 	formatparser.cc \
 	lua.cc \
 	luawidget.cc \
diff --git a/client/debug.cc b/client/debug.cc
new file mode 100644
index 0000000..3138cf4
--- /dev/null
+++ b/client/debug.cc
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ *            debug.cc
+ *
+ *  Tue Aug 17 10:48:45 CEST 2010
+ *  Copyright 2010 Bent Bisballe Nyeng
+ *  deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ *  This file is part of Pracro.
+ *
+ *  Pracro is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Pracro is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Pracro; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+#include "debug.h"
+
+#include <QDialog>
+#include <QListWidget>
+#include <QVBoxLayout>
+#include <QCloseEvent>
+#include <QSettings>
+
+static const char * const class_str[] =
+  { "debug", "error", "warn", "log" };
+
+class DebugWindow : public QDialog {
+public:
+  DebugWindow();
+
+  void log(const char *func, const char *file, const int line,
+           debug_class cl, const char *ch, QString &msg);
+protected:
+  void closeEvent(QCloseEvent *event);
+
+private:
+  QListWidget *lst;
+};
+
+DebugWindow::DebugWindow()
+{
+  setLayout(new QVBoxLayout());
+  lst = new QListWidget();
+  layout()->addWidget(lst);
+
+  QSettings settings("Aasimon.org", "Pracro");
+  settings.beginGroup("DebugWindow");
+  resize(settings.value("size", QSize(700, 800)).toSize());
+  move(settings.value("pos", QPoint(0, 0)).toPoint());
+  settings.endGroup();
+}
+
+void DebugWindow::closeEvent(QCloseEvent *event)
+{
+  QSettings settings("Aasimon.org", "Pracro");
+  settings.beginGroup("DebugWindow");
+  settings.setValue("size", size());
+  settings.setValue("pos", pos());
+  settings.endGroup();
+  event->accept();
+}
+
+void DebugWindow::log(const char *func, const char *file, const int line,
+                      debug_class cl, const char *ch, QString &msg)
+{
+  // Remove trailing newlines.
+  while(msg.endsWith("\n")) msg = msg.left(msg.length() - 1);
+
+  QString txt;
+  txt.sprintf("[%s] %s %s:%s:%d ",
+              class_str[(unsigned)cl], ch, file, func, line);
+  txt += " : " + msg;
+
+  QListWidgetItem *item = new QListWidgetItem();
+  item->setText(txt);
+  if(cl == _error) item->setBackground(QBrush(QColor(230, 200, 200)));
+  if(cl == _warn) item->setBackground(QBrush(QColor(200, 200, 230)));
+  if(cl == _log) item->setBackground(QBrush(QColor(200, 230, 200)));
+
+  lst->addItem(item);
+  lst->scrollToItem(item);
+}
+
+
+static DebugWindow* debugwindow = NULL;
+
+void dbg_init()
+{
+  if(debugwindow) dbg_free();
+  debugwindow = new DebugWindow();
+}
+
+void dbg_free()
+{
+  if(debugwindow) delete debugwindow;
+  debugwindow = NULL;
+}
+
+void dbg_show()
+{
+  if(debugwindow) debugwindow->show();
+}
+
+void dbg_toggle()
+{
+  if(debugwindow) {
+    if(debugwindow->isVisible()) dbg_hide();
+    else dbg_show();
+  }
+}
+
+void dbg_hide()
+{
+  if(debugwindow) debugwindow->hide();
+}
+
+void dbg_log(const char *func, const char *file, const int line,
+             debug_class cl, const char *ch, const char *fmt, ...)
+{
+  if(debugwindow) {
+    QString msg;
+
+    va_list va;
+    va_start(va, fmt);
+    msg.vsprintf(fmt, va);
+    va_end(va);
+
+    debugwindow->log(func, file, line, cl, ch, msg);
+  } else {
+    fprintf(stderr, "[%s] %s %s:%s:%d ",
+            class_str[(unsigned)cl], ch, file, func, line);
+    va_list va;
+    va_start(va, fmt);
+    vfprintf(stderr, fmt, va);
+    va_end(va);
+  }
+}
+
+
+#ifdef TEST_DEBUG
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+
+TEST_END;
+
+#endif/*TEST_DEBUG*/
diff --git a/client/debug.h b/client/debug.h
new file mode 100644
index 0000000..0508b31
--- /dev/null
+++ b/client/debug.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ *            debug.h
+ *
+ *  Tue Aug 17 10:48:44 CEST 2010
+ *  Copyright 2010 Bent Bisballe Nyeng
+ *  deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ *  This file is part of Pracro.
+ *
+ *  Pracro is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Pracro is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Pracro; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+#ifndef __PRACRO_DEBUG_H__
+
+void dbg_init();
+void dbg_free();
+
+void dbg_show();
+void dbg_toggle();
+void dbg_hide();
+
+typedef enum {
+  _debug,
+  _error,
+  _warn,
+  _log
+} debug_class;
+
+void dbg_log(const char *func, const char *file, const int line,
+             debug_class cl, const char *ch, const char *fmt, ...)
+  __attribute__((format (printf,6,7)));
+
+#ifdef USE_DEBUG
+#define DEBUG(ch, fmt...) \
+  dbg_log(__func__, __FILE__, __LINE__, _debug, #ch, fmt);
+#else
+#define DEBUG(ch, fmt...)
+#endif
+#define ERROR(ch, fmt...) \
+  dbg_log(__func__, __FILE__,__LINE__, _error, #ch, fmt);
+#define WARN(ch, fmt...) \
+  dbg_log(__func__, __FILE__,__LINE__, _warn, #ch, fmt);
+#define LOG(ch, fmt...) \
+  dbg_log(__func__, __FILE__,__LINE__, _log, #ch, fmt);
+
+#define __PRACRO_DEBUG_H__
+#endif/*__PRACRO_DEBUG_H__*/
diff --git a/client/lua.cc b/client/lua.cc
index eb9b8a3..3607a26 100644
--- a/client/lua.cc
+++ b/client/lua.cc
@@ -32,8 +32,7 @@
 
 #include "luawidget.h"
 
-//#define DEBUG(fmt...) printf("LUA (%p)", this); printf(fmt); fflush(stdout)
-#define DEBUG(ftm...)
+#include "debug.h"
 
 #define GLOBAL_POINTER "_pracroGlobalLUAObjectPointerThisShouldBeANameThatIsNotAccidentallyOverwritten"
 
@@ -61,7 +60,7 @@ static int get_widget(lua_State *L)
 
   Widget *widget = lua->getWidget(name);
 
-  // DEBUG("FIND: %s (%p)\n", name.toStdString().c_str(), widget);
+  DEBUG(lua, "FIND: %s (%p)\n", name.toStdString().c_str(), widget);
 
   if(widget) {
     wdg_make_widget(L, widget);
@@ -69,7 +68,7 @@ static int get_widget(lua_State *L)
     lua_pushnil(L);
   }
 
-  // DEBUG("DONE\n");
+  DEBUG(lua, "DONE\n");
 
   return 1;
 }
@@ -93,7 +92,7 @@ void LUA::clear()
 
   L = luaL_newstate();
   if(L == NULL) {
-    error("Could not create LUA state.");
+    ERROR(lua, "Could not create LUA state.");
     return;
   }
 
@@ -110,11 +109,11 @@ void LUA::clear()
 QString LUA::runParser(QString program)
 {
   if(L == NULL) {
-    error("LUA state not initialized!");
+    ERROR(lua, "LUA state not initialized!");
     return false;
   }
 
-  DEBUG("Running %s\n", program.toStdString().c_str());
+  DEBUG(lua, "Running %s\n", program.toStdString().c_str());
 
   int top = lua_gettop(L);
 
@@ -122,23 +121,23 @@ QString LUA::runParser(QString program)
                      program.toStdString().c_str(),
                      program.size(),
                      "parser")) {
-    error(lua_tostring(L, lua_gettop(L)));
+    ERROR(lua, "%s", lua_tostring(L, lua_gettop(L)));
     return false;
   }
 
   // Run the loaded code
   if(lua_pcall(L, 0, LUA_MULTRET, 0)) {
-    error(lua_tostring(L, lua_gettop(L)));
+    ERROR(lua, "%s", lua_tostring(L, lua_gettop(L)));
     return false;
   }
 
   if(top != lua_gettop(L) - 1) {
-    error("Program did not return a single value.\n");
+    ERROR(lua, "Program did not return a single value.\n");
     return false;
   }
 
   if(lua_isstring(L, lua_gettop(L)) == false) {
-    error("Program did not return a boolean value.\n");
+    ERROR(lua, "Program did not return a boolean value.\n");
     return false;
   }
 
@@ -151,11 +150,11 @@ QString LUA::runParser(QString program)
 bool LUA::runScript(QString script, Widget *widget, QString name)
 {
   if(L == NULL) {
-    error("LUA state not initialized!");
+    ERROR(lua, "LUA state not initialized!");
     return false;
   }
 
-  DEBUG("Running %s script %s on %s widget.\n",
+  DEBUG(lua, "Running %s script %s on %s widget.\n",
         name.toStdString().c_str(),
         script.toStdString().c_str(),
         widget?widget->name().toStdString().c_str():"NULL");
@@ -169,26 +168,24 @@ bool LUA::runScript(QString script, Widget *widget, QString name)
                      script.toStdString().c_str(),
                      script.size(),
                      name.toStdString().c_str())) {
-    error(lua_tostring(L, lua_gettop(L)));
+    ERROR(lua, "%s", lua_tostring(L, lua_gettop(L)));
     return false;
   }
 
   // Run the loaded code
   if(lua_pcall(L, 0, LUA_MULTRET, 0)) {
-    error(lua_tostring(L, lua_gettop(L)));
+    ERROR(lua, "%s", lua_tostring(L, lua_gettop(L)));
     return false;
   }
 
   return true;
 }
 
-void LUA::error(QString message)
-{
-  printf("LUA ERROR: %s\n", message.toStdString().c_str());
-}
-
 Widget *LUA::getWidget(QString name)
 {
   if(*rootwidget) return (*rootwidget)->findWidget(name, true);
-  else return NULL;
+  else {
+    WARN(lua, "Could not find widget '%s'", name.toStdString().c_str());
+    return NULL;
+  }
 }
diff --git a/client/lua.h b/client/lua.h
index d94bd15..bacce14 100644
--- a/client/lua.h
+++ b/client/lua.h
@@ -43,8 +43,6 @@ public:
 
   bool runScript(QString script, Widget *widget, QString name = "");
 
-  void error(QString message);
-
   Widget *getWidget(QString name);
 
   void clear();
diff --git a/client/macrowindow.cc b/client/macrowindow.cc
index f0565c9..49f3782 100644
--- a/client/macrowindow.cc
+++ b/client/macrowindow.cc
@@ -37,19 +37,18 @@
 #include "lua.h"
 #include "resumewidget.h"
 
+#include "debug.h"
+
 extern QString cpr;
 extern QString user;
 extern QString host;
 extern quint16 port;
 
-//#define DEBUG(fmt...) printf("MacroWindow (%p)",this);printf(fmt);fflush(stdout)
-#define DEBUG(ftm...)
-
 MacroWindow::MacroWindow(NetCom &n, QDomNode &xml_doc, QString templ,
                          bool collapsed, bool compact)
   : Collapser(), netcom(n)
 {
-  DEBUG("macrowindow %p\n", this);
+  DEBUG(macrowindow, "Constructor %p\n", this);
 
   mainwidget = NULL;
   lua = new LUA(&mainwidget);
@@ -114,7 +113,8 @@ void MacroWindow::initMacro(QDomNode &node)
   } else if(elem.tagName() == "widgets") {
 
     if(mainwidget) {
-      DEBUG("WARNING: mainwidget already exists! Calling clear().\n");
+      WARN(macrowindow,
+           "WARNING: mainwidget already exists! Calling clear().\n");
       clear();
     }
 
@@ -281,7 +281,7 @@ void MacroWindow::toggleMacro()
 
 void MacroWindow::macroChanged()
 {
-  DEBUG("This macro was changed!\n");
+  DEBUG(macrowindow, "This macro was changed!\n");
   emit macroHasChanged();
   waschanged = true;
 }
@@ -298,7 +298,7 @@ void MacroWindow::setActive(bool active)
 
 void MacroWindow::clear()
 {
-  DEBUG("clear %p\n", this);
+  DEBUG(macrowindow, "clear %p\n", this);
   setExpandedWidget(NULL);
 
   if(mainwidget) delete mainwidget;
@@ -309,6 +309,6 @@ void MacroWindow::clear()
 
 void MacroWindow::collapsed()
 {
-  DEBUG("collapsed %p\n", this);
+  DEBUG(macrowindow, "collapsed %p\n", this);
   clear();
 }
diff --git a/client/mainwindow.cc b/client/mainwindow.cc
index f7cb173..e8a7f51 100644
--- a/client/mainwindow.cc
+++ b/client/mainwindow.cc
@@ -42,10 +42,25 @@
 #include <QAction>
 #include <QEvent>
 #include <QCloseEvent>
+#include <QLabel>
 
 #include "macrodrawer.h"
 #include "macrowindow.h"
 
+#include "debug.h"
+
+class Dbg : public QLabel {
+public:
+  Dbg() {
+    setText("dbg");
+  }
+
+  void mousePressEvent(QMouseEvent *)
+  {
+    dbg_toggle();
+  }
+};
+
 MainWindow::MainWindow(QString cpr, QString templ, QString host,
                        quint16 port, QString user)
   : QMainWindow(0, Qt::WindowContextHelpButtonHint),
@@ -63,6 +78,7 @@ MainWindow::MainWindow(QString cpr, QString templ, QString host,
 
   QStatusBar *status = statusBar();
   status->addPermanentWidget(new QLabel("Pracro v."VERSION));
+  status->addPermanentWidget(new Dbg());
 
   QToolBar *toolbar = addToolBar("controls");
   toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
@@ -171,6 +187,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
 
     event->accept();
     if(viewer) viewer->close();
+    dbg_free();
   } else {
     event->ignore();
   }
diff --git a/client/netcom.cc b/client/netcom.cc
index 02c5704..d04493f 100644
--- a/client/netcom.cc
+++ b/client/netcom.cc
@@ -37,6 +37,8 @@
 
 #include "widgets/widget.h"
 
+#include "debug.h"
+
 #ifdef USE_SSL
 #include <QMessageBox>
 #include <QList>
@@ -48,9 +50,6 @@
 #endif
 #endif
 
-//#define DEBUG(fmt...) printf(fmt)
-#define DEBUG(ftm...)
-
 NetCom::NetCom(QString host, quint16 port)
 {
   //
@@ -85,7 +84,7 @@ void NetCom::replyFinished(QNetworkReply *reply)
 QDomDocument NetCom::makeTransfer(QDomDocument &doc,
                                   bool commit, bool lockgui, bool discard)
 {
-  DEBUG("\nMaking transfer:\n%s", doc.toString().toStdString().c_str());
+  DEBUG(netcom, "Making transfer:\n%s", doc.toString().toStdString().c_str());
 
   if(lockgui && qApp->activeWindow()) qApp->activeWindow()->setEnabled(false);
   if(lockgui) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
@@ -112,13 +111,13 @@ QDomDocument NetCom::makeTransfer(QDomDocument &doc,
   QDomDocument res_doc;
   res_doc.setContent(data);
 
-  DEBUG("\nRecieved reponse:\n%s", data.data());
+  DEBUG(netcom, "Recieved reponse:\n%s", data.data());
 
-  DEBUG("\nRecieved reponse (Parsed):\n%s", res_doc.toByteArray().data());
+  DEBUG(netcom, "Recieved reponse (Parsed):\n%s", res_doc.toByteArray().data());
 
   if(reply->hasRawHeader("SessionID")) {
     sessionid = reply->rawHeader("SessionID");
-    DEBUG("SESSION ID: %s\n", sessionid.toStdString().c_str());
+    LOG(netcom, "SESSION ID: %s\n", sessionid.toStdString().c_str());
   }
 
   if(lockgui) QApplication::restoreOverrideCursor();
@@ -192,10 +191,10 @@ QDomDocument NetCom::send(QVector< Widget* > widgets, QString templ,
   //  the commit string
   QVector< Widget* >::iterator i = widgets.begin();
   while(i != widgets.end()) {
-    DEBUG("W = ");
+    DEBUG(netcom, "W = ");
     if(*i) {
       Widget* w = *i;
-      DEBUG("name: %s val: %s", w->name().toStdString().c_str(),
+      DEBUG(netcom, "name: %s val: %s", w->name().toStdString().c_str(),
             w->value().toStdString().c_str());
       if(w->enabled() && w->name() != "" && w->local() == false) {
         QDomElement field_elem = doc.createElement("field");
@@ -204,7 +203,6 @@ QDomDocument NetCom::send(QVector< Widget* > widgets, QString templ,
         commit_elem.appendChild(field_elem);
       }
     }
-    DEBUG("\n");
     i++;
   }
   
diff --git a/client/pracro.cc b/client/pracro.cc
index 76cd4df..ded56bc 100644
--- a/client/pracro.cc
+++ b/client/pracro.cc
@@ -39,6 +39,8 @@
 #include "mainwindow.h"
 #include "viewer.h"
 
+#include "debug.h"
+
 #define CPR_DEFAULT ""
 #define MACRO_DEFAULT ""
 #define TEMPLATE_DEFAULT ""
@@ -94,6 +96,9 @@ int main(int argc, char *argv[])
 {
   QApplication app(argc, argv);
 
+  dbg_init();
+  dbg_show();
+
   QString macro = MACRO_DEFAULT;
   QString templ = TEMPLATE_DEFAULT;
   bool show_viewer = false;
diff --git a/client/widgets/widget.cc b/client/widgets/widget.cc
index d85d1ad..231359c 100644
--- a/client/widgets/widget.cc
+++ b/client/widgets/widget.cc
@@ -33,8 +33,8 @@
 #include <QLayout>
 #include <QObject>
 
-//#define DEBUG(fmt...) printf(fmt)
-#define DEBUG(ftm...)
+#define DEBUG(fmt...) printf("Widget (%p)", this); printf(fmt); fflush(stdout)
+//#define DEBUG(ftm...)
 
 Widget::Widget(QDomNode &node, MacroWindow *macrowindow)
 {
@@ -64,9 +64,8 @@ Widget::Widget(QDomNode &node, MacroWindow *macrowindow)
   lazy_value = elem.attribute("value", "");
   lazy_source = elem.attribute("prefilled", "prefilled");
 
-  if((hasOnChangeEvent = elem.hasAttribute("onChange"))) {
-    onChangeEventScript = elem.attribute("onChange");
-  }
+  hasOnChangeEvent = elem.hasAttribute("onChange");
+  onChangeEventScript = elem.attribute("onChange", "");
 
   is_valid = true;
 
-- 
cgit v1.2.3