summaryrefslogtreecommitdiffstats
path: root/quanta/components/debugger/dbgp
diff options
context:
space:
mode:
Diffstat (limited to 'quanta/components/debugger/dbgp')
-rw-r--r--quanta/components/debugger/dbgp/Makefile.am17
-rw-r--r--quanta/components/debugger/dbgp/dbgpnetwork.cpp314
-rw-r--r--quanta/components/debugger/dbgp/dbgpnetwork.h76
-rw-r--r--quanta/components/debugger/dbgp/dbgpsettings.cpp44
-rw-r--r--quanta/components/debugger/dbgp/dbgpsettings.h35
-rw-r--r--quanta/components/debugger/dbgp/dbgpsettingss.ui728
-rw-r--r--quanta/components/debugger/dbgp/qbytearrayfifo.cpp76
-rw-r--r--quanta/components/debugger/dbgp/qbytearrayfifo.h43
-rw-r--r--quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp1042
-rw-r--r--quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop44
-rw-r--r--quanta/components/debugger/dbgp/quantadebuggerdbgp.h166
11 files changed, 2585 insertions, 0 deletions
diff --git a/quanta/components/debugger/dbgp/Makefile.am b/quanta/components/debugger/dbgp/Makefile.am
new file mode 100644
index 00000000..fbff3bdf
--- /dev/null
+++ b/quanta/components/debugger/dbgp/Makefile.am
@@ -0,0 +1,17 @@
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = quantadebuggerdbgp.la
+
+quantadebuggerdbgp_la_SOURCES = quantadebuggerdbgp.cpp dbgpsettingss.ui \
+ dbgpsettings.cpp dbgpnetwork.cpp qbytearrayfifo.cpp
+quantadebuggerdbgp_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+quantadebuggerdbgp_la_LIBADD = ../interfaces/libdebuggerinterface.la $(LIB_KPARTS)
+kde_services_DATA = quantadebuggerdbgp.desktop
+
+INCLUDES = -I$(top_srcdir)/quanta/components/debugger \
+ -I$(top_srcdir)/quanta/components/debugger/interfaces -I$(top_srcdir)/quanta/components/debugger/dbgp \
+ -I$(top_srcdir)/quanta/project -I$(top_srcdir)/quanta/utility $(all_includes)
+
+
+noinst_HEADERS = dbgpsettings.h quantadebuggerdbgp.h dbgpnetwork.h \
+ qbytearrayfifo.h
diff --git a/quanta/components/debugger/dbgp/dbgpnetwork.cpp b/quanta/components/debugger/dbgp/dbgpnetwork.cpp
new file mode 100644
index 00000000..87306448
--- /dev/null
+++ b/quanta/components/debugger/dbgp/dbgpnetwork.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2005 by Linus McCabe, <Linus@McCabe.nu>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "dbgpnetwork.h"
+
+#include <kserversocket.h>
+#include <kstreamsocket.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+DBGpNetwork::DBGpNetwork()
+: QObject()
+{
+ m_socket = NULL;
+ m_server = NULL;
+ m_datalen = -1;
+ m_transaction_id = 0;
+}
+
+DBGpNetwork::~DBGpNetwork()
+{
+}
+
+void DBGpNetwork::sessionStart(bool useproxy, const QString& server, const QString & service)
+{
+
+ kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl;
+ m_useproxy = useproxy;
+
+ if(m_useproxy)
+ {
+ if(m_socket)
+ {
+// m_socket->setBufferSize(-1);
+ connect(m_socket, SIGNAL(gotError(int)), this, SLOT(slotError(int)));
+ connect(m_socket, SIGNAL(connected(const KResolverEntry &)), this, SLOT(slotConnected(const KNetwork::KResolverEntry &)));
+ connect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed()));
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
+ connect(m_socket, SIGNAL(destroyed()), this, SLOT(slotSocketDestroyed()));
+ m_socket->connect();
+ emit active(false);
+ kdDebug(24002) << k_funcinfo << ", proxy:" << server << ", " << service << endl;
+ }
+ }
+ else
+ {
+ if(!m_server)
+ {
+ m_server = new KNetwork::KServerSocket(service);
+
+ m_server->setAddressReuseable(true);
+ connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept()));
+ connect(m_server, SIGNAL(gotError(int)), this, SLOT(slotError(int)));
+
+ if(m_server->listen())
+ {
+ emit active(true);
+ emit networkError(i18n("Listening on port %1").arg(service), true);
+ }
+ else
+ {
+ delete m_server;
+ m_server = NULL;
+ emit active(false);
+ emit networkError(i18n("Unable to listen on port %1").arg(service), true);
+ }
+ }
+ }
+}
+
+
+void DBGpNetwork::sessionEnd()
+{
+ // Close socket
+ if(m_socket)
+ {
+ m_socket->flush();
+ disconnect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed()));
+ if (m_socket)
+ m_socket->close();
+ delete m_socket;
+ m_socket = 0L;
+ }
+
+ // Close the server
+ if(m_server)
+ {
+ m_server->close();
+ delete m_server;
+ m_server = NULL;
+ }
+
+ // Fake a connection closed signal
+ slotConnectionClosed();
+ emit active(false);
+}
+
+
+// Socket errors
+void DBGpNetwork::slotError(int)
+{
+ kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl;
+ if(m_socket)
+ {
+ kdDebug(24002) << k_funcinfo << ", " << m_socket->errorString() << endl;
+ if(m_socket->error() == KNetwork::KSocketBase::RemotelyDisconnected)
+ {
+ slotConnectionClosed();
+ emit networkError(i18n("Disconnected from remote host"), true);
+ return;
+ }
+
+ if(m_socket->error())
+ {
+ emit networkError(m_socket->errorString(), true);
+ }
+ }
+
+ if(m_server && m_server->error())
+ {
+ kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl;
+ emit networkError(m_server->errorString(), true);
+ }
+}
+
+// slotReadyAccept
+void DBGpNetwork::slotReadyAccept()
+{
+
+ kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl;
+ if(!m_socket)
+ {
+ disconnect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept()));
+
+ m_socket = (KNetwork::KStreamSocket *)m_server->accept(); // KSocketServer returns a KStreamSocket (!)
+ if(m_socket)
+ {
+ kdDebug(24002) << k_funcinfo << ", ready" << ", m_socket" << m_socket << endl;
+ m_socket->enableRead(true);
+ m_socket->setAddressReuseable(true);
+// m_socket->setSocketFlags(KExtendedSocket::inetSocket | KExtendedSocket::inputBufferedSocket);
+// m_socket->setBufferSize(-1);
+ connect(m_socket, SIGNAL(gotError(int)), this, SLOT(slotError(int)));
+ connect(m_socket, SIGNAL(connected(const KResolverEntry &)), this, SLOT(slotConnected(const KResolverEntry &)));
+ connect(m_socket, SIGNAL(closed()), this, SLOT(slotConnectionClosed()));
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
+ connected();
+ }
+ else
+ {
+ kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl;
+ }
+ }
+
+}
+
+// Connection established
+void DBGpNetwork::slotConnected(const KResolverEntry &)
+{
+ connected();
+}
+
+bool DBGpNetwork::isConnected()
+{
+ return m_socket != NULL && m_socket->state() == KNetwork::KClientSocketBase::Connected;
+}
+
+bool DBGpNetwork::isActive()
+{
+ return
+ (m_socket != NULL && m_socket->state() == KNetwork::KClientSocketBase::Connected)
+ || (m_server != NULL);
+}
+
+void DBGpNetwork::connected()
+{
+
+ kdDebug(24002) << k_funcinfo << endl;
+ emit connected(true);
+// debuggerInterface()->enableAction("debug_disconnect", true);
+// debuggerInterface()->enableAction("debug_request", false);
+}
+
+// Connectio closed
+void DBGpNetwork::slotConnectionClosed()
+{
+ kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl;
+
+ // Check if we have more data to read
+ slotReadyRead();
+// kdDebug(24002) << k_funcinfo << "buffer: " << m_buffer << endl;
+
+ if(m_socket)
+ {
+ m_socket->flush();
+ m_socket->close();
+ delete m_socket;
+ m_socket = NULL;
+ }
+
+ if(m_server)
+ connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept()));
+
+ // Disable all session related actions and enable connection action
+ emit connected(false);
+ emit active(m_server != NULL);
+
+}
+
+
+//called when m_socket is destroyed either by deleting it or if XDebug disconnects from the client
+void DBGpNetwork::slotSocketDestroyed()
+{
+ kdDebug(24002) << k_funcinfo << " , m_server: " << m_server << ", m_socket" << m_socket << endl;
+
+ m_socket = NULL; //m_socket is already wrong, without this the app would crash on the next m_socket->close() or delete m_socket call.
+ slotConnectionClosed();
+}
+
+
+// Data from socket
+void DBGpNetwork::slotReadyRead()
+{
+
+ // Data from dbgp
+ while(m_socket && (m_socket->bytesAvailable() > 0 || m_fifo.length() >= (unsigned long)m_datalen))
+ {
+ int bytes;
+ QString data;
+
+ if(m_socket && m_socket->bytesAvailable() > 0 )
+ {
+ // Read all available bytes from socket and append them to the buffer
+ bytes = m_socket->bytesAvailable();
+ char* buffer = new char[bytes];
+ m_socket->readBlock(buffer, bytes);
+
+ // Put it in the fifo buffer
+ m_fifo.append(buffer, bytes);
+
+ delete[] buffer;
+ }
+
+ while(1)
+ {
+ // If datalen == -1, we didnt read the size yet, otherwise we're reading data.
+ if(m_datalen == -1)
+ {
+ bytes = m_fifo.find('\0');
+ if(bytes < 0)
+ break;
+
+ data = m_fifo.retrieve();
+ m_datalen = data.toLong();
+
+ }
+ if(m_datalen != -1 && (long)m_fifo.length() >= m_datalen + 1)
+ {
+ data = m_fifo.retrieve();
+ m_datalen = -1;
+ emit command(data);
+ }
+ else
+ break;
+ }
+ }
+}
+
+long DBGpNetwork::sendCommand(const QString & command)
+{
+ return sendCommand(command, "");
+}
+
+long DBGpNetwork::sendCommand(const QString & command, const QString & arguments)
+{
+ if(!isConnected())
+ return false;
+
+ m_transaction_id++;
+ QString commandline = command + QString(" -i %1").arg(m_transaction_id) + (!arguments.isEmpty() ? " " : "") + arguments;
+
+ kdDebug(24002) << k_funcinfo << ", sending: " << commandline << endl;
+
+ m_socket->writeBlock(commandline.latin1(), commandline.length() + 1); // Send string + NULL termination
+
+ return m_transaction_id;
+}
+
+long DBGpNetwork::sendCommand( const QString & command, const QString & arguments, const QString & data )
+{
+ QByteArrayFifo buffer;
+ buffer.append(data.ascii(), data.length());
+ return sendCommand(command, arguments + " -- " + buffer.base64Encoded());
+}
+
+// #include "dbgpnetwork.moc"
+
+#include "dbgpnetwork.moc"
diff --git a/quanta/components/debugger/dbgp/dbgpnetwork.h b/quanta/components/debugger/dbgp/dbgpnetwork.h
new file mode 100644
index 00000000..0651bc08
--- /dev/null
+++ b/quanta/components/debugger/dbgp/dbgpnetwork.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005 by Linus McCabe, <Linus@McCabe.nu>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef dbgpnetwork_H
+#define dbgpnetwork_H
+
+#include <kserversocket.h>
+#include <kstreamsocket.h>
+
+#include "qbytearrayfifo.h"
+
+//using namespace KNetwork;
+class KResolverEntry;
+
+class DBGpNetwork : public QObject
+{
+ Q_OBJECT
+
+ private:
+ KNetwork::KStreamSocket *m_socket;
+ KNetwork::KServerSocket *m_server;
+ QByteArrayFifo m_fifo;
+ bool m_useproxy;
+ long m_datalen;
+ long m_transaction_id;
+
+ void connected();
+
+ signals:
+ void active(bool isOnline);
+ void connected(bool isConnected);
+ void networkError(const QString &error, bool log);
+ void command(const QString& data);
+
+ public:
+ DBGpNetwork();
+ ~DBGpNetwork();
+
+ virtual void sessionStart(bool useproxy, const QString& server, const QString & service);
+ virtual void sessionEnd();
+
+ bool isConnected();
+ bool isActive();
+
+ long sendCommand(const QString & command);
+ long sendCommand(const QString & command, const QString & arguments);
+ long sendCommand(const QString & command, const QString & arguments, const QString & data);
+
+ public slots:
+ // Socket slots
+ void slotConnected(const KResolverEntry &);
+ void slotConnectionClosed();
+ void slotError(int);
+ void slotReadyRead();
+ void slotReadyAccept();
+ void slotSocketDestroyed();
+};
+
+
+#endif // dbgpnetwork_H
diff --git a/quanta/components/debugger/dbgp/dbgpsettings.cpp b/quanta/components/debugger/dbgp/dbgpsettings.cpp
new file mode 100644
index 00000000..80b7eaf1
--- /dev/null
+++ b/quanta/components/debugger/dbgp/dbgpsettings.cpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ dbgpsettings.cpp
+ -------------------
+ begin : 2004-04-05
+ copyright : (C) 2004 Linus McCabe <linus@mccabe.nu>
+ ***************************************************************************/
+
+/****************************************************************************
+ * *
+ * This program 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. *
+ * *
+ ***************************************************************************/
+
+
+#include "qlineedit.h"
+#include "qcheckbox.h"
+#include "dbgpsettings.h"
+#include <ktextbrowser.h>
+
+DBGpSettings::DBGpSettings(const QString &protocolversion)
+ : DBGpSettingsS(0, "DBGpSettings", false, 0)
+{
+ textAbout->setText(textAbout->text().replace("%PROTOCOLVERSION%", protocolversion));
+ connect(checkLocalProject, SIGNAL(toggled(bool)), this, SLOT(slotLocalProjectToggle(bool)));
+}
+
+DBGpSettings::~DBGpSettings()
+{
+}
+
+void DBGpSettings::slotLocalProjectToggle( bool localproject)
+{
+ lineServerBasedir->setEnabled(!localproject);
+ lineLocalBasedir->setEnabled(!localproject);
+}
+
+
+
+
+#include "dbgpsettings.moc"
+
diff --git a/quanta/components/debugger/dbgp/dbgpsettings.h b/quanta/components/debugger/dbgp/dbgpsettings.h
new file mode 100644
index 00000000..4f2721ff
--- /dev/null
+++ b/quanta/components/debugger/dbgp/dbgpsettings.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ dbgpsettings.h
+ -------------------
+ begin : 2005-08-01
+ copyright : (C) 2005 Linus McCabe <linus@mccabe.nu>
+ ***************************************************************************/
+
+/****************************************************************************
+ * *
+ * This program 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DBGPSETTINGS_H
+#define DBGPSETTINGS_H
+
+#include "dbgpsettingss.h"
+
+class DBGpSettings : public DBGpSettingsS
+{
+ Q_OBJECT
+
+ public:
+ DBGpSettings(const QString &protocolversion);
+ ~DBGpSettings();
+
+ public slots:
+ virtual void slotLocalProjectToggle(bool localproject);
+};
+
+#endif
+
diff --git a/quanta/components/debugger/dbgp/dbgpsettingss.ui b/quanta/components/debugger/dbgp/dbgpsettingss.ui
new file mode 100644
index 00000000..2b846a7e
--- /dev/null
+++ b/quanta/components/debugger/dbgp/dbgpsettingss.ui
@@ -0,0 +1,728 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DBGpSettingsS</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>DBGpSettingsS</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>569</width>
+ <height>467</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>DBGp Settings</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>Ca&amp;ncel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>Connection Settings</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblDebuggerServerListenPort</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Listen port:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>lineServerListenPort</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblRequest</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Request URL:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>lineStartSession</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>See "What's This?" for available variables</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>%afn - Filename of the current script
+%afd - Absolute directory of the current script
+%afp - Absolute path (directory + filename) of the current script
+
+%rfpd - Directory of the current script relative to project root
+%rfpp - Path of the current script relative to project root
+
+%rfdd - Directory of the current script relative to document root
+%rfdp - Path of the current script relative to document root
+
+%apd - Project root
+%add - Document root of current script</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Directory Mapping</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>lineServerBasedir</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblDebuggerServerBasedir</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Server basedir:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>lineLocalBasedir</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>checkLocalProject</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblDebuggerLocalBasedir</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Local basedir:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblLocalProject</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Local project:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="2" column="0">
+ <property name="name">
+ <cstring>groupBox3_2</cstring>
+ </property>
+ <property name="title">
+ <string>Profiling</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>lineProfilerFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>See "What's This?" for available variables</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Path to the profiler output
+%a - Appid as returned from the debugger
+%c - CRC32 of the initial filepath</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblRequest_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Profiler output:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblLocalProject_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Map profiler output:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>checkProfilerMapFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this checkbox is checked, the profiler output filename will be mapped using the basedirs just like the remote script files.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblLocalProject_2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Open automatically:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>checkProfilerAutoOpen</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>4</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this checkbox is checked, the profiler output will be opened automatically once the session ends.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Deb&amp;ug Behavior</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Error Handling</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="4" column="1">
+ <property name="name">
+ <cstring>checkBreakOnUserError</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>User errors</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="5" colspan="1">
+ <property name="name">
+ <cstring>lblBreakOn</cstring>
+ </property>
+ <property name="text">
+ <string>Break on:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>checkBreakOnUserWarning</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>User warnings</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>checkBreakOnUserNotice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>User notices</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>checkBreakOnNotice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Notices</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>checkBreakOnWarning</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>W&amp;arnings</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="title">
+ <string>Execution</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox" row="0" column="1" rowspan="1" colspan="3">
+ <item>
+ <property name="text">
+ <string>Pause</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Run</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image1</pixmap>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboDefaultExecutionState</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblDefaultExecutionMode</cstring>
+ </property>
+ <property name="text">
+ <string>Default mode:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer4_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;About</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;h4&gt;DBGp Plugin for Quanta +&lt;/h4&gt;</string>
+ </property>
+ </widget>
+ <widget class="KTextBrowser" row="1" column="0">
+ <property name="name">
+ <cstring>textAbout</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head&gt;&lt;meta name="qrichtext" content="1" /&gt;&lt;/head&gt;&lt;body style="font-size:10pt;font-family:Bitstream Vera Sans"&gt;
+&lt;p&gt;&lt;span style="font-weight:600"&gt;About&lt;/span&gt;&lt;/p&gt;
+&lt;p&gt;DBGp is a debugger protocol defined by the developers of Xdebug. This plugin integrates debuggers that supports the DBGp protocol with Quanta. &lt;/p&gt;
+&lt;p&gt;In order to use this plugin for PHP debugging, you need to get a supporting debugger. Currently, only &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; is tested.&lt;/p&gt;
+&lt;p&gt;For more info about Xdebug, please visit the Xdebug website at &lt;a href="http://xdebug.org"&gt;http://xdebug.org&lt;/a&gt; &lt;/p&gt;
+&lt;p&gt;&lt;span style="font-weight:600"&gt;Technical Details&lt;/span&gt;&lt;/p&gt;
+&lt;p&gt;This version of the debugger supports version %PROTOCOLVERSION% of the DBGp protocol. &lt;/p&gt;
+&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<images>
+ <image name="image0">
+ <data format="PNG" length="696">89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff610000027f49444154388d7d93df4b53611cc69ff73de7ccb375dcdad46d2e3269036d21c4420a0b898484e82a08a2a02238a41741dd77e14dff4074d521efbae8a61b2f6a892062604e53117165e28f864dd73adb999e3cdb79cfe9c25a9c4dfa5e3e3ccfe7fdfee02538a412830b226075c3b662804d006b9567a5d4b4d2a7d77a494d5002c81370c20075797dc7fd157804139f77445846a14898fe9a67ead38f4aff661d2031b81006a1e3a16053c7ddcb3e5c3cc5c1ebe1000046c5c6a7af3a86c776b1b2bef3c3cdb2373ebcb83a5e052406e725103a9388473a1e5d13d1e8e60f9b0c1566e1655245727a3b2f19cb5d13c3b7bfff71da43a16073c7bd4b024667b56aa0b7cb0b009858fca75deff1622367357d59d58764597e481203332238317be74ad8d7798ca2ffacbf6a4eceaa00e0d0dea554ac6feb50deaabbc15f635d3c806e9728f9fc6e865cc172b49c2b9875633c1bf34033fca00db6a495a33d3c805840a2c8692638426a00953a40a9dc0000a0820842f9180f80941987cd3c0717ef04bc598ac02354f0b80642c8c1f6096cca03d66a51b791ce37d7bd06007a45a80b7304d8370db82c3d4379564a31a350a404a0f45086a3dc0283c83358fbea5e80a5e7e8b4d2a713a60f53238b36afe630c75b54c45b5487d6eed3408d2c04333712e437b608009c93937e2634a5cec79ba3019febbf1dfc2c9631b594cb448cd19b216e2d55ddda0579245a165adf9f89f94e76b649203517b16d1be9cd5dccafa8997065f241982c4f2a8aa2395cbdf75fb5eac289218fe7c8adf6904b3ada7870b242c9c07ab6bc67e8ea48c89c7a1ee2d6161545d1809adf0800b22cbbbe99a7231a17ed21948f11d894587a26c0d273417e630b405e5194f25fff6f6493fb9b9d8e82910000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="229">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000000ac49444154388ded94c10dc33008453f5637ea061ec24cd2293289976083ce440f6d2262b012da5b95277188133f7f4560e0e2039dfc4eb39e621f164097894455c30280debbdb539c0180881c25dcd15a73f2509c8588c0cc3b795a4c445b0170bf65e596158f821969f19af4e8b02bf1f7e2b3890bf09eb8f145660223b63eb6a267ad00e209b47d6cfb39143f824be42e825aab5b4f27b6f2993483db2c223a4aa3db6b0633ff14e80f79015c6574466adcb13f0000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>DBGpSettingsS</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>DBGpSettingsS</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>tabWidget2</tabstop>
+ <tabstop>lineLocalBasedir</tabstop>
+ <tabstop>lineServerBasedir</tabstop>
+ <tabstop>lineServerListenPort</tabstop>
+ <tabstop>checkBreakOnNotice</tabstop>
+ <tabstop>checkBreakOnWarning</tabstop>
+ <tabstop>checkBreakOnUserNotice</tabstop>
+ <tabstop>checkBreakOnUserWarning</tabstop>
+ <tabstop>checkBreakOnUserError</tabstop>
+ <tabstop>comboDefaultExecutionState</tabstop>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+</tabstops>
+<slots>
+ <slot>slotLocalProjectToggled(bool)</slot>
+ <slot>checkLocalProject_toggled(bool)</slot>
+ <slot>slotLocalProjectToggle(bool)</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktextbrowser.h</includehint>
+</includehints>
+</UI>
diff --git a/quanta/components/debugger/dbgp/qbytearrayfifo.cpp b/quanta/components/debugger/dbgp/qbytearrayfifo.cpp
new file mode 100644
index 00000000..3060e43d
--- /dev/null
+++ b/quanta/components/debugger/dbgp/qbytearrayfifo.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005 by Linus McCabe, <Linus@McCabe.nu>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "qbytearrayfifo.h"
+#include <qcstring.h>
+#include <kmdcodec.h>
+
+QByteArrayFifo::QByteArrayFifo( )
+{
+ m_size = 0;
+ m_array.resize(0);
+}
+
+QString QByteArrayFifo::retrieve( )
+{
+ // See if there's a null teminator somewhere
+ QString str(m_array);
+ size_t size = str.length() + 1;
+
+ // Decrease size and move bytes to the beginning of the array
+ m_size -= size;
+ for(size_t cnt = 0; cnt < m_size; cnt++)
+ m_array[cnt] = m_array[cnt + size];
+
+ // Resize array, needed for find() to work
+ m_array.resize(m_size);
+
+ return str;
+}
+
+bool QByteArrayFifo::append(const char * chars, size_t size )
+{
+ // Resize the array, fail if not possible
+ if(!m_array.resize(m_size + size ))
+ return false;
+
+ // Copy the elements
+ for(size_t cnt = 0; cnt < size; cnt++)
+ m_array[cnt + m_size] = chars[cnt];
+
+ // Increase size var
+ m_size += size;
+
+ return true;
+}
+
+long QByteArrayFifo::find( char character )
+{
+ // If size is 0, find() outputs a warning for some reason
+ if(m_size == 0)
+ return -1;
+
+ return m_array.find(character);
+}
+
+QString QByteArrayFifo::base64Encoded()
+{
+ return KCodecs::base64Encode(m_array);
+}
+
diff --git a/quanta/components/debugger/dbgp/qbytearrayfifo.h b/quanta/components/debugger/dbgp/qbytearrayfifo.h
new file mode 100644
index 00000000..a422bc3d
--- /dev/null
+++ b/quanta/components/debugger/dbgp/qbytearrayfifo.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005 by Linus McCabe, <Linus@McCabe.nu>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef qbytearrayfifo_H
+#define qbytearrayfifo_H
+
+#include <qstring.h>
+#include <qcstring.h>
+
+class QByteArrayFifo
+{
+
+ public:
+ QByteArrayFifo();
+ bool append(const char * chars, size_t size);
+ QString retrieve();
+ QString base64Encoded();
+ long find(char character);
+ size_t length() { return m_size; }
+
+ private:
+ QByteArray m_array;
+ size_t m_size;
+
+};
+
+#endif // qbytearrayfifo_H
diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp b/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp
new file mode 100644
index 00000000..100ec9d3
--- /dev/null
+++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp
@@ -0,0 +1,1042 @@
+/***************************************************************************
+ quantadebuggerdbgp.cpp
+ -------------------
+ begin : 2004-03-12
+ copyright : (C) 2004 Linus McCabe <linus@mccabe.nu>
+ ***************************************************************************/
+
+/****************************************************************************
+ * *
+ * This program 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. *
+ * *
+ ***************************************************************************/
+
+#include <errno.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qfile.h>
+#include <qlineedit.h>
+#include <qmap.h>
+#include <qregexp.h>
+#include <qslider.h>
+#include <qstring.h>
+
+#include <stdarg.h>
+
+#include "debuggerclient.h"
+#include "quantadebuggerdbgp.h"
+#include "debuggerinterface.h"
+#include "debuggerbreakpoint.h"
+#include "dbgpsettings.h"
+#include "debuggervariable.h"
+#include "variableslistview.h"
+#include "pathmapper.h"
+
+
+
+K_EXPORT_COMPONENT_FACTORY( quantadebuggerdbgp,
+ KGenericFactory<QuantaDebuggerDBGp>("quantadebuggerdbgp"))
+
+const char QuantaDebuggerDBGp::protocolversion[] = "1.0";
+
+QuantaDebuggerDBGp::QuantaDebuggerDBGp (QObject *parent, const char*, const QStringList&)
+ : DebuggerClient (parent, "DBGp")
+{
+ // Create a socket object and set up its signals
+ m_errormask = 1794;
+ m_supportsasync = false;
+ m_defaultExecutionState = Starting;
+ setExecutionState(m_defaultExecutionState);
+ emit updateStatus(DebuggerUI::NoSession);
+
+ connect(&m_network, SIGNAL(command(const QString&)), this, SLOT(processCommand(const QString&)));
+ connect(&m_network, SIGNAL(active(bool)), this, SLOT(slotNetworkActive(bool)));
+ connect(&m_network, SIGNAL(connected(bool)), this, SLOT(slotNetworkConnected(bool)));
+ connect(&m_network, SIGNAL(networkError(const QString &, bool)), this, SLOT(slotNetworkError(const QString &, bool)));
+
+}
+
+
+QuantaDebuggerDBGp::~QuantaDebuggerDBGp ()
+{
+
+// kdDebug(24002) << k_funcinfo << endl;
+
+ m_network.sessionEnd();
+}
+
+void QuantaDebuggerDBGp::slotNetworkActive(bool active)
+{
+ // debuggerInterface() might not be available, for example from project dialog
+ if(!debuggerInterface())
+ return;
+
+ debuggerInterface()->enableAction("debug_request", active);
+ debuggerInterface()->enableAction("debug_connect", !active);
+ debuggerInterface()->enableAction("debug_disconnect", active);
+
+ setExecutionState(m_defaultExecutionState);
+
+ if(active)
+ emit updateStatus(DebuggerUI::AwaitingConnection);
+ else
+ emit updateStatus(DebuggerUI::NoSession);
+
+}
+
+void QuantaDebuggerDBGp::slotNetworkConnected(bool connected)
+{
+ // debuggerInterface() might not be available, for example from project dialog
+ if(!debuggerInterface())
+ return;
+
+ m_active = connected;
+
+ debuggerInterface()->enableAction("debug_run", connected);
+ debuggerInterface()->enableAction("debug_leap", connected);
+ debuggerInterface()->enableAction("debug_pause", connected);
+ debuggerInterface()->enableAction("debug_kill", connected);
+
+ debuggerInterface()->enableAction("debug_stepinto", connected);
+ debuggerInterface()->enableAction("debug_stepover", connected);
+ debuggerInterface()->enableAction("debug_stepout", connected);
+
+ debuggerInterface()->setActiveLine("", 0);
+ if(connected)
+ emit updateStatus(DebuggerUI::Connected);
+ else
+ {
+ setExecutionState(m_defaultExecutionState);
+ emit updateStatus(DebuggerUI::AwaitingConnection);
+
+ profilerOpen(false);
+ }
+
+}
+
+void QuantaDebuggerDBGp::slotNetworkError(const QString &errormsg, bool log)
+{
+ debuggerInterface()->showStatus(errormsg, log);
+}
+
+
+// Try to make a connection to the dbgp server
+void QuantaDebuggerDBGp::startSession()
+{
+ kdDebug(24002) << k_funcinfo << endl;
+
+ m_network.sessionStart(m_useproxy, m_serverHost, m_useproxy ? m_serverPort : m_listenPort);
+// setExecutionState(Starting);
+}
+
+
+void QuantaDebuggerDBGp::endSession()
+{
+
+ kdDebug(24002) << k_funcinfo << endl;
+
+ // Close the socket
+ m_network.sessionEnd();
+
+// debuggerInterface()->enableAction("debug_request", false);
+// debuggerInterface()->enableAction("debug_run", false);
+// debuggerInterface()->enableAction("debug_leap", false);
+// debuggerInterface()->enableAction("debug_pause", false);
+
+}
+
+
+// Change executionstate of the script
+void QuantaDebuggerDBGp::setExecutionState( const State & state, bool forcesend )
+{
+ if(m_executionState != state || forcesend)
+ {
+ if(state == Running)
+ m_network.sendCommand("run");
+ else if (state == Break)
+ m_network.sendCommand("break");
+ }
+ m_executionState = state;
+
+ if(debuggerInterface()) {
+ // The run action will be active if we're started, stopped or paused
+ debuggerInterface()->enableAction("debug_run", m_executionState == Break || m_executionState == Starting || m_executionState == Stopped);
+
+ // The pause action will be enabled if we're running and either supports async or we're not connected (ie will start running)
+ debuggerInterface()->enableAction("debug_pause", m_executionState == Running && (m_supportsasync || !isActive())) ;
+
+ // Kill is active if we're paused, just started of the debugger supports async, as long as we have an active session
+ debuggerInterface()->enableAction("debug_kill", isActive() && (m_executionState == Break || (m_executionState == Running && m_supportsasync) || m_executionState == Starting || m_executionState == Stopping ));
+
+ // These are only activated when we have an active seesion and are paused
+ debuggerInterface()->enableAction("debug_stepinto", isActive() && (m_executionState == Break || m_executionState == Starting ));
+ debuggerInterface()->enableAction("debug_stepout", isActive() && (m_executionState == Break || m_executionState == Starting));
+ debuggerInterface()->enableAction("debug_stepover", isActive() && (m_executionState == Break || m_executionState == Starting));
+ }
+
+}
+
+// Change executionstate of the script
+void QuantaDebuggerDBGp::setExecutionState(const QString &state)
+{
+ kdDebug(24002) << k_funcinfo << state << endl;
+
+ if(state == "starting")
+ {
+ setExecutionState(Starting);
+ emit updateStatus(DebuggerUI::Paused);
+ }
+ else if(state == "stopping")
+ {
+ setExecutionState(Stopping);
+ emit updateStatus(DebuggerUI::Paused);
+ m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket
+ }
+ else if(state == "stopped")
+ {
+ setExecutionState(Stopped);
+ emit updateStatus(DebuggerUI::Paused);
+ m_network.slotSocketDestroyed(); //XDebug disconnects when stopped and destroys our socket
+ }
+ else if(state == "running")
+ {
+ setExecutionState(Running);
+ emit updateStatus(DebuggerUI::Running);
+ }
+ else if(state == "break")
+ {
+ setExecutionState(Break);
+ emit updateStatus(DebuggerUI::Paused);
+ }
+
+}
+
+// Return capabilities of dbgp
+const uint QuantaDebuggerDBGp::supports(DebuggerClientCapabilities::Capabilities cap)
+{
+ switch(cap)
+ {
+ case DebuggerClientCapabilities::LineBreakpoints:
+// case DebuggerClientCapabilities::ConditionalBreakpoints:
+ case DebuggerClientCapabilities::StartSession:
+ case DebuggerClientCapabilities::EndSession:
+ case DebuggerClientCapabilities::Kill:
+ case DebuggerClientCapabilities::Pause:
+ case DebuggerClientCapabilities::Run:
+ //case DebuggerClientCapabilities::Skip:
+ case DebuggerClientCapabilities::StepOut:
+ case DebuggerClientCapabilities::StepInto:
+ case DebuggerClientCapabilities::StepOver:
+ case DebuggerClientCapabilities::Watches:
+ case DebuggerClientCapabilities::VariableSetValue:
+ case DebuggerClientCapabilities::ProfilerOpen:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
+// Process a dbgp command
+void QuantaDebuggerDBGp::processCommand(const QString& datas)
+{
+ kdDebug(24002) << k_lineinfo << datas.left(50) << " (" << datas.length() << " bytes)" << endl;
+
+ QDomDocument data;
+ data.setContent(datas);
+ kdDebug(24002) << datas << endl;
+
+ // Did we get a normal response?
+ if(data.elementsByTagName("response").count() > 0)
+ {
+ QDomNode response = data.elementsByTagName("response").item(0);
+ QString command = attribute(response, "command");
+
+ // Status command
+ if(command == "status")
+ setExecutionState(attribute(response, "status"));
+
+ // Callback stack
+ else if(command == "stack_get")
+ stackShow(response);
+
+ // Reply from a user execution action
+ else if(command == "break"
+ || command == "step_over"
+ || command == "step_into"
+ || command == "step_out")
+ {
+ handleError(response);
+ // If this is the acknoledge of a step command, request the call stack
+ m_network.sendCommand("stack_get");
+ setExecutionState(attribute(response, "status"));
+ handleError(response);
+ m_network.sendCommand("feature_get", "-n profiler_filename");
+ sendWatches();
+ }
+
+ // Run
+ else if(command == "run" )
+ {
+ setExecutionState(attribute(response, "status"));
+ handleError(response);
+ m_network.sendCommand("stack_get");
+ }
+
+ // Feature get replu
+ else if(command == "feature_get")
+ checkSupport(response);
+
+ // Reply after adding a breakpoint
+ else if(command == "breakpoint_set")
+ setBreakpointKey(response);
+
+ else if(command == "typemap_get")
+ typemapSetup(response);
+
+ else if(command == "property_get")
+ showWatch(response);
+
+ else if(command == "property_set")
+ propertySetResponse(response);
+ else if(command == "stop")
+ setExecutionState("stopped");
+
+ // Unknown command...
+ else
+ {
+ kdDebug(24002) << " * Unknown command: " << command << endl;
+ }
+ }
+ else if(data.elementsByTagName("init").count() > 0)
+ {
+ QDomNode init = data.elementsByTagName("init").item(0);
+ initiateSession(init);
+ return;
+ }
+ else
+ {
+ debuggerInterface()->showStatus(i18n("Unrecognized package: '%1%2'").arg(datas.left(50)).arg(datas.length() > 50 ? "..." : ""), true);
+
+ kdDebug(24002) << datas << endl;
+ }
+
+}
+
+void QuantaDebuggerDBGp::initiateSession(const QDomNode& initpacket)
+{
+ if(attribute(initpacket, "protocol_version") != protocolversion)
+ {
+ debuggerInterface()->showStatus(
+ i18n("The debugger for %1 uses an unsupported protocol version (%2)")
+ .arg(attribute(initpacket, "language"))
+ .arg(attribute(initpacket, "protocol_version"))
+ , true);
+
+ endSession();
+ return;
+ }
+ QString path = attribute(initpacket, "fileuri");
+ if (path.startsWith("file://"))
+ {
+ path.remove(0, 7);
+ }
+ debuggerInterface()->setActiveLine(mapServerPathToLocal(path), 0);
+
+ // Store some vars
+ m_initialscript = attribute(initpacket, "fileuri");
+ m_appid = attribute(initpacket, "appid");
+
+// setExecutionState(Starting);
+// m_network.sendCommand("feature_get", "-n encoding");
+ m_network.sendCommand("feature_get", "-n supports_async");
+// m_network.sendCommand("feature_get", "-n breakpoint_types");
+// m_network.sendCommand("feature_get", "-n profiler_filename");
+ m_network.sendCommand("feature_get", "-n breakpoint_set");
+ m_network.sendCommand("feature_get", "-n supports_postmortem");
+ m_network.sendCommand("typemap_get");
+ m_network.sendCommand("feature_get", "-n quanta_initialized");
+}
+
+void QuantaDebuggerDBGp::stackShow(const QDomNode&node)
+{
+ bool foundlowlevel = false;
+ BacktraceType type;
+ QString typestr;
+
+ // Clear backtrace
+ debuggerInterface()->backtraceClear();
+
+ // Add new one
+ for(QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling())
+ {
+ // Type isnt currently correct with xdebug
+// type = (attribute(child, "type") == "file" ? File : Eval);
+ typestr = attribute(child, "filename");
+ if(typestr.find(QRegExp(".*%28[0-9]+%29%20%3A%20eval")) >= 0)
+ type = Eval;
+ else
+ type = File;
+
+// kdDebug(24002) << " * Stck " << attribute(child, "level") << ": " << attribute(child, "type") << " (" << type << ") = " << attribute(child, "filename") << ", " << attribute(child, "lineno") << endl;
+
+
+ // If this is the lowest level and the type
+ if(type == File && !foundlowlevel)
+ {
+ foundlowlevel = true;
+ debuggerInterface()->setActiveLine(mapServerPathToLocal(attribute(child, "filename")), attribute(child, "lineno").toLong() - 1);
+ }
+
+ debuggerInterface()->backtraceShow(
+ attribute(child, "level").toLong(),
+ type,
+ attribute(child, "filename"),
+ attribute(child, "lineno").toLong() - 1, // Quanta lines are 0-based, DBGp is 1 based
+ attribute(child, "where"));
+ }
+
+}
+
+void QuantaDebuggerDBGp::checkSupport( const QDomNode & node )
+{
+ QString feature = attribute(node, "feature_name");
+ QString data = node.nodeValue();
+ if(feature == "supports_async")
+ m_supportsasync = data.toLong();
+
+ // if the debugger supports breakpoints, we have to send all current ones
+ else if(feature == "breakpoint_set"/* && data.toLong()*/)
+ debuggerInterface()->refreshBreakpoints();
+
+ // Our own feature, probably not available but then we know we're done initiating
+ else if(feature == "quanta_initialized" )
+ {
+ m_network.sendCommand("stack_get");
+ if(m_executionState != Break)
+ setExecutionState(m_executionState, true);
+ }
+
+}
+
+QString QuantaDebuggerDBGp::attribute(const QDomNode&node, const QString &attribute)
+{
+ return node.attributes().namedItem(attribute).nodeValue();
+}
+
+// Turn on/off actions related to a debugging session
+void QuantaDebuggerDBGp::debuggingState(bool enable)
+{
+ debuggerInterface()->enableAction("debug_kill", enable);
+ debuggerInterface()->enableAction("debug_stepout", enable);
+ debuggerInterface()->enableAction("debug_stepinto", enable);
+ debuggerInterface()->enableAction("debug_stepover", enable);
+ debuggerInterface()->enableAction("debug_skip", enable);
+}
+
+
+void QuantaDebuggerDBGp::sendWatches()
+{
+ for(QValueList<QString>::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it)
+ m_network.sendCommand("property_get", "-n " + (*it));
+}
+
+// Return name of debugger
+QString QuantaDebuggerDBGp::getName()
+{
+ return "DBGp"; // no i18n on the name
+}
+
+
+// Send HTTP Request
+void QuantaDebuggerDBGp::request()
+{
+ QString request;
+ request = debuggerInterface()->activeFileParts(m_startsession);
+
+ //if(request.startsWith(m_localBasedir, false))
+ // request.remove(0, m_localBasedir.length());
+
+ //request = m_startsession + request;
+ kdDebug(24002) << k_funcinfo << ", request: " << request << endl;
+ debuggerInterface()->sendRequest(request);
+}
+
+
+// Go as fast as possible and dont update current line or watches
+void QuantaDebuggerDBGp::run()
+{
+ setExecutionState(Running);
+// m_network.sendCommand("run");
+// m_network.sendCommand("status");
+}
+
+// Step into function
+void QuantaDebuggerDBGp::stepInto()
+{
+ m_network.sendCommand("step_into");
+}
+
+// Step over function
+void QuantaDebuggerDBGp::stepOver()
+{
+ if(m_executionState == Starting)
+ m_network.sendCommand("step_into");
+ else
+ m_network.sendCommand("step_over");
+}
+
+// Step out of function
+void QuantaDebuggerDBGp::stepOut()
+{
+ m_network.sendCommand("step_out");
+}
+
+
+// Kill the running script
+void QuantaDebuggerDBGp::kill()
+{
+ m_network.sendCommand("stop");
+}
+
+// Pause execution
+void QuantaDebuggerDBGp::pause()
+{
+ if(isActive())
+ setExecutionState(Break);
+ else
+ setExecutionState(Starting);
+// m_network.sendCommand("break");
+// m_network.sendCommand("status");
+}
+
+
+// Add a breakpoint
+void QuantaDebuggerDBGp::addBreakpoint (DebuggerBreakpoint* breakpoint)
+{
+ QString type;
+ if(breakpoint->type() == DebuggerBreakpoint::LineBreakpoint)
+ type = "line";
+ else if(breakpoint->type() == DebuggerBreakpoint::ConditionalTrue)
+ type = "conditional";
+ else
+ type = "watch";
+
+ long id = m_network.sendCommand(
+ "breakpoint_set",
+ "-t " + type +
+ " -f " + mapLocalPathToServer(breakpoint->filePath()) +
+ " -n " + QString::number(breakpoint->line() + 1)
+ , breakpoint->condition());
+
+ breakpoint->setKey(QString("id %1").arg(id));
+}
+
+void QuantaDebuggerDBGp::setBreakpointKey( const QDomNode & response )
+{
+ long id;
+
+ id = attribute(response, "transaction_id").toLong();
+ if(id > 0)
+ {
+ QString oldkey = QString("id %1").arg(id);
+ DebuggerBreakpoint *bp = debuggerInterface()->findDebuggerBreakpoint(oldkey);
+ if(bp)
+ debuggerInterface()->updateBreakpointKey(*bp, attribute(response, "id"));
+ }
+}
+
+
+// Clear a breakpoint
+void QuantaDebuggerDBGp::removeBreakpoint(DebuggerBreakpoint* bp)
+{
+ m_network.sendCommand("breakpoint_remove", "-d " + bp->key());
+}
+
+// A file was opened...
+void QuantaDebuggerDBGp::fileOpened(const QString&)
+{
+// sendCommand("reinitialize", 0);
+}
+
+// Watch a variable
+void QuantaDebuggerDBGp::addWatch(const QString & variable)
+{
+ if(m_watchlist.find(variable) == m_watchlist.end())
+ m_watchlist.append(variable);
+ m_network.sendCommand("property_get", "-n " + variable);
+}
+// Remove watch
+void QuantaDebuggerDBGp::removeWatch(DebuggerVariable *variable)
+{
+ if(m_watchlist.find(variable->name()) != m_watchlist.end())
+ m_watchlist.remove(m_watchlist.find(variable->name()));
+}
+
+// Show conditional breakpoint state
+void QuantaDebuggerDBGp::showCondition(const StringMap &)
+{
+
+// DebuggerBreakpoint *bp = debuggerInterface()->newDebuggerBreakpoint();
+// bp->setType(args["type"] == "true" ? DebuggerBreakpoint::ConditionalTrue : DebuggerBreakpoint::ConditionalChange);
+// bp->setCondition(args["expression"]);
+// bp->setFilePath(mapServerPathToLocal(args["filename"]));
+// bp->setClass(args["class"]);
+// bp->setFunction(args["function"]);
+// bp->setValue(args["value"]);
+//
+// bp->setState(DebuggerBreakpoint::Undefined);
+//
+// debuggerInterface()->showBreakpoint(*bp);
+}
+
+// Read configuration
+void QuantaDebuggerDBGp::readConfig(QDomNode node)
+{
+ // Server
+ QDomNode valuenode = node.namedItem("serverhost");
+ m_serverHost = valuenode.firstChild().nodeValue();
+ if(m_serverHost.isEmpty())
+ m_serverHost = "localhost";
+
+ valuenode = node.namedItem("serverport");
+ m_serverPort = valuenode.firstChild().nodeValue();
+ if(m_serverPort.isEmpty())
+ m_serverPort = "9000";
+
+ valuenode = node.namedItem("localbasedir");
+ m_localBasedir = valuenode.firstChild().nodeValue();
+ if(debuggerInterface())
+ debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir);
+
+ valuenode = node.namedItem("serverbasedir");
+ m_serverBasedir = valuenode.firstChild().nodeValue();
+ if(debuggerInterface())
+ debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir);
+
+ valuenode = node.namedItem("listenport");
+ m_listenPort = valuenode.firstChild().nodeValue();
+ if(m_listenPort.isEmpty())
+ m_listenPort = "9000";
+
+ valuenode = node.namedItem("startsession");
+ m_startsession = valuenode.firstChild().nodeValue();
+ if(m_startsession.isEmpty())
+ m_startsession = "http://localhost/%rfpp?XDEBUG_SESSION_START=1&XDEBUG_PROFILE";
+
+ valuenode = node.namedItem("defaultexecutionstate");
+ if(valuenode.firstChild().nodeValue().isEmpty())
+ m_defaultExecutionState = Starting;
+ else
+ {
+ if(valuenode.firstChild().nodeValue() == "break")
+ m_defaultExecutionState = Starting;
+ else
+ m_defaultExecutionState = Running;
+ }
+
+ valuenode = node.namedItem("useproxy");
+ m_useproxy = valuenode.firstChild().nodeValue() == "1";
+
+ valuenode = node.namedItem("errormask");
+ m_errormask = valuenode.firstChild().nodeValue().toLong();
+ kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl;
+
+ // Profiler
+ valuenode = node.namedItem("profilerfilename");
+ m_profilerFilename = valuenode.firstChild().nodeValue();
+ if(m_profilerFilename.isEmpty())
+ m_profilerFilename = "/tmp/cachegrind.out.%a";
+
+ valuenode = node.namedItem("profiler_autoopen");
+ m_profilerAutoOpen = valuenode.firstChild().nodeValue().toLong();
+
+ valuenode = node.namedItem("profiler_mapfilename");
+ m_profilerMapFilename = valuenode.firstChild().nodeValue().toLong();
+
+
+}
+
+
+// Show configuration
+void QuantaDebuggerDBGp::showConfig(QDomNode node)
+{
+ DBGpSettings set(protocolversion);
+
+ readConfig(node);
+
+ if(m_localBasedir == "/" && m_serverBasedir == "/")
+ set.checkLocalProject->setChecked(true);
+ set.lineLocalBasedir->setText(m_localBasedir);
+ set.lineServerBasedir->setText(m_serverBasedir);
+ set.lineServerListenPort->setText(m_listenPort);
+ set.lineStartSession->setText(m_startsession);
+ if(m_defaultExecutionState == Starting)
+ set.comboDefaultExecutionState->setCurrentItem(0);
+ else
+ set.comboDefaultExecutionState->setCurrentItem(1);
+
+ set.checkBreakOnNotice->setChecked(QuantaDebuggerDBGp::Notice & m_errormask);
+ set.checkBreakOnWarning->setChecked(QuantaDebuggerDBGp::Warning & m_errormask);
+ set.checkBreakOnUserNotice->setChecked(QuantaDebuggerDBGp::User_Notice & m_errormask);
+ set.checkBreakOnUserWarning->setChecked(QuantaDebuggerDBGp::User_Warning & m_errormask);
+ set.checkBreakOnUserError->setChecked(QuantaDebuggerDBGp::User_Error & m_errormask);
+
+ set.lineProfilerFilename->setText(m_profilerFilename);
+ if(m_profilerAutoOpen)
+ set.checkProfilerAutoOpen->setChecked(true);
+ if(m_profilerMapFilename)
+ set.checkProfilerMapFilename->setChecked(true);
+
+ if(set.exec() == QDialog::Accepted )
+ {
+ QDomElement el;
+
+ el = node.namedItem("localproject").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("localproject");
+ node.appendChild( el );
+ if(set.checkLocalProject->isChecked())
+ {
+ m_localBasedir = "/";
+ m_serverBasedir = "/";
+ }
+ else
+ {
+ m_localBasedir = set.lineLocalBasedir->text();
+ m_serverBasedir = set.lineServerBasedir->text();
+ if (!m_localBasedir.endsWith("/"))
+ m_localBasedir.append('/');
+ if (!m_serverBasedir.endsWith("/"))
+ m_serverBasedir.append('/');
+ }
+
+ el = node.namedItem("localbasedir").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("localbasedir");
+ node.appendChild( el );
+ el.appendChild( node.ownerDocument().createTextNode(m_localBasedir) );
+ if(debuggerInterface())
+ debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir);
+
+ el = node.namedItem("serverbasedir").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("serverbasedir");
+ node.appendChild( el );
+ if(debuggerInterface())
+ debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir);
+ el.appendChild( node.ownerDocument().createTextNode(m_serverBasedir) );
+
+ el = node.namedItem("listenport").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("listenport");
+ node.appendChild( el );
+ m_listenPort = set.lineServerListenPort->text();
+ el.appendChild( node.ownerDocument().createTextNode(m_listenPort) );
+
+ el = node.namedItem("startsession").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("startsession");
+ node.appendChild( el );
+ m_startsession = set.lineStartSession->text();
+ el.appendChild(node.ownerDocument().createTextNode(m_startsession));
+
+ el = node.namedItem("defaultexecutionstate").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("defaultexecutionstate");
+ node.appendChild( el );
+ if(set.comboDefaultExecutionState->currentItem() == 0)
+ {
+ m_defaultExecutionState = Starting;
+ el.appendChild(node.ownerDocument().createTextNode("break"));
+ }
+ else
+ {
+ m_defaultExecutionState = Running;
+ el.appendChild(node.ownerDocument().createTextNode("run"));
+
+ }
+
+ el = node.namedItem("errormask").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("errormask");
+ node.appendChild( el );
+ m_errormask = (set.checkBreakOnNotice->isChecked() ? QuantaDebuggerDBGp::Notice : 0)
+ + (set.checkBreakOnWarning->isChecked() ? QuantaDebuggerDBGp::Warning : 0)
+ + (set.checkBreakOnUserNotice->isChecked() ? QuantaDebuggerDBGp::User_Notice : 0)
+ + (set.checkBreakOnUserWarning->isChecked() ? QuantaDebuggerDBGp::User_Warning : 0)
+ + (set.checkBreakOnUserError->isChecked() ? QuantaDebuggerDBGp::User_Error : 0);
+ kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl;
+ el.appendChild( node.ownerDocument().createTextNode(QString::number(m_errormask)));
+
+ // Profiler
+ el = node.namedItem("profilerfilename").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("profilerfilename");
+ node.appendChild( el );
+ m_profilerFilename = set.lineProfilerFilename->text();
+ el.appendChild(node.ownerDocument().createTextNode(m_profilerFilename));
+
+ el = node.namedItem("profilerfilename_map").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("profilerfilename_map");
+ node.appendChild( el );
+ m_profilerMapFilename = (set.checkProfilerMapFilename->isChecked() ? true : false);
+ el.appendChild(node.ownerDocument().createTextNode(m_profilerMapFilename ? "1" : "0"));
+
+ el = node.namedItem("profiler_autoopen").toElement();
+ if (!el.isNull())
+ el.parentNode().removeChild(el);
+ el = node.ownerDocument().createElement("profiler_autoopen");
+ node.appendChild( el );
+ m_profilerAutoOpen = (set.checkProfilerAutoOpen->isChecked() ? true : false);
+ el.appendChild(node.ownerDocument().createTextNode(m_profilerAutoOpen ? "1" : "0"));
+ }
+}
+
+// Map a server filepath to a local one using project settings
+QString QuantaDebuggerDBGp::mapServerPathToLocal(const QString& serverpath)
+{
+ // Translate filename from server to local
+ return debuggerInterface()->Mapper()->mapServerPathToLocal(serverpath);
+}
+
+// Map a local filepath to a server one using project settings
+QString QuantaDebuggerDBGp::mapLocalPathToServer(const QString& localpath)
+{
+ // Translate filename from local to server
+ return debuggerInterface()->Mapper()->mapLocalPathToServer(localpath);
+}
+
+void QuantaDebuggerDBGp::variableSetValue(const DebuggerVariable &variable)
+{
+ m_network.sendCommand("property_set", "-n " + variable.name(), variable.value());
+
+ for(QValueList<QString>::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it)
+ if((*it) == variable.name())
+ {
+ m_network.sendCommand("property_get", "-n " + variable.name(), variable.value());
+ return;
+ }
+
+ return;
+}
+
+void QuantaDebuggerDBGp::profilerOpen()
+{
+ profilerOpen(true);
+}
+
+void QuantaDebuggerDBGp::profilerOpen(bool forceopen)
+{
+ QString profileroutput = m_profilerFilename;
+ profileroutput.replace("%a", m_appid);
+ profileroutput.replace("%c", m_initialscript);
+
+ if(m_profilerMapFilename)
+ profileroutput = mapServerPathToLocal( profileroutput);
+
+ bool exists = QFile::exists(profileroutput);
+ if(m_profilerAutoOpen || forceopen)
+ {
+ if(exists)
+ {
+ KRun *run = new KRun(profileroutput);
+ run->setAutoDelete(true);
+ }
+ else
+ {
+ if(forceopen)
+ KMessageBox::sorry(NULL, i18n("Unable to open profiler output (%1)").arg(profileroutput), i18n("Profiler File Error"));
+ else
+ debuggerInterface()->showStatus(i18n("Unable to open profiler output (%1)").arg(profileroutput), false);
+ }
+ }
+ else
+ {
+ debuggerInterface()->enableAction("debug_profiler_open", exists);
+ }
+}
+
+void QuantaDebuggerDBGp::typemapSetup( const QDomNode & typemapnode )
+{
+ /*
+ <map name="bool" type="bool" xsi:type="xsd:boolean"></map>
+ <map name="int" type="int" xsi:type="xsd:decimal"></map>
+ <map name="float" type="float" xsi:type="xsd:double"></map>
+ <map name="string" type="string" xsi:type="xsd:string"></map>
+ <map name="null" type="null"></map>
+ <map name="array" type="hash"></map>
+ <map name="object" type="object"></map>
+ <map name="resource" type="resource"></map>
+ */
+
+// // First defaults in case they are not sent (which seems to be the case with hash and xdebug)
+// m_variabletypes["bool"] = "bool";
+// m_variabletypes["int"] = "int";
+// m_variabletypes["float"] = "float";
+// m_variabletypes["string"] = "string";
+// m_variabletypes["null"] = "null";
+// m_variabletypes["array"] = "hash";
+// m_variabletypes["hash"] = "hash";
+// m_variabletypes["object"] = "object";
+// m_variabletypes["resource"] = "resource";
+
+ QDomNode child = typemapnode.firstChild();
+ while(!child.isNull())
+ {
+ if(child.nodeName() == "map")
+ {
+ m_variabletypes[attribute(child, "name")] = attribute(child, "type");
+ }
+ child = child.nextSibling();
+ }
+}
+
+
+void QuantaDebuggerDBGp::showWatch( const QDomNode & variablenode)
+{
+ debuggerInterface()->showVariable(buildVariable(variablenode.firstChild()));
+}
+
+void QuantaDebuggerDBGp::propertySetResponse( const QDomNode & setnode)
+{
+ if(attribute(setnode, "success") == "0")
+ {
+ debuggerInterface()->showStatus(i18n("Unable to set value of variable."), true);
+ }
+}
+
+
+DebuggerVariable* QuantaDebuggerDBGp::buildVariable( const QDomNode & variablenode)
+{
+ /*
+ Sample:
+ <property name="$arrayVar" fullname="$arrayVar" address="-1073754976" type="hash" children="1" numchildren="4">
+ <property name="birthyear" fullname="$arrayVar['birthyear']" address="135522364" type="int">
+ <![CDATA[1949]]>
+ </property>
+ <property name="songs" fullname="$arrayVar['songs']" address="135522236" type="hash" children="1" numchildren="3">
+ <property name="0" fullname="$arrayVar['songs'][0]" address="135522332" type="string" encoding="base64">
+ <![CDATA[SW5ub2NlbnQgV2hlbiBZb3UgRHJlYW0=]]>
+ </property>
+ <property name="1" fullname="$arrayVar['songs'][1]" address="135522300" type="string" encoding="base64">
+ <![CDATA[Q2hyaXN0bWFzIENhcmQgRnJvbSBBIEhvb2tlcg==]]>
+ </property>
+ </property>
+ </property>
+ */
+ QString name = attribute(variablenode, "name");
+ QString type = m_variabletypes[attribute(variablenode, "type")];
+
+ if(type == "int")
+ {
+ QString value = variablenode.firstChild().nodeValue();
+ return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Integer);
+ }
+ else if (type == "string")
+ {
+ QCString value = QCString(variablenode.firstChild().nodeValue());
+ value = KCodecs::base64Decode(value);
+ return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::String);
+ }
+ else if (type == "bool")
+ {
+ QString value = variablenode.firstChild().nodeValue();
+ return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Boolean);
+ }
+ else if (type == "resource")
+ {
+ QString value = variablenode.firstChild().nodeValue();
+ return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Resource);
+ }
+ else if (type == "float")
+ {
+ QString value = variablenode.firstChild().nodeValue();
+ return debuggerInterface()->newDebuggerVariable( name, value, DebuggerVariableTypes::Float);
+ }
+ else if (type == "null")
+ {
+ QString value = variablenode.firstChild().nodeValue();
+ return debuggerInterface()->newDebuggerVariable( name, "", DebuggerVariableTypes::Undefined);
+ }
+ else if (type == "hash" || type == "array" || type == "object")
+ {
+ QDomNode child = variablenode.firstChild();
+ QPtrList<DebuggerVariable> vars ;
+ while(!child.isNull())
+ {
+ DebuggerVariable* var = buildVariable( child);
+ if(var)
+ vars.append(var);
+
+ child = child.nextSibling();
+ }
+ if(type == "object")
+ return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Object);
+ else
+ return debuggerInterface()->newDebuggerVariable(name, vars, DebuggerVariableTypes::Array);
+ }
+
+ return debuggerInterface()->newDebuggerVariable(name, "", DebuggerVariableTypes::Error);;
+}
+
+void QuantaDebuggerDBGp::handleError(const QDomNode & statusnode )
+{
+
+ if(attribute(statusnode, "reason") == "error" || attribute(statusnode, "reason") == "aborted")
+ {
+ QDomNode errornode = statusnode.firstChild();
+ while(!errornode.isNull())
+ {
+ if(errornode.nodeName() == "error")
+ {
+ if(attribute(statusnode, "reason") == "error")
+ {
+ // Managable error
+ long error = attribute(errornode, "code").toLong();
+ if(!(error & m_errormask))
+ {
+ setExecutionState(Running);
+ }
+ else
+ {
+ emit updateStatus(DebuggerUI::HaltedOnError);
+ debuggerInterface()->showStatus(errornode.firstChild().nodeValue(), true);
+ }
+ break;
+ }
+ else
+ {
+ // Fatal error
+ emit updateStatus(DebuggerUI::HaltedOnError);
+ debuggerInterface()->showStatus(errornode.firstChild().nodeValue(), true);
+ }
+ }
+ errornode = errornode.nextSibling();
+ }
+ }
+
+}
+
+#include "quantadebuggerdbgp.moc"
diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop b/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop
new file mode 100644
index 00000000..3bebcf06
--- /dev/null
+++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop
@@ -0,0 +1,44 @@
+[Desktop Entry]
+Type=Service
+Name=DBGp
+Comment=DBGp debugger plugin, see http://xdebug.org
+Comment[bg]=Приставка на дебъгер DBGp, http://xdebug.org
+Comment[ca]=Connector de depuració DBGp, consulteu http://xdebug.org
+Comment[cs]=DBGp debugger plugin, viz http://xdebug.org
+Comment[da]=DBGp fejlretter-plugin, se http://xdebug.org
+Comment[de]=DBGp Debugger Plugin, siehe http://xdebug.org
+Comment[el]=Πρόσθετο αποσφαλματωτή DBGp, δείτε το http://xdebug.org
+Comment[es]=Extensión para el depurador DBGp, vea http://xdebug.org
+Comment[et]=DBGp siluri plugin, vaata http://xdebug.org
+Comment[eu]=DBGp araztailearen plugina, ikusi http://xdebug.org
+Comment[fa]=وصلۀ اشکال‌زدای DBGp، http://xdebug.org را ببینید
+Comment[fi]=DBGp-debugliitännäinen, katso http://xdebug.org
+Comment[fr]=Module de débogage DBGp, consultez http://xdebug.org
+Comment[ga]=Breiseán dífhabhtóra DBGp, féach ar http://xdebug.org
+Comment[gl]=Extensión DBGp para o depurador, vexa tamén http://xdebug.org
+Comment[hu]=DBGp nyomkövető modul, lásd: http://xdebug.org
+Comment[is]=DBGp aflúsunaríforrit. Sjá http://xdebug.org
+Comment[it]=Plugin di degub DBGp, vedi http://xdebug.org
+Comment[ja]=DBGp デバッガ プラグイン。http://xdebug.org をご覧ください。
+Comment[ka]=DBGp განბზიკვის მოდული, იხილეთ http://xdebug.org
+Comment[lt]=DBGp derintuvės priedas, žr. http://xdebug.org
+Comment[ms]=Plugin nyahpepijat DBGp, lihat http://xdebug.org
+Comment[nds]=Fehlersöök-Moduul för't DBGp, kiek bi http://xdebug.org
+Comment[ne]=DBGp त्रुटिमोचक प्लगइन, http://xdebug.org हेर्नुहोस्
+Comment[nl]=DBGp-debugger-plugin, zie http://xdebug.org
+Comment[pl]=Wtyczka debugera DBGp, patrz http://xdebug.org
+Comment[pt]='Plugin' de depuração DBGp, veja http://xdebug.org
+Comment[pt_BR]=Plugin de depuração DBGp, veja http://xdebug.org
+Comment[ru]=Модуль для отладчика DBGp, http://xdebug.org
+Comment[sk]=DBGp debuger modul, pozri http://xdebug.org
+Comment[sl]=Vstavek za razhoroščevanje DBGp, glej http://xdebug.org
+Comment[sr]=DBGp прикључак, види http://xdebug.org
+Comment[sr@Latn]=DBGp priključak, vidi http://xdebug.org
+Comment[sv]=DBGp-insticksprogram för felsökning, se http://xdebug.org
+Comment[uk]=Втулок зневаджувача DBGp, див. http://xdebug.org
+Comment[zh_CN]=DBGp 调试器插件,参看 http://xdebug.org
+Comment[zh_HK]=DBGp 除錯器外掛程式,請參閱 http://xdebug.org
+Comment[zh_TW]=DBGp 除錯器外掛程式,請參閱 http://xdebug.org
+Icon=kdbg
+ServiceTypes=Quanta/Debugger
+X-KDE-Library=quantadebuggerdbgp
diff --git a/quanta/components/debugger/dbgp/quantadebuggerdbgp.h b/quanta/components/debugger/dbgp/quantadebuggerdbgp.h
new file mode 100644
index 00000000..fd8eda22
--- /dev/null
+++ b/quanta/components/debugger/dbgp/quantadebuggerdbgp.h
@@ -0,0 +1,166 @@
+/***************************************************************************
+ phpdebugdbgp.cpp
+ -------------------
+ begin : 2004-03-12
+ copyright : (C) 2004 Linus McCabe <linus@mccabe.nu>
+ ***************************************************************************/
+
+/****************************************************************************
+ * *
+ * This program 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef QUANTADEBUGGERGUBED_H
+#define QUANTADEBUGGERGUBED_H
+
+#include <kserversocket.h>
+#include <kstreamsocket.h>
+#include <qptrlist.h>
+#include <kurl.h>
+#include <qdom.h>
+
+#include "debuggerclient.h"
+#include "dbgpnetwork.h"
+
+typedef QValueList<QString> WatchList;
+typedef QMap<QString, QString> StringMap;
+
+class QuantaDebuggerDBGp : public DebuggerClient
+{
+ Q_OBJECT
+
+ public:
+ QuantaDebuggerDBGp(QObject *parent, const char* name, const QStringList&);
+ ~QuantaDebuggerDBGp();
+
+ // Execution states
+ enum State
+ {
+ Starting = 0,
+ Stopping,
+ Stopped,
+ Running,
+ Break
+ };
+ // Error codes
+ enum Errors
+ {
+ Warning = 2,
+ Notice = 8,
+ User_Error = 256,
+ User_Warning = 512,
+ User_Notice = 1024
+ };
+
+ // Protocol version
+ static const char protocolversion[];
+
+ // Manager interaction
+ const uint supports(DebuggerClientCapabilities::Capabilities);
+
+ // Execution control
+ void request();
+ void run();
+ void stepInto();
+ void stepOver();
+ void stepOut();
+ void pause();
+ void kill();
+ void setExecutionState(const QString &state);
+ void setExecutionState(const State &state, bool forcesend = false);
+
+ // Connection
+ void startSession();
+ void endSession();
+
+ // Return name of debugger
+ QString getName();
+
+ // Initiation
+ void checkSupport(const QDomNode&node);
+
+ // New file opened in quanta
+ void fileOpened(const QString& file);
+
+ // Settings
+ void readConfig(QDomNode node);
+ void showConfig(QDomNode node);
+
+ // Breakpoints
+ void addBreakpoint(DebuggerBreakpoint* breakpoint);
+ void removeBreakpoint(DebuggerBreakpoint* breakpoint);
+ void showCondition(const StringMap &args);
+
+ // Variables
+ void addWatch(const QString &variable);
+ void removeWatch(DebuggerVariable *var);
+ void variableSetValue(const DebuggerVariable &variable);
+ void propertySetResponse( const QDomNode & setnode);
+
+ // Call stack
+ void stackShow(const QDomNode&node);
+
+ private:
+ DBGpNetwork m_network;
+
+ QString m_serverBasedir;
+ QString m_localBasedir;
+ QString m_serverPort;
+ QString m_serverHost;
+ QString m_startsession;
+ QString m_listenPort;
+ QString m_profilerFilename;
+ QString m_appid;
+ QString m_initialscript;
+
+ bool m_useproxy;
+ bool m_profilerAutoOpen;
+ bool m_profilerMapFilename;
+ State m_executionState, m_defaultExecutionState;
+ long m_errormask;
+ long m_displaydelay;
+ bool m_supportsasync;
+
+ // Variable type mapping
+ StringMap m_variabletypes;
+
+ // Internal watchlist
+ WatchList m_watchlist;
+
+ void sendWatches();
+ void debuggingState(bool enable);
+ void connected();
+
+ void handleError(const QDomNode & statusnode );
+
+ QString mapServerPathToLocal(const QString& serverpath);
+ QString mapLocalPathToServer(const QString& localpath);
+ QString bpToDBGp(DebuggerBreakpoint* breakpoint);
+ void setBreakpointKey(const QDomNode& response);
+
+ QString attribute(const QDomNode&node, const QString &attribute);
+ void initiateSession(const QDomNode& initpacket);
+
+ void typemapSetup(const QDomNode& typemapnode);
+ void showWatch(const QDomNode& typemapnode);
+ DebuggerVariable* buildVariable(const QDomNode& typemapnode);
+
+ // Profiler
+ void profilerOpen(bool forceopen);
+ void profilerOpen();
+
+ public slots:
+ void slotNetworkActive(bool active);
+ void slotNetworkConnected(bool connected);
+ void slotNetworkError(const QString &errormsg, bool log);
+ void processCommand(const QString&);
+
+ signals:
+ void updateStatus(DebuggerUI::DebuggerStatus);
+};
+
+#endif