From e9ae80694875f869892f13f4fcaf1170a00dea41 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- quanta/components/Makefile.am | 5 + quanta/components/csseditor/Makefile.am | 18 + quanta/components/csseditor/colorrequester.cpp | 129 ++ quanta/components/csseditor/colorrequester.h | 50 + quanta/components/csseditor/colorslider.cpp | 85 ++ quanta/components/csseditor/colorslider.h | 69 ++ quanta/components/csseditor/csseditor.cpp | 697 +++++++++++ quanta/components/csseditor/csseditor.h | 117 ++ quanta/components/csseditor/csseditor_globals.cpp | 50 + quanta/components/csseditor/csseditor_globals.h | 63 + quanta/components/csseditor/csseditors.ui | 411 +++++++ quanta/components/csseditor/cssselector.cpp | 395 ++++++ quanta/components/csseditor/cssselector.h | 74 ++ quanta/components/csseditor/cssselectors.ui | 985 +++++++++++++++ .../components/csseditor/cssshpropertyparser.cpp | 127 ++ quanta/components/csseditor/cssshpropertyparser.h | 46 + quanta/components/csseditor/data/Makefile.am | 3 + quanta/components/csseditor/data/atrules.xml | 7 + quanta/components/csseditor/data/config.xml | 609 +++++++++ quanta/components/csseditor/data/dtdTags.xml | 19 + quanta/components/csseditor/data/pseudo.xml | 14 + quanta/components/csseditor/doubleeditors.cpp | 120 ++ quanta/components/csseditor/doubleeditors.h | 86 ++ quanta/components/csseditor/encodingselector.cpp | 47 + quanta/components/csseditor/encodingselector.h | 40 + quanta/components/csseditor/encodingselectors.ui | 115 ++ quanta/components/csseditor/fontfamilychooser.cpp | 175 +++ quanta/components/csseditor/fontfamilychooser.h | 52 + quanta/components/csseditor/fontfamilychoosers.ui | 441 +++++++ quanta/components/csseditor/minieditor.h | 37 + quanta/components/csseditor/percentageeditor.cpp | 38 + quanta/components/csseditor/percentageeditor.h | 52 + quanta/components/csseditor/propertysetter.cpp | 129 ++ quanta/components/csseditor/propertysetter.h | 64 + quanta/components/csseditor/qmyhighlighter.cpp | 65 + quanta/components/csseditor/qmyhighlighter.h | 36 + quanta/components/csseditor/shorthandformer.cpp | 781 ++++++++++++ quanta/components/csseditor/shorthandformer.h | 117 ++ quanta/components/csseditor/specialsb.cpp | 127 ++ quanta/components/csseditor/specialsb.h | 79 ++ quanta/components/csseditor/styleeditor.cpp | 109 ++ quanta/components/csseditor/styleeditor.h | 42 + quanta/components/csseditor/stylesheetparser.cpp | 245 ++++ quanta/components/csseditor/stylesheetparser.h | 58 + quanta/components/csseditor/tlpeditors.cpp | 174 +++ quanta/components/csseditor/tlpeditors.h | 94 ++ quanta/components/cvsservice/Makefile.am | 13 + quanta/components/cvsservice/cvscommitdlgs.ui | 150 +++ quanta/components/cvsservice/cvsservice.cpp | 555 +++++++++ quanta/components/cvsservice/cvsservice.h | 118 ++ quanta/components/cvsservice/cvsservicedcopif.h | 30 + quanta/components/cvsservice/cvsupdatetodlgs.ui | 198 +++ quanta/components/debugger/Makefile.am | 25 + quanta/components/debugger/backtracelistview.cpp | 128 ++ quanta/components/debugger/backtracelistview.h | 93 ++ .../debugger/conditionalbreakpointdialog.cpp | 100 ++ .../debugger/conditionalbreakpointdialog.h | 56 + .../debugger/conditionalbreakpointdialogs.ui | 329 +++++ quanta/components/debugger/dbgp/Makefile.am | 17 + quanta/components/debugger/dbgp/dbgpnetwork.cpp | 314 +++++ quanta/components/debugger/dbgp/dbgpnetwork.h | 76 ++ quanta/components/debugger/dbgp/dbgpsettings.cpp | 44 + quanta/components/debugger/dbgp/dbgpsettings.h | 35 + quanta/components/debugger/dbgp/dbgpsettingss.ui | 728 +++++++++++ quanta/components/debugger/dbgp/qbytearrayfifo.cpp | 76 ++ quanta/components/debugger/dbgp/qbytearrayfifo.h | 43 + .../debugger/dbgp/quantadebuggerdbgp.cpp | 1042 ++++++++++++++++ .../debugger/dbgp/quantadebuggerdbgp.desktop | 44 + .../components/debugger/dbgp/quantadebuggerdbgp.h | 166 +++ quanta/components/debugger/debuggerbreakpoint.cpp | 181 +++ quanta/components/debugger/debuggerbreakpoint.h | 85 ++ .../components/debugger/debuggerbreakpointlist.cpp | 193 +++ .../components/debugger/debuggerbreakpointlist.h | 58 + .../components/debugger/debuggerbreakpointview.cpp | 193 +++ .../components/debugger/debuggerbreakpointview.h | 74 ++ quanta/components/debugger/debuggermanager.cpp | 850 +++++++++++++ quanta/components/debugger/debuggermanager.h | 128 ++ quanta/components/debugger/debuggerui.cpp | 205 ++++ quanta/components/debugger/debuggerui.h | 90 ++ quanta/components/debugger/debuggervariable.cpp | 283 +++++ quanta/components/debugger/debuggervariable.h | 103 ++ quanta/components/debugger/debuggervariablesets.ui | 185 +++ quanta/components/debugger/gubed/Makefile.am | 18 + quanta/components/debugger/gubed/gubedsettings.cpp | 41 + quanta/components/debugger/gubed/gubedsettings.h | 36 + quanta/components/debugger/gubed/gubedsettingss.ui | 762 ++++++++++++ .../debugger/gubed/quantadebuggergubed.cpp | 1247 +++++++++++++++++++ .../debugger/gubed/quantadebuggergubed.desktop | 48 + .../debugger/gubed/quantadebuggergubed.h | 153 +++ quanta/components/debugger/interfaces/Makefile.am | 17 + .../debugger/interfaces/debuggerclient.cpp | 160 +++ .../debugger/interfaces/debuggerclient.h | 115 ++ .../debugger/interfaces/debuggerinterface.cpp | 26 + .../debugger/interfaces/debuggerinterface.h | 80 ++ .../debugger/interfaces/quantadebugger.desktop | 45 + quanta/components/debugger/pathmapper.cpp | 228 ++++ quanta/components/debugger/pathmapper.h | 55 + quanta/components/debugger/pathmapperdialog.cpp | 102 ++ quanta/components/debugger/pathmapperdialog.h | 52 + quanta/components/debugger/pathmapperdialogs.ui | 345 ++++++ .../debugger/quantadebuggerinterface.cpp | 176 +++ .../components/debugger/quantadebuggerinterface.h | 75 ++ quanta/components/debugger/variableslistview.cpp | 290 +++++ quanta/components/debugger/variableslistview.h | 71 ++ quanta/components/framewizard/Makefile.am | 9 + quanta/components/framewizard/areaattributedb.cpp | 40 + quanta/components/framewizard/areaattributedb.h | 49 + quanta/components/framewizard/fmfpeditor.cpp | 111 ++ quanta/components/framewizard/fmfpeditor.h | 42 + quanta/components/framewizard/fmfpeditors.ui | 541 ++++++++ quanta/components/framewizard/fmrceditor.cpp | 34 + quanta/components/framewizard/fmrceditor.h | 38 + quanta/components/framewizard/fmrceditors.ui | 149 +++ quanta/components/framewizard/framewizard.cpp | 120 ++ quanta/components/framewizard/framewizard.h | 61 + quanta/components/framewizard/framewizards.ui | 369 ++++++ quanta/components/framewizard/fwglobal.cpp | 22 + quanta/components/framewizard/fwglobal.h | 24 + quanta/components/framewizard/selectablearea.cpp | 57 + quanta/components/framewizard/selectablearea.h | 53 + quanta/components/framewizard/treenode.cpp | 135 ++ quanta/components/framewizard/treenode.h | 87 ++ .../components/framewizard/visualframeeditor.cpp | 449 +++++++ quanta/components/framewizard/visualframeeditor.h | 66 + quanta/components/tableeditor/Makefile.am | 15 + quanta/components/tableeditor/tableeditor.cpp | 1298 ++++++++++++++++++++ quanta/components/tableeditor/tableeditor.h | 132 ++ quanta/components/tableeditor/tableeditors.ui | 642 ++++++++++ quanta/components/tableeditor/tableitem.cpp | 94 ++ quanta/components/tableeditor/tableitem.h | 56 + 130 files changed, 23139 insertions(+) create mode 100644 quanta/components/Makefile.am create mode 100644 quanta/components/csseditor/Makefile.am create mode 100644 quanta/components/csseditor/colorrequester.cpp create mode 100644 quanta/components/csseditor/colorrequester.h create mode 100644 quanta/components/csseditor/colorslider.cpp create mode 100644 quanta/components/csseditor/colorslider.h create mode 100644 quanta/components/csseditor/csseditor.cpp create mode 100644 quanta/components/csseditor/csseditor.h create mode 100644 quanta/components/csseditor/csseditor_globals.cpp create mode 100644 quanta/components/csseditor/csseditor_globals.h create mode 100644 quanta/components/csseditor/csseditors.ui create mode 100644 quanta/components/csseditor/cssselector.cpp create mode 100644 quanta/components/csseditor/cssselector.h create mode 100644 quanta/components/csseditor/cssselectors.ui create mode 100644 quanta/components/csseditor/cssshpropertyparser.cpp create mode 100644 quanta/components/csseditor/cssshpropertyparser.h create mode 100644 quanta/components/csseditor/data/Makefile.am create mode 100644 quanta/components/csseditor/data/atrules.xml create mode 100644 quanta/components/csseditor/data/config.xml create mode 100644 quanta/components/csseditor/data/dtdTags.xml create mode 100644 quanta/components/csseditor/data/pseudo.xml create mode 100644 quanta/components/csseditor/doubleeditors.cpp create mode 100644 quanta/components/csseditor/doubleeditors.h create mode 100644 quanta/components/csseditor/encodingselector.cpp create mode 100644 quanta/components/csseditor/encodingselector.h create mode 100644 quanta/components/csseditor/encodingselectors.ui create mode 100644 quanta/components/csseditor/fontfamilychooser.cpp create mode 100644 quanta/components/csseditor/fontfamilychooser.h create mode 100644 quanta/components/csseditor/fontfamilychoosers.ui create mode 100644 quanta/components/csseditor/minieditor.h create mode 100644 quanta/components/csseditor/percentageeditor.cpp create mode 100644 quanta/components/csseditor/percentageeditor.h create mode 100644 quanta/components/csseditor/propertysetter.cpp create mode 100644 quanta/components/csseditor/propertysetter.h create mode 100644 quanta/components/csseditor/qmyhighlighter.cpp create mode 100644 quanta/components/csseditor/qmyhighlighter.h create mode 100644 quanta/components/csseditor/shorthandformer.cpp create mode 100644 quanta/components/csseditor/shorthandformer.h create mode 100644 quanta/components/csseditor/specialsb.cpp create mode 100644 quanta/components/csseditor/specialsb.h create mode 100644 quanta/components/csseditor/styleeditor.cpp create mode 100644 quanta/components/csseditor/styleeditor.h create mode 100644 quanta/components/csseditor/stylesheetparser.cpp create mode 100644 quanta/components/csseditor/stylesheetparser.h create mode 100644 quanta/components/csseditor/tlpeditors.cpp create mode 100644 quanta/components/csseditor/tlpeditors.h create mode 100644 quanta/components/cvsservice/Makefile.am create mode 100644 quanta/components/cvsservice/cvscommitdlgs.ui create mode 100644 quanta/components/cvsservice/cvsservice.cpp create mode 100644 quanta/components/cvsservice/cvsservice.h create mode 100644 quanta/components/cvsservice/cvsservicedcopif.h create mode 100644 quanta/components/cvsservice/cvsupdatetodlgs.ui create mode 100644 quanta/components/debugger/Makefile.am create mode 100644 quanta/components/debugger/backtracelistview.cpp create mode 100644 quanta/components/debugger/backtracelistview.h create mode 100644 quanta/components/debugger/conditionalbreakpointdialog.cpp create mode 100644 quanta/components/debugger/conditionalbreakpointdialog.h create mode 100644 quanta/components/debugger/conditionalbreakpointdialogs.ui create mode 100644 quanta/components/debugger/dbgp/Makefile.am create mode 100644 quanta/components/debugger/dbgp/dbgpnetwork.cpp create mode 100644 quanta/components/debugger/dbgp/dbgpnetwork.h create mode 100644 quanta/components/debugger/dbgp/dbgpsettings.cpp create mode 100644 quanta/components/debugger/dbgp/dbgpsettings.h create mode 100644 quanta/components/debugger/dbgp/dbgpsettingss.ui create mode 100644 quanta/components/debugger/dbgp/qbytearrayfifo.cpp create mode 100644 quanta/components/debugger/dbgp/qbytearrayfifo.h create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.cpp create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.desktop create mode 100644 quanta/components/debugger/dbgp/quantadebuggerdbgp.h create mode 100644 quanta/components/debugger/debuggerbreakpoint.cpp create mode 100644 quanta/components/debugger/debuggerbreakpoint.h create mode 100644 quanta/components/debugger/debuggerbreakpointlist.cpp create mode 100644 quanta/components/debugger/debuggerbreakpointlist.h create mode 100644 quanta/components/debugger/debuggerbreakpointview.cpp create mode 100644 quanta/components/debugger/debuggerbreakpointview.h create mode 100644 quanta/components/debugger/debuggermanager.cpp create mode 100644 quanta/components/debugger/debuggermanager.h create mode 100644 quanta/components/debugger/debuggerui.cpp create mode 100644 quanta/components/debugger/debuggerui.h create mode 100644 quanta/components/debugger/debuggervariable.cpp create mode 100644 quanta/components/debugger/debuggervariable.h create mode 100644 quanta/components/debugger/debuggervariablesets.ui create mode 100644 quanta/components/debugger/gubed/Makefile.am create mode 100644 quanta/components/debugger/gubed/gubedsettings.cpp create mode 100644 quanta/components/debugger/gubed/gubedsettings.h create mode 100644 quanta/components/debugger/gubed/gubedsettingss.ui create mode 100644 quanta/components/debugger/gubed/quantadebuggergubed.cpp create mode 100644 quanta/components/debugger/gubed/quantadebuggergubed.desktop create mode 100644 quanta/components/debugger/gubed/quantadebuggergubed.h create mode 100644 quanta/components/debugger/interfaces/Makefile.am create mode 100644 quanta/components/debugger/interfaces/debuggerclient.cpp create mode 100644 quanta/components/debugger/interfaces/debuggerclient.h create mode 100644 quanta/components/debugger/interfaces/debuggerinterface.cpp create mode 100644 quanta/components/debugger/interfaces/debuggerinterface.h create mode 100644 quanta/components/debugger/interfaces/quantadebugger.desktop create mode 100644 quanta/components/debugger/pathmapper.cpp create mode 100644 quanta/components/debugger/pathmapper.h create mode 100644 quanta/components/debugger/pathmapperdialog.cpp create mode 100644 quanta/components/debugger/pathmapperdialog.h create mode 100644 quanta/components/debugger/pathmapperdialogs.ui create mode 100644 quanta/components/debugger/quantadebuggerinterface.cpp create mode 100644 quanta/components/debugger/quantadebuggerinterface.h create mode 100644 quanta/components/debugger/variableslistview.cpp create mode 100644 quanta/components/debugger/variableslistview.h create mode 100644 quanta/components/framewizard/Makefile.am create mode 100644 quanta/components/framewizard/areaattributedb.cpp create mode 100644 quanta/components/framewizard/areaattributedb.h create mode 100644 quanta/components/framewizard/fmfpeditor.cpp create mode 100644 quanta/components/framewizard/fmfpeditor.h create mode 100644 quanta/components/framewizard/fmfpeditors.ui create mode 100644 quanta/components/framewizard/fmrceditor.cpp create mode 100644 quanta/components/framewizard/fmrceditor.h create mode 100644 quanta/components/framewizard/fmrceditors.ui create mode 100644 quanta/components/framewizard/framewizard.cpp create mode 100644 quanta/components/framewizard/framewizard.h create mode 100644 quanta/components/framewizard/framewizards.ui create mode 100644 quanta/components/framewizard/fwglobal.cpp create mode 100644 quanta/components/framewizard/fwglobal.h create mode 100644 quanta/components/framewizard/selectablearea.cpp create mode 100644 quanta/components/framewizard/selectablearea.h create mode 100644 quanta/components/framewizard/treenode.cpp create mode 100644 quanta/components/framewizard/treenode.h create mode 100644 quanta/components/framewizard/visualframeeditor.cpp create mode 100644 quanta/components/framewizard/visualframeeditor.h create mode 100644 quanta/components/tableeditor/Makefile.am create mode 100644 quanta/components/tableeditor/tableeditor.cpp create mode 100644 quanta/components/tableeditor/tableeditor.h create mode 100644 quanta/components/tableeditor/tableeditors.ui create mode 100644 quanta/components/tableeditor/tableitem.cpp create mode 100644 quanta/components/tableeditor/tableitem.h (limited to 'quanta/components') diff --git a/quanta/components/Makefile.am b/quanta/components/Makefile.am new file mode 100644 index 00000000..654571d1 --- /dev/null +++ b/quanta/components/Makefile.am @@ -0,0 +1,5 @@ +if include_cvsservice +CVSSERVICE = cvsservice +endif + +SUBDIRS = csseditor framewizard tableeditor debugger $(CVSSERVICE) diff --git a/quanta/components/csseditor/Makefile.am b/quanta/components/csseditor/Makefile.am new file mode 100644 index 00000000..3b888e32 --- /dev/null +++ b/quanta/components/csseditor/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = data + +noinst_LTLIBRARIES = libcsseditor.la + +libcsseditor_la_SOURCES = fontfamilychoosers.ui cssselectors.ui csseditors.ui \ + fontfamilychooser.cpp cssselector.cpp csseditor.cpp specialsb.cpp doubleeditors.cpp \ + qmyhighlighter.cpp colorrequester.cpp propertysetter.cpp shorthandformer.cpp colorslider.cpp \ + csseditor_globals.cpp tlpeditors.cpp styleeditor.cpp stylesheetparser.cpp cssshpropertyparser.cpp percentageeditor.cpp + +libcsseditor_la_METASOURCES = AUTO + +AM_CPPFLAGS = -I$(top_srcdir)/quanta/src \ + -I$(top_srcdir)/quanta/utility \ + -I$(top_srcdir)/quanta/parsers \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/lib \ + $(KMDI_INCLUDES) $(all_includes) +noinst_HEADERS = styleeditor.h diff --git a/quanta/components/csseditor/colorrequester.cpp b/quanta/components/csseditor/colorrequester.cpp new file mode 100644 index 00000000..1333a48e --- /dev/null +++ b/quanta/components/csseditor/colorrequester.cpp @@ -0,0 +1,129 @@ +/*************************************************************************** + colorrequester.cpp - description + ------------------- + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "colorrequester.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "propertysetter.h" + +class colorRequester::colorRequesterPrivate{ + public: + KLineEdit *edit; + colorRequesterPrivate() { edit = 0L; } + void setText( const QString& text ) { edit->setText( text ); } + void connectSignals( QObject *receiver ) { connect( edit, SIGNAL( textChanged( const QString& )),receiver, SIGNAL( textChanged( const QString& ))); } +}; + +colorRequester::colorRequester(QWidget *parent, const char* name) : miniEditor(parent,name){ + d = new colorRequesterPrivate; + init(); +} + +colorRequester::~colorRequester(){ + delete myColorDialog; + delete d; +} + +void colorRequester::connectToPropertySetter(propertySetter* p){ + connect( this, SIGNAL(textChanged(const QString&)), p, SIGNAL(valueChanged(const QString&))); +} + +void colorRequester::init() +{ + myColorDialog = 0L; + + if ( !d->edit ) + d->edit = new KLineEdit( this, "line edit" ); + + myButton = new KPushButton( this, "kfile button"); + QIconSet iconSet = SmallIconSet(QString::fromLatin1("colorize")); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + myButton->setIconSet( iconSet ); + myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + QToolTip::add(myButton, i18n("Open color dialog")); + + setSpacing( KDialog::spacingHint() ); + + QWidget *widget = (QWidget*) d->edit; + setFocusProxy( widget ); + + d->connectSignals( this ); + connect( myButton, SIGNAL( clicked() ), this, SLOT( openColorDialog() )); + connect( d->edit, SIGNAL( textChanged ( const QString & ) ), this, SLOT( setInitialValue(/*const QString&*/ ) )); + + KAccel *accel = new KAccel( this ); + accel->insert( KStdAccel::Open, this, SLOT( openColorDialog() )); + accel->readSettings(); + } + +void colorRequester::openColorDialog(){ + KColorDialog dlg(this,"dlg",true); + dlg.setColor(QColor(m_initialValue)); + if(dlg.exec()){ + QColor myColor(dlg.color()); + d->edit->setText(myColor.name()); + emit textChanged(myColor.name()); + } +} + +KLineEdit * colorRequester::lineEdit() const{ + return d->edit; +} +#include +void colorRequester::setInitialValue(/*const QString& s*/){ + QString temp = d->edit->text(); + temp.remove(" "); + if( temp.contains("#") != 0){ + temp.remove("#"); + if(temp.length() == 3) { + QString temp2; + temp2.append(temp[0]); + temp2.append(temp[0]); + temp2.append(temp[1]); + temp2.append(temp[1]); + temp2.append(temp[2]); + temp2.append(temp[2]); + temp = temp2; + } + bool ok; + int r = temp.left(2).toInt( &ok, 16 ); + int g = temp.mid(2,2).toInt( &ok, 16 ); + int b = temp.right(2).toInt( &ok, 16 ); + m_initialValue.setRgb(r,g,b); + } + else + + if( temp.contains("rgb(") != 0){ + temp.remove("rgb(").remove(")"); + QStringList rgbValues = QStringList::split(",",temp); +// bool ok; + int r = rgbValues[0].toInt(); + int g = rgbValues[1].toInt(); + int b = rgbValues[2].toInt(); + m_initialValue.setRgb(r,g,b); + } + else + m_initialValue.setNamedColor(d->edit->text()); +} + +#include "colorrequester.moc" diff --git a/quanta/components/csseditor/colorrequester.h b/quanta/components/csseditor/colorrequester.h new file mode 100644 index 00000000..e0b4be4f --- /dev/null +++ b/quanta/components/csseditor/colorrequester.h @@ -0,0 +1,50 @@ +/*************************************************************************** + colorrequester.h - description + ------------------- + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 COLORREQUESTER_H +#define COLORREQUESTER_H + +#include +#include + +#include "minieditor.h" + +class KLineEdit; +class KColorDialog; +class colorRequester : public miniEditor{ + Q_OBJECT + public: + colorRequester(QWidget *parent, const char* name=0); + ~colorRequester(); + KLineEdit * lineEdit() const; + KPushButton * button() const { return myButton; } + virtual void connectToPropertySetter(propertySetter* p); + //void setInitialValue(const QString&); + public slots: + void openColorDialog(); + void setInitialValue(/*const QString&*/); + protected: + void init(); + signals: + void selectedColor(QColor); + void textChanged(const QString&); + private: + mutable KColorDialog * myColorDialog; + KPushButton *myButton; + class colorRequesterPrivate; + colorRequesterPrivate *d; + QColor m_initialValue; +}; +#endif diff --git a/quanta/components/csseditor/colorslider.cpp b/quanta/components/csseditor/colorslider.cpp new file mode 100644 index 00000000..436c7e21 --- /dev/null +++ b/quanta/components/csseditor/colorslider.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + colorslider.cpp - description + ------------------- + begin : lun ago 9 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 +#include + +#include + +#include "colorslider.h" +#include "propertysetter.h" + +/** + *@author gulmini luciano + */ + + + +colorSlider::colorSlider(const QString& fn,const QString& l,const QString& c,const QString& r,QWidget *parent, const char *name) : miniEditor(parent,name) { + m_functionName = fn; + QVBox *leftBox = new QVBox(this); + QVBox *centerBox = new QVBox(this); + QVBox *rightBox = new QVBox(this); + QLabel *leftLabel = new QLabel("" + l +"",leftBox); + QLabel *centerLabel = new QLabel(("" + c +""),centerBox); + QLabel *rightLabel = new QLabel(("" + r +""),rightBox); + leftLabel->setAlignment(Qt::AlignHCenter); + centerLabel->setAlignment(Qt::AlignHCenter); + rightLabel->setAlignment(Qt::AlignHCenter); + leftLabel->setTextFormat (Qt::RichText ) ; + centerLabel->setTextFormat ( Qt::RichText ) ; + rightLabel->setTextFormat (Qt::RichText ) ; + m_leftValue = new QSlider ( 0, 255, 1, 0, Qt::Horizontal , leftBox); + m_centerValue = new QSlider ( 0, 255, 1, 0, Qt::Horizontal , centerBox); + m_rightValue = new QSlider ( 0, 255, 1, 0, Qt::Horizontal , rightBox); + setSpacing(10); + connect(m_leftValue, SIGNAL(valueChanged ( int)), this, SLOT(convertLeftValue(int))); + connect(m_centerValue, SIGNAL(valueChanged ( int)), this, SLOT(convertCenterValue(int))); + connect(m_rightValue, SIGNAL(valueChanged ( int)), this, SLOT(convertRightValue(int))); +} + +colorSlider::~colorSlider(){ + //delete m_redValue; + //delete m_greenValue; + //delete m_blueValue; +} + +void colorSlider::connectToPropertySetter(propertySetter* p){ + connect( this, SIGNAL(valueChanged(const QString&)), p, SIGNAL(valueChanged(const QString&))); +} + +void colorSlider::convertLeftValue(int i){ + emit valueChanged(m_functionName + "(" + QString::number(i,10) + "," + QString::number(m_centerValue->value(),10) + "," +QString::number(m_rightValue->value(),10) +")"); +} + +void colorSlider::convertCenterValue(int i){ + emit valueChanged(m_functionName + "(" + QString::number(m_leftValue->value(),10) + "," + QString::number(i,10) + "," + QString::number(m_rightValue->value(),10) +")"); +} + +void colorSlider::convertRightValue(int i){ + emit valueChanged(m_functionName + "(" + QString::number(m_leftValue->value(),10) + "," + QString::number(m_centerValue->value(),10) + "," + QString::number(i,10) +")"); +} + +RGBcolorSlider::RGBcolorSlider(QWidget *parent, const char *name) : colorSlider("rgb",i18n("Red"),i18n("Green"),i18n("Blue"),parent,name){ +} + +//FOR CSS3 +/*HSLcolorSlider::HSLcolorSlider(QWidget *parent, const char *name) : colorSlider("hsl",i18n("Hue"),i18n("Saturation"),i18n("Lightness"),parent,name){ +} +*/ + +#include "colorslider.moc" diff --git a/quanta/components/csseditor/colorslider.h b/quanta/components/csseditor/colorslider.h new file mode 100644 index 00000000..41a78fa9 --- /dev/null +++ b/quanta/components/csseditor/colorslider.h @@ -0,0 +1,69 @@ +/*************************************************************************** + colorslider.h - description + ------------------- + begin : lun ago 9 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 COLORSLIDER_H +#define COLORSLIDER_H + +#include + +#include "minieditor.h" + + + +/** + *@author gulmini luciano + */ + +class colorSlider : public miniEditor { + Q_OBJECT + private : + QString m_functionName; + protected: + QSlider *m_leftValue, + *m_centerValue, + *m_rightValue; + public: + colorSlider(const QString& functionName,const QString& l=QString::null,const QString& c=QString::null,const QString& r=QString::null,QWidget *parent=0, const char *name=0); + virtual ~colorSlider(); + virtual void connectToPropertySetter(propertySetter* p); + + private slots: + void convertLeftValue(int i); + void convertCenterValue(int i); + void convertRightValue(int i); + + signals: + void valueChanged(const QString&); +}; + +class RGBcolorSlider : public colorSlider { + Q_OBJECT + public: + RGBcolorSlider(QWidget *parent=0, const char *name=0); + ~RGBcolorSlider(){} +}; + +//FOR CSS3 +/*class HSLcolorSlider : public colorSlider { + Q_OBJECT + public: + HSLcolorSlider(QWidget *parent=0, const char *name=0); + ~HSLcolorSlider(); +};*/ + + +#endif diff --git a/quanta/components/csseditor/csseditor.cpp b/quanta/components/csseditor/csseditor.cpp new file mode 100644 index 00000000..692a8edf --- /dev/null +++ b/quanta/components/csseditor/csseditor.cpp @@ -0,0 +1,697 @@ +/*************************************************************************** + csseditor.cpp - description + ------------------- + begin : mer lug 23 11:20:17 CEST 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "csseditor.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "propertysetter.h" +#include "qmyhighlighter.h" +#include "cssshpropertyparser.h" +#include "shorthandformer.h" +#include "percentageeditor.h" +#include "colorslider.h" +#include "tlpeditors.h" +#include "doubleeditors.h" +#include "specialsb.h" +#include "colorrequester.h" + + + +myCheckListItem::myCheckListItem(QListView * parent, const QString & text):QCheckListItem(parent, text, QCheckListItem::CheckBox),m_checkedChildren(0){ + m_sig = new QSignal; +} + +myCheckListItem::myCheckListItem(QCheckListItem * parent, const QString & text):QCheckListItem(parent, text, QCheckListItem::CheckBox),m_checkedChildren(0){ + m_sig = new QSignal; +} + +myCheckListItem::~myCheckListItem(){ + delete m_sig; +} + +void myCheckListItem::connect( QObject *receiver, const char *member ){ + m_sig->connect( receiver, member ); +} + +void myCheckListItem::activate(){ + if(isOn()) QCheckListItem::activate(); +} + +void myCheckListItem::addCheckedChild() { + m_checkedChildren++; +} + +void myCheckListItem::stateChange (bool b){ + + if(!b) { + if(childCount()) { + QListViewItem * child = firstChild(); + while( child ) { + m_sig->setValue(QVariant(child->text(0))); + m_sig->activate(); + static_cast(child)->setOn(false); + child = child->nextSibling(); + } + m_checkedChildren = 0; + } + else { + if(parent()){ + myCheckListItem *p = static_cast(parent()); + while( p ) { + if( p->m_checkedChildren != 1) { + p->m_checkedChildren--; + m_sig->setValue(QVariant(text(0))); + m_sig->activate(); + break; + } + else { + m_sig->setValue(QVariant(text(0))); + m_sig->activate(); + p->setOn(false); + } + p = static_cast(p->parent()); + } + } + else { + m_sig->setValue(QVariant(text(0))); + m_sig->activate(); + } + } + } + else { + if(parent()) static_cast(parent())->addCheckedChild(); + } +} + +void CSSEditor::appendSub(QDomNodeList l, myCheckListItem *cli){ + unsigned int i; + for(i=0;iconnect(this,SLOT(removeProperty(const QVariant&))); + if(l.item(i).toElement().attribute("hasSub") == "yes") + appendSub(l.item(i).childNodes(),item); + } +} + +void CSSEditor::buildListView(QDomNodeList l, QListView *lv){ + unsigned int i; + for(i=0;iconnect(this,SLOT(removeProperty(const QVariant&))); + if(l.item(i).toElement().attribute("hasSub") == "yes") { + QDomNodeList listSub = l.item(i).childNodes(); + appendSub(listSub,item); + } + } +} + +void CSSEditor::setCurrentPropOn(const QString& s){ + if( (m_currentProp = static_cast(lvVisual->findItem( s,0 )) )) + m_currentProp->setOn(true); + else + if( (m_currentProp = static_cast(lvAll->findItem( s,0 )) )) + m_currentProp->setOn(true); + else + if( (m_currentProp = static_cast(lvAural->findItem( s,0 )) )) + m_currentProp->setOn(true); + else + if( (m_currentProp = static_cast(lvInteractive->findItem( s,0 )) )) + m_currentProp->setOn(true); + else + if( (m_currentProp = static_cast(lvPaged->findItem( s,0 )) )) + m_currentProp->setOn(true); + + if( m_currentProp && m_currentProp->depth() ) { + myCheckListItem *p = static_cast(m_currentProp->parent()); + while(p) { + p->setOn(true); + p=static_cast(p->parent()); + } + } +} + + + void CSSEditor::addAndSetPropertyOn(const QString& property, const QString& value){ + addProperty(property,value); + setCurrentPropOn(property); + } + + void CSSEditor::setSidesOfPropertyBorderOn(const QString& s){ + static_cast(lvVisual->findItem( "border-top",0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-right",0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-bottom",0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-left",0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-top-"+s,0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-right-"+s,0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-bottom-"+s,0 ))->setOn(true); + static_cast(lvVisual->findItem( "border-left-"+s,0 ))->setOn(true); + } + +void CSSEditor::hidePreviewer(){ + fPreview->hide(); + } + +void CSSEditor::initialize(){ + + m_config = kapp->config(); + connect(pbOk, SIGNAL(clicked()), this, SLOT(toggleShortendForm())); + m_config->setGroup("CSSEditor Options"); + SHckb->setChecked(m_config->readBoolEntry("Shorthand form enabled",false)); + + QString configFile = locate("appdata", "csseditor/config.xml"); + + m_myhi = new QMyHighlighter(display); + + QBoxLayout *fPreviewLayout = new QBoxLayout(fPreview,QBoxLayout::LeftToRight); + m_previewer=new KHTMLPart(fPreview); + + fPreviewLayout->addWidget(m_previewer->view()); + + QFile file( configFile ); + if ( !file.open( IO_ReadOnly ) ) { + return; + } + if ( !m_doc.setContent( &file ) ) { + file.close(); + return; + } + file.close(); + + QDomElement docElem = m_doc.documentElement(); + + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + QDomElement e = n.toElement(); + if( !e.isNull() ) { + if( e.attribute("type") == "visual") { + lvVisual->setRootIsDecorated(true); + buildListView(e.childNodes(), lvVisual); + } + if( e.attribute("type") == "paged") { + lvPaged->setRootIsDecorated(true); + buildListView(e.childNodes(), lvPaged); + } + if( e.attribute("type") == "interactive") { + lvInteractive->setRootIsDecorated(true); + buildListView(e.childNodes(), lvInteractive); + } + if( e.attribute("type") == "aural") { + lvAural->setRootIsDecorated(true); + buildListView(e.childNodes(), lvAural); + } + if( e.attribute("type") == "all"){ + lvAll->setRootIsDecorated(true); + buildListView(e.childNodes(), lvAll); + } + } + n = n.nextSibling(); + } // end while + + Connect(); + + QBoxLayout *fEditingLayout = new QBoxLayout(fEditing,QBoxLayout::LeftToRight); + + m_ps = new propertySetter(fEditing); + fEditingLayout->addWidget(m_ps); + connect(m_ps, SIGNAL(valueChanged(const QString&)), this, SLOT(checkProperty(const QString&))); + + QStringList props; + QString temp; + bool normalMode = true; + + if( !m_selectorName.isEmpty() ){ //the cssselector has been called + m_initialProperties = m_initialProperties.stripWhiteSpace(); + props=QStringList::split(";",m_initialProperties); + temp= m_selectorName + " {\n\t" ; + } + + else { + m_InlineStyleContent = m_InlineStyleContent.stripWhiteSpace(); + normalMode = false; + props=QStringList::split(";",m_InlineStyleContent); + temp="\n\t"; + } + + for ( QStringList::Iterator it = props.begin(); it != props.end(); ++it ) { + const QString propertyName((*it).section(":",0,0).stripWhiteSpace()); + const QString propertyValue((*it).section(":",1)); + + if( ShorthandFormer::SHFormList().contains(propertyName)==0 ) { + temp+= propertyName + " : " + propertyValue +";\n\t"; + addAndSetPropertyOn(propertyName,propertyValue); + } + else{ + ShorthandFormer decompressor; + QMap expandedProperties = decompressor.expand(propertyName, propertyValue ); + QMap::Iterator it; + + for ( it = expandedProperties.begin(); it != expandedProperties.end(); ++it ) { + addAndSetPropertyOn( it.key(), it.data() ); + temp += ( it.key() + " : " + it.data() + ";\n\t"); + } + } + } + temp.truncate(temp.length()-1); + //temp.chop(1); + if(normalMode)//normal mode editing + temp+="}"; + display->setText(temp); + activatePreview(); +} + +void CSSEditor::toggleShortendForm() +{ + m_config->setGroup("CSSEditor Options"); + m_config->writeEntry("Shorthand form enabled", SHckb->isChecked()); + m_config->sync(); +} + +CSSEditor::CSSEditor(QListViewItem *i, QWidget *parent, const char *name) : CSSEditorS(parent, name){ + m_selectorName = i->text(0); + m_initialProperties = i->text(1); +} + +CSSEditor::~CSSEditor() { + delete m_myhi; + delete m_ps; + delete m_previewer; +} + +void CSSEditor::setMiniEditors(QListViewItem* i){ + + m_ps->reset(); + + if(i->childCount()==0) { + m_currentProp = static_cast(i); + QDomNodeList valueTypes = m_doc.elementsByTagName(i->text(0)).item(0).childNodes(); + unsigned int i; + for(i=0; isetComboBox(); + QStringList values = QStringList::split(",",curr.attribute("value")); + m_ps->ComboBox()->insertStringList(values); + if(m_properties.contains(m_currentProp->text(0)) !=0 ) + if( values.contains(m_currentProp->text(0))) + m_ps->ComboBox()->setCurrentText(m_properties[m_currentProp->text(0)]); + if(curr.attribute("editable") == "yes"){ + m_ps->ComboBox()->setEditable(true); + /*if(m_properties.contains(m_currentProp->text(0)) !=0 ) + m_ps->ComboBox()->setEditText(m_properties[m_currentProp->text(0)]); */ + } + } + else + + /*if( typeName == "spinbox") { + m_ps->setSpinBox("0", values.item(k).toElement().attribute("minValue"), + values.item(k).toElement().attribute("maxValue"), + values.item(k).toElement().attribute("suffix")); + } + + else*/ + if( valueTypeName == "number") m_ps->setLineEdit(); + else + if( valueTypeName == "integer") { + if(m_properties.contains(m_currentProp->text(0)) !=0 ) { + if(!curr.attribute("minValue").isNull()) + m_ps->setSpinBox(m_properties[m_currentProp->text(0)],curr.attribute("minValue")); + else + m_ps->setSpinBox(m_properties[m_currentProp->text(0)]); + } + else + if(!curr.attribute("minValue").isNull()) + m_ps->setSpinBox("0",curr.attribute("minValue")); + else + m_ps->setSpinBox(); + } + else + if( valueTypeName == "length") { + lengthEditor *editor = new lengthEditor(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ) + editor->setInitialValue(m_properties[m_currentProp->text(0)]); + else + editor->setInitialValue(QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "percentage") { + if(m_properties.contains(m_currentProp->text(0)) !=0 ){ + percentageEditor *editor = new percentageEditor(m_properties[m_currentProp->text(0)],m_ps); + m_ps->installMiniEditor(editor); + } + else { + percentageEditor *editor = new percentageEditor("0",m_ps); + m_ps->installMiniEditor(editor); + } + } + else + if( valueTypeName == "doubleLength") { + doubleLengthEditor *editor = new doubleLengthEditor(m_ps); + + if(m_properties.contains(m_currentProp->text(0)) !=0 ){ + QString temp(m_properties[m_currentProp->text(0)].simplifyWhiteSpace()), + sx(temp.section(" ",0,0)), + dx(temp.section(" ",1,1)); + + editor->setInitialValue(sx,dx); + } + else editor->setInitialValue(QString::null,QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "doublePercentage") { + doublePercentageEditor *editor = new doublePercentageEditor(m_ps); + + if(m_properties.contains(m_currentProp->text(0)) !=0 ){ + QString temp(m_properties[m_currentProp->text(0)].simplifyWhiteSpace()), + sx(temp.section(" ",0,0)), + dx(temp.section(" ",1,1)); + + editor->setInitialValue(sx,dx); + } + else editor->setInitialValue(QString::null,QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "frequency") { + frequencyEditor *editor = new frequencyEditor(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ) + editor->setInitialValue(m_properties[m_currentProp->text(0)]); + else + editor->setInitialValue(QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "time") { + timeEditor *editor = new timeEditor(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ) + editor->setInitialValue(m_properties[m_currentProp->text(0)]); + else + editor->setInitialValue(QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "angle") { + angleEditor *editor = new angleEditor(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ) + editor->setInitialValue(m_properties[m_currentProp->text(0)]); + else + editor->setInitialValue(QString::null); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "freeedit") { + m_ps->setLineEdit(); + } + else + if( valueTypeName == "uri") { + URIEditor *editor = new URIEditor(m_ps); + + if(curr.attribute("mode") == "multi") editor->setMode(URIEditor::Multi); + else editor->setMode(URIEditor::Single); + + if( curr.attribute("resourceType") == "audio") editor->setResourceType(URIEditor::audio); + else + if( curr.attribute("resourceType") == "image") editor->setResourceType(URIEditor::image); + else + if( curr.attribute("resourceType") == "mousePointer") editor->setResourceType(URIEditor::mousePointer); + + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "colors") { + RGBcolorSlider *RGBeditor = new RGBcolorSlider(m_ps); + colorRequester *CReditor = new colorRequester(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ){ + CReditor->lineEdit()->setText(m_properties[m_currentProp->text(0)]); + CReditor->setInitialValue(); + + } + + m_ps->installMiniEditor(CReditor); + m_ps->setPredefinedColorListEditor(); + m_ps->installMiniEditor(RGBeditor); + } + else + if( valueTypeName =="doubleList") { + doubleComboBoxEditor *editor = new doubleComboBoxEditor(m_ps); + editor->cbSx()->insertStringList(QStringList::split(",",curr.firstChild().toElement().attribute("value"))); + editor->cbDx()->insertStringList(QStringList::split(",",curr.lastChild().toElement().attribute("value"))); + m_ps->installMiniEditor(editor); + } + else + if( valueTypeName == "fontDialog" ){ + fontEditor *editor = new fontEditor(m_ps); + if(m_properties.contains(m_currentProp->text(0)) !=0 ){ + editor->setInitialValue(m_properties[m_currentProp->text(0)]); + } + else editor->setInitialValue(QString::null); + m_ps->installMiniEditor(editor); + } + } + m_ps->addButton(); + m_ps->Show(); + } +} + +void CSSEditor::checkProperty(const QString& v){ + if(!m_currentProp->isOn()) + m_currentProp->setOn(true); + + if( m_currentProp->depth() ){ + myCheckListItem *p = static_cast(m_currentProp->parent()); + while(p){ + p->setOn(true); + p=static_cast(p->parent()); + } + } + + if(m_currentProp->text(0) =="border-style" ){ + setSidesOfPropertyBorderOn("style"); + QStringList values = QStringList::split(" ",v.stripWhiteSpace()); + addProperty("border-top-style",values[0]); + switch(values.count()) { + case 1: + addProperty("border-right-style",values[0]); + addProperty("border-bottom-style",values[0]); + addProperty("border-left-style",values[0]); + break; + + case 2: + addProperty("border-right-style",values[1]); + addProperty("border-bottom-style",values[0]); + addProperty("border-left-style",values[1]); + break; + + case 3: + addProperty("border-right-style",values[1]); + addProperty("border-bottom-style",values[2]); + addProperty("border-left-style",values[1]); + break; + + case 4: + addProperty("border-right-style",values[1]); + addProperty("border-bottom-style",values[2]); + addProperty("border-left-style",values[3]);break; + } + } + else + if(m_currentProp->text(0) =="border-width" ){ + setSidesOfPropertyBorderOn("width"); + QStringList values = QStringList::split(" ",v.stripWhiteSpace()); + addProperty("border-top-width",values[0]); + switch(values.count()) { + case 1: + addProperty("border-right-width",values[0]); + addProperty("border-bottom-width",values[0]); + addProperty("border-left-width",values[0]); + break; + + case 2: + addProperty("border-right-width",values[1]); + addProperty("border-bottom-width",values[0]); + addProperty("border-left-width",values[1]); + break; + + case 3: + addProperty("border-right-width",values[1]); + addProperty("border-bottom-width",values[2]); + addProperty("border-left-width",values[1]); + break; + + case 4: + addProperty("border-right-width",values[1]); + addProperty("border-bottom-width",values[2]); + addProperty("border-left-width",values[3]);break; + } + } + else + if(m_currentProp->text(0) =="border-color" ){ + setSidesOfPropertyBorderOn("color"); + QStringList values = QStringList::split(" ",v.stripWhiteSpace()); + addProperty("border-top-color",values[0]); + switch(values.count()) { + case 1: + addProperty("border-right-color",values[0]); + addProperty("border-bottom-color",values[0]); + addProperty("border-left-color",values[0]); + break; + + case 2: + addProperty("border-right-color",values[1]); + addProperty("border-bottom-color",values[0]); + addProperty("border-left-color",values[1]); + break; + + case 3: + addProperty("border-right-color",values[1]); + addProperty("border-bottom-color",values[2]); + addProperty("border-left-color",values[1]); + break; + + case 4: + addProperty("border-right-style",values[1]); + addProperty("border-bottom-style",values[2]); + addProperty("border-left-style",values[3]);break; + } + } + else addProperty(m_currentProp->text(0),v); + emit signalUpdatePreview(); +} + +void CSSEditor::Connect(){ + connect(this, SIGNAL(signalUpdatePreview()), this, SLOT(updatePreview())); + connect(lvVisual,SIGNAL(selectionChanged ( QListViewItem * )),this,SLOT(setMiniEditors ( QListViewItem * ))); + connect(lvAll,SIGNAL( selectionChanged( QListViewItem * )),this,SLOT(setMiniEditors ( QListViewItem * ))); + connect(lvAural,SIGNAL( selectionChanged( QListViewItem * )),this,SLOT(setMiniEditors ( QListViewItem * ))); + connect(lvInteractive,SIGNAL( selectionChanged( QListViewItem * )),this,SLOT(setMiniEditors ( QListViewItem * ))); + connect(lvPaged,SIGNAL( selectionChanged( QListViewItem * )),this,SLOT(setMiniEditors ( QListViewItem * ))); +} + +void CSSEditor::removeProperty(const QVariant& v){ + m_properties.remove(v.toString()); + updatePreview(); +} + +QString CSSEditor::generateProperties(){ + QString props; + QMap::Iterator it; + if(!SHckb->isChecked()) { + for ( it = m_properties.begin(); it != m_properties.end(); ++it ) + props+= it.key() + " : " + it.data().stripWhiteSpace() + "; " ; + props.truncate(props.length()-1);//the last white space creates some problems: better remove it + //props.chop(1); + return props; + } + else { + ShorthandFormer sf(m_properties); + return sf.compress(); + } +} + +void CSSEditor::updatePreview(){ + updateDisplay(); + activatePreview(); +} + +void CSSEditor::activatePreview() { + if(!m_isFileToPreviewExternal){ + QString testHeader, + testFooter, + testBody; + + if(!m_selectorName.isEmpty()) { + testHeader += m_selectorName + " { \n "; + testFooter = "\n}" + m_Selectors; + } + else { + testHeader += " style=\"" ; + testFooter = "\"" ; + } + + QMap::Iterator it; + for ( it = m_properties.begin(); it != m_properties.end(); ++it ) + testBody+= it.key() + " : " + it.data() + ";"; + + m_previewer->begin( KURL(m_fileToPreview) ); + m_previewer->write( m_Header + testHeader + testBody+ testFooter+ m_Footer); + m_previewer->end(); + + + } + else { + QString tmp("{"); + QFile file(m_fileToPreview); + if ( file.open( IO_ReadOnly ) ) { + QMap::Iterator it; + for ( it = m_properties.begin(); it != m_properties.end(); ++it ) + tmp+= it.key() + " : " + it.data() + ";"; + + + QFileInfo fi(m_fileToPreview); + KParts::URLArgs a; + if(fi.extension().lower() == "xml" || fi.extension().lower() == "xhtml") + a.serviceType="text/xml"; + if(fi.extension().lower() == "html" || fi.extension().lower() == "html") + a.serviceType="text/xml"; + m_previewer->browserExtension()->setURLArgs(a); + QTextStream stream( &file ); + + m_previewer->begin(KURL(m_fileToPreview)); + m_previewer->write(stream.read()); + m_previewer->end(); + m_previewer->setUserStyleSheet(m_externalStyleSheetDefinition + " " + m_selectorName+" "+ tmp +"}"); + file.close(); + } + //else KMessageBox::sorry(this,i18n("The css file you want to edit can't be opened")); + } +} + +void CSSEditor::updateDisplay(){ + QString toDisplay; + QMap::Iterator it; + for ( it = m_properties.begin(); it != m_properties.end(); ++it ) + toDisplay += it.key() + " : " + it.data() + ";\n\t"; + + if(!m_selectorName.isEmpty()){// we're working on block + toDisplay.prepend(m_selectorName +" {\n\t"); + toDisplay+="}"; + } + else toDisplay.prepend("\n\t"); + + display->setText(toDisplay); +} + +#include "csseditor.moc" diff --git a/quanta/components/csseditor/csseditor.h b/quanta/components/csseditor/csseditor.h new file mode 100644 index 00000000..6994a686 --- /dev/null +++ b/quanta/components/csseditor/csseditor.h @@ -0,0 +1,117 @@ +/*************************************************************************** + csseditor.h - description + ------------------- + begin : mer lug 23 11:20:17 CEST 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 CSSEDITOR_H +#define CSSEDITOR_H + +#include +#include "csseditors.h" +#include +#include +#include +#include + +class propertySetter; +class KConfig; +class KHTMLPart; +class QListViewItem; +class QDomNodeList; +class QVariant; +class QMyHighlighter; + + +class myCheckListItem : public QCheckListItem +{ + private: + QSignal *m_sig; + unsigned int m_checkedChildren; + + public : + myCheckListItem(QCheckListItem * parent, const QString & text); + myCheckListItem(QListView * parent, const QString & text); + ~myCheckListItem(); + void connect( QObject *receiver, const char *member ); + void addCheckedChild(); + + protected : + virtual void activate(); + virtual void stateChange (bool); +}; + +/** CSSEditor is the base class of the project */ +class CSSEditor : public CSSEditorS +{ + Q_OBJECT + private: + QMyHighlighter *m_myhi; + propertySetter *m_ps; + myCheckListItem *m_currentProp; + KHTMLPart *m_previewer; + QDomDocument m_doc; + QMap m_properties; + QString m_selectorName, + m_initialProperties, + m_Selectors, + m_Header, + m_Footer, + + m_InlineStyleContent, + m_externalStyleSheetDefinition, + m_fileToPreview; + + bool m_isFileToPreviewExternal; + KConfig *m_config; + + //sourceFileName; + + void Connect(); + void appendSub(QDomNodeList, myCheckListItem *); + void buildListView(QDomNodeList, QListView *); + void updateDisplay(); + void activatePreview(); + void setCurrentPropOn(const QString& s); + void addProperty(const QString& property, const QString& value) { m_properties[property] = value; } + void addAndSetPropertyOn(const QString& property, const QString& value); + void setSidesOfPropertyBorderOn(const QString& s); + + private slots: + void checkProperty(const QString&); + void removeProperty(const QVariant&); + void updatePreview(); + void setMiniEditors(QListViewItem*); + void toggleShortendForm(); + + public: + + CSSEditor(QWidget* parent=0, const char *name=0): CSSEditorS(parent, name), m_config(0L){} + CSSEditor( QListViewItem * i, QWidget* parent=0, const char *name=0); + ~CSSEditor(); + void initialize(); + void setSelectors( const QString& s) { m_Selectors = s; } + void setHeader( const QString& s) { m_Header = s; } + void setFooter( const QString& s) { m_Footer = s;} + void setInlineStyleContent( const QString& s){ m_InlineStyleContent = s; } + QString generateProperties(); + void hidePreviewer(); + void setFileToPreview(const QString& s,bool b) { m_fileToPreview = s; m_isFileToPreviewExternal = b;} + void setExternalStyleSheetDefinition(const QString& s) { m_externalStyleSheetDefinition = s;} + + signals: + void signalUpdatePreview(); +}; + +#endif diff --git a/quanta/components/csseditor/csseditor_globals.cpp b/quanta/components/csseditor/csseditor_globals.cpp new file mode 100644 index 00000000..a73cb876 --- /dev/null +++ b/quanta/components/csseditor/csseditor_globals.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + csseditor_globals.cpp - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 +#include "csseditor_globals.h" + +mySpinBox::mySpinBox(QWidget * parent , const char * name ) : QSpinBox (parent, name){ + connect( editor(), SIGNAL(textChanged(const QString&)), this, SLOT(checkSuffix( const QString & ))); + connect( editor(), SIGNAL(textChanged(const QString&)), this, SIGNAL(valueChanged( const QString & ))); +} + +mySpinBox::mySpinBox( int minValue, int maxValue, int step, QWidget * parent, const char * name ) : QSpinBox( minValue, maxValue, step, parent,name ){ + connect( editor(), SIGNAL(textChanged(const QString&)), this, SLOT(checkSuffix( const QString & ))); + connect( editor(), SIGNAL(textChanged(const QString&)), this, SIGNAL(valueChanged( const QString & ))); +} + +mySpinBox::~mySpinBox(){} + +void mySpinBox::checkSuffix(const QString&){// check if the suffix is present and how many times : it normalizes these times to one + if(!suffix().isEmpty()){ + const QString suf(suffix()); + QString t(editor()->text()); + if( t.contains(suf) ==0 ) { + editor()->setText( t + suf); + editor()->setCursorPosition(editor()->cursorPosition() - 1); + } + else + if( t.contains(suf) >1 ) { + editor()->setText( t.remove(suf) + suf); + editor()->setCursorPosition(editor()->cursorPosition() - 1); + } + } +} + + +#include "csseditor_globals.moc" diff --git a/quanta/components/csseditor/csseditor_globals.h b/quanta/components/csseditor/csseditor_globals.h new file mode 100644 index 00000000..fefae7c8 --- /dev/null +++ b/quanta/components/csseditor/csseditor_globals.h @@ -0,0 +1,63 @@ +/*************************************************************************** + csseditor_globals.h - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 CSSEDITOR_GLOBALS_H +#define CSSEDITOR_GLOBALS_H +#include +#include +#include + +namespace CSSEditorGlobals { +const QStringList HTMLColors(QStringList::split(",",QString("aliceblue,antiquewhite,aqua,aquamarine,azure,beige,bisque,black,blanchedalmond," + "blue,blueviolet,brown,burlywood,cadetblue,chartreuse,chocolate,coral,cornflowerblue," + "cornsilk,crimson,cyan,darkblue,darkcyan,darkgoldenrod,darkgray,darkgreen," + "darkkhaki,darkmagenta,darkolivegreen,darkorange,darkorchid,darkred,darksalmon," + "darkseagreen,darkslateblue,darkslategray,darkturquoise,darkviolet,deeppink," + "deepskyblue,dimgray,dodgerblue,firebrick,floralwhite,forestgreen,fuchsia,gainsboro," + "ghostwhite,gold,goldenrod,gray,green,greenyellow,honeydew,hotpink,indianred," + "indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon,lightblue,lightcoral," + "lightcyan,lightgoldenrodyellow,lightgreen,lightgrey,lightpink,lightsalmon,lightseagreen," + "lightskyblue,lightslategray,lightsteelblue,lightyellow,lime,limegreen,linen,magenta," + "maroon,mediumaquamarine,mediumblue,mediumorchid,mediumpurple,mediumseagreen," + "mediumslateblue,mediumspringgreen,mediumturquoise,mediumvioletred,midnightblue," + "mintcream,mistyrose,moccasin,navajowhite,navy,oldlace,olive,olivedrab,orange," + "orangered,orchid,palegoldenrod,palegreen,paleturquoise,palevioletred,papayawhip," + "peachpuff,peru,pink,plum,powderblue,purple,red,rosybrown,royalblue,saddlebrown," + "salmon,sandybrown,seagreen,seashell,sienna,silver,skyblue,slateblue,slategray,snow," + "springgreen,steelblue,tan,teal,thistle,tomato,turquoise,violet,wheat,white,whitesmoke," + "yellow,yellowgreen"))); + + + const QStringList lengthUnits(QStringList::split(",",QString("cm,em,ex,in,mm,pc,pt,px"))); + const QStringList frequencyUnits(QStringList::split(",",QString("Hz,kHz"))); + const QStringList angleUnits(QStringList::split(",",QString("deg,rad,grad"))); + const QStringList timeUnits(QStringList::split(",",QString("s,ms"))); +} + + +class mySpinBox : public QSpinBox{ + Q_OBJECT + public: + mySpinBox(QWidget * parent = 0, const char * name = 0 ); + mySpinBox( int minValue, int maxValue, int step = 1, QWidget * parent = 0, const char * name = 0 ); + ~mySpinBox(); + public slots: + void checkSuffix(const QString&); +}; + + +#endif diff --git a/quanta/components/csseditor/csseditors.ui b/quanta/components/csseditor/csseditors.ui new file mode 100644 index 00000000..de99118f --- /dev/null +++ b/quanta/components/csseditor/csseditors.ui @@ -0,0 +1,411 @@ + +CSSEditorS + + + CSSEditorS + + + + 0 + 0 + 631 + 490 + + + + CSS Editor + + + true + + + + unnamed + + + + spacer1 + + + Horizontal + + + Expanding + + + + 280 + 20 + + + + + + layout6 + + + + unnamed + + + + pbOk + + + + 0 + 0 + 0 + 0 + + + + &OK + + + + + pbCancel + + + + 0 + 0 + 0 + 0 + + + + &Cancel + + + + + + + SHckb + + + Use shorthand form + + + false + + + + + splitter3 + + + NoFrame + + + Plain + + + Horizontal + + + + twMediaGroup + + + + 0 + 7 + 0 + 0 + + + + + 33 + 7 + + + + + 290 + 32767 + + + + + tab + + + Visual + + + + unnamed + + + 0 + + + + + Properties + + + false + + + false + + + + lvVisual + + + 13 + + + LastColumn + + + + + + + tab + + + Paged + + + + unnamed + + + 0 + + + + + Properties + + + true + + + true + + + + lvPaged + + + AllColumns + + + + + + + tab + + + Interactive + + + + unnamed + + + 0 + + + + + Properties + + + true + + + true + + + + lvInteractive + + + AllColumns + + + + + + + tab + + + Aural + + + + unnamed + + + 0 + + + + + Properties + + + true + + + true + + + + lvAural + + + AllColumns + + + + + + + tab + + + All + + + + unnamed + + + 0 + + + + + Properties + + + true + + + true + + + + lvAll + + + AllColumns + + + + + + + + splitter3 + + + Vertical + + + + fEditing + + + StyledPanel + + + Raised + + + + + fPreview + + + + 7 + 7 + 0 + 0 + + + + + 0 + 200 + + + + StyledPanel + + + Raised + + + + + display + + + + 7 + 7 + 0 + 0 + + + + + 32766 + 32766 + + + + true + + + + + + + pbHelp + + + false + + + &Help + + + + + + + + + pbCancel + clicked() + CSSEditorS + reject() + + + pbOk + clicked() + CSSEditorS + accept() + + + + + kpushbutton.h + + diff --git a/quanta/components/csseditor/cssselector.cpp b/quanta/components/csseditor/cssselector.cpp new file mode 100644 index 00000000..1425102f --- /dev/null +++ b/quanta/components/csseditor/cssselector.cpp @@ -0,0 +1,395 @@ +/*************************************************************************** + cssselector.cpp - description + ------------------- + begin : mer ago 6 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "cssselector.h" +#include "csseditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "project.h" +#include "stylesheetparser.h" + + +CSSSelector::CSSSelector(QWidget *parent, const char* name) : CSSSelectorS (parent,name),m_orderNumber(0),m_stopProcessingStylesheet(false) { + + m_currentItem = 0L; + + Connect(); + + kurApplyToFile->fileDialog()->setURL(Project::ref()->projectBaseURL().url()); + kurApplyToFile->fileDialog()->setFilter( "*.html *.htm |" + i18n("HTML Files") +" (*.html *.htm)\n*.xhtml |" + i18n("XHTML Files")+" (*.xhtml)\n*.xml |" + i18n("XML Files")+" (*.xml)\n*.*|" + i18n("All Files")+" (*.*)" ); + QWhatsThis::add((QLineEdit*)(kurApplyToFile->lineEdit()),"With this line edit you can insert the URL of the file you want to use to preview the style sheet you are editing"); + + /*QString configDir = locate("appdata", "csseditor/config.xml"); + configDir = QFileInfo(configDir).dirPath() + "/";*/ + + QString configDir = QFileInfo( locate("appdata", "csseditor/config.xml") ).dirPath() + "/"; + + QDomDocument doc; + QFile file( configDir+"pseudo.xml" ); + if ( !file.open( IO_ReadOnly ) ) + return; + if ( !doc.setContent( &file ) ) { + file.close(); + return; + } + file.close(); + + QDomElement docElem = doc.documentElement(); + + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + QDomElement e = n.toElement(); + if( !e.isNull() ) { + cbPseudo->insertItem(e.attribute("name")); + } + n = n.nextSibling(); + } + + file.setName( configDir+"dtdTags.xml" ); + if ( !file.open( IO_ReadOnly ) ) + return; + if ( !doc.setContent( &file ) ) { + file.close(); + return; + } + file.close(); + + QStringList dtdNames, + dtdNickNames; + docElem = doc.documentElement(); + n = docElem.firstChild(); + while( !n.isNull() ) { + QDomElement e = n.toElement(); + if( !e.isNull() ) { + dtdNames.append(e.attribute("name")); + dtdNickNames.append(e.attribute("nickName")); + if(e.attribute("default") == "yes") { + QStringList tagList = QStringList::split( ',',e.text() ); + tagList.sort(); + cbTag->insertStringList( tagList ); + cbTag->setAutoCompletion(true); + } + } + n = n.nextSibling(); + } + cbDTD->insertStringList( dtdNickNames ); +} + +CSSSelector::~CSSSelector(){ +} + +void CSSSelector::Connect(){ + + connect(cbDTD,SIGNAL(activated(const QString&)),this,SLOT(setDTDTags(const QString&))); + + connect(pbAddTag,SIGNAL(clicked()), this ,SLOT(addTag())); + connect(pbAddClass,SIGNAL(clicked()), this ,SLOT(addClass())); + connect(pbAddID,SIGNAL(clicked()), this ,SLOT(addID())); + connect(pbAddPseudo,SIGNAL(clicked()), this ,SLOT(addPseudo())); + + connect(lvTags, SIGNAL(doubleClicked( QListViewItem * )), this, SLOT(openCSSEditor(QListViewItem *))); + connect(lvClasses, SIGNAL(doubleClicked( QListViewItem * )), this, SLOT(openCSSEditor(QListViewItem *))); + connect(lvIDs, SIGNAL(doubleClicked( QListViewItem * )), this, SLOT(openCSSEditor(QListViewItem *))); + connect(lvPseudo, SIGNAL(doubleClicked( QListViewItem * )), this, SLOT(openCSSEditor(QListViewItem *))); + + connect(lvTags, SIGNAL(selectionChanged( QListViewItem * )), this, SLOT(setCurrentItem(QListViewItem *))); + connect(lvClasses, SIGNAL(selectionChanged( QListViewItem * )), this, SLOT(setCurrentItem(QListViewItem *))); + connect(lvIDs, SIGNAL(selectionChanged( QListViewItem * )), this, SLOT(setCurrentItem(QListViewItem *))); + connect(lvPseudo, SIGNAL( selectionChanged( QListViewItem * )), this, SLOT(setCurrentItem(QListViewItem *))); + + connect(pbRemoveSelectedTag,SIGNAL(clicked()), this ,SLOT(removeSelected())); + connect(pbRemoveSelectedClass,SIGNAL(clicked()), this ,SLOT(removeSelected())); + connect(pbRemoveSelectedID,SIGNAL(clicked()), this ,SLOT(removeSelected())); + connect(pbRemoveSelectedPseudo,SIGNAL(clicked()), this ,SLOT(removeSelected())); + + connect(twSelectors,SIGNAL(currentChanged ( QWidget * )), this ,SLOT(setCurrentListView( QWidget * ))); + + connect(pbRemoveAllTags,SIGNAL(clicked()), this ,SLOT(removeAll())); + connect(pbRemoveAllClasses,SIGNAL(clicked()), this ,SLOT(removeAll())); + connect(pbRemoveAllIDs,SIGNAL(clicked()), this ,SLOT(removeAll())); + connect(pbRemoveAllPseudo,SIGNAL(clicked()), this ,SLOT(removeAll())); +} + +void CSSSelector::setDTDTags(const QString& s){ + + QString configDir = QFileInfo( locate("appdata", "csseditor/config.xml") ).dirPath() + "/"; + + QDomDocument doc; + + QFile file( configDir+"dtdTags.xml" ); + if ( !file.open( IO_ReadOnly ) ) + return; + if ( !doc.setContent( &file ) ) { + file.close(); + return; + } + file.close(); + + QStringList dtdNames; + QDomElement docElem = doc.documentElement(); + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + if( n.toElement().attribute("nickName") == s ) + break; + n = n.nextSibling(); + } + QStringList tagList = QStringList::split( ',',n.toElement().text() ); + tagList.sort(); + cbTag->clear(); + cbTag->insertStringList( tagList ); + cbTag->setAutoCompletion(true); +} + +void CSSSelector::addTag(){ + QListViewItem *item = new QListViewItem(lvTags); + if(!cbTag->currentText().isEmpty()){ + item->setText(0,cbTag->currentText()); + QPair tmp(QString::null,++m_orderNumber); + m_currentStylesheetStructure[item->text(0)]=tmp; + } +} + +void CSSSelector::addClass(){ + QListViewItem *item = new QListViewItem(lvClasses); + if(!leClass->text().isEmpty()){ + item->setText(0,leClass->text()); + QPair tmp(QString::null,++m_orderNumber); + m_currentStylesheetStructure[item->text(0)]=tmp; + } +} + +void CSSSelector::addID(){ + QListViewItem *item = new QListViewItem(lvIDs); + if(!leID->text().isEmpty()){ + item->setText(0,leID->text()); + QPair tmp(QString::null,++m_orderNumber); + m_currentStylesheetStructure[item->text(0)]=tmp; + } +} + +void CSSSelector::addPseudo(){ + QListViewItem *item = new QListViewItem(lvPseudo); + item->setText(0,(lePseudoSelector->text()+":"+cbPseudo->currentText()).stripWhiteSpace()); + QPair tmp(QString::null,++m_orderNumber); + m_currentStylesheetStructure[item->text(0)]=tmp; +} + +void CSSSelector::openCSSEditor(QListViewItem * i){ + if(!m_stopProcessingStylesheet){ + QListView *lv = i->listView(); + QListViewItem *temp; + QString s; + QObjectList *l = queryList( "QListView" ); + QObjectListIt it( *l ); // iterate over the listviews + QObject *obj; + + while ( (obj = it.current()) != 0 ) { + QListView *lvTemp = (QListView*)obj; + if( lv != lvTemp){ + temp = lvTemp->firstChild(); + while(temp){ + s+=(temp->text(0)+" { "+temp->text(1)+" } "); + temp = temp->nextSibling(); + } + } + ++it; + } + delete l; // delete the list, not the objects + + temp = lv->firstChild(); + + while(temp){ + if(temp != i) s+=(temp->text(0)+" { "+temp->text(1)+" } "); + temp = temp->nextSibling(); + } + + CSSEditor dlg(i); + if(m_callingFrom == "XHTML"){ + dlg.setHeader(m_header); + dlg.setSelectors(s); + dlg.setFooter(m_footer); + dlg.setFileToPreview(m_fileToPreview,false); + } + else if(m_callingFrom == "CSS"){ + if(kurApplyToFile->url().isEmpty()) + dlg.hidePreviewer(); + else { + dlg.setFileToPreview(kurApplyToFile->url(),true); + + QString tmp; + QListViewItem *item = lvTags->firstChild(); + while( item ) { + if(i->text(0).stripWhiteSpace() != item->text(0).stripWhiteSpace()) + tmp += item->text(0) + " {" + item->text(1) + "}"; + item = item->nextSibling(); + } + + item = lvClasses->firstChild(); + while( item ) { + if(i->text(0).stripWhiteSpace() != item->text(0).stripWhiteSpace()) + tmp += item->text(0) + " {" + item->text(1) + "}"; + item = item->nextSibling(); + } + + item = lvIDs->firstChild(); + while( item ) { + if(i->text(0).stripWhiteSpace() != item->text(0).stripWhiteSpace()) + tmp += item->text(0) + " {" + item->text(1) + "}"; + item = item->nextSibling(); + } + + item = lvPseudo->firstChild(); + while( item ) { + if(i->text(0).stripWhiteSpace() != item->text(0).stripWhiteSpace()) + tmp += item->text(0) + " {" + item->text(1) + "}"; + item = item->nextSibling(); + } + + dlg.setExternalStyleSheetDefinition(tmp); + } + } + + dlg.initialize(); + + if(dlg.exec()) { + i->setText(1,dlg.generateProperties()); + QPair tmp(m_currentStylesheetStructure[i->text(0)]); + tmp.first = dlg.generateProperties(); + m_currentStylesheetStructure[i->text(0)] = tmp; + } + } +} + +void CSSSelector::setCurrentListView(QWidget* w){ + QObjectList *l = w->queryList( "QListView" ); + m_currentListView = static_cast(l->first()); +} + +void CSSSelector::removeAll(){ + QListViewItemIterator it( m_currentListView ); + while ( it.current() ) { + QListViewItem *item = it.current(); + m_currentStylesheetStructure.remove(item->text(0)); + ++it; + } + m_currentListView->clear(); +} + +void CSSSelector::removeSelected(){ + if( m_currentItem ) { + m_currentStylesheetStructure.remove(m_currentItem->text(0)); + delete m_currentItem; + m_currentItem = 0L; + } +} + +void CSSSelector::loadCSSContent(const QString& s){ + stylesheetParser p(s); + connect(&p,SIGNAL(errorOccurred(const QString&)), this, SLOT(setStylesheetProcessing(const QString&))); + p.parse(); + m_orderNumber = p.orderNumber(); + + QMap >::Iterator it; + m_currentStylesheetStructure = p.stylesheetStructure(); + for ( it = m_currentStylesheetStructure.begin(); it != m_currentStylesheetStructure.end(); ++it ) { + if(!it.key().startsWith("@rule") && !it.key().startsWith("/*")){ + QListViewItem *item; + if(it.key().contains(":")){ + item = new QListViewItem(lvPseudo); + } + else + if(it.key().contains("#")){ + item = new QListViewItem(lvIDs); + } + else + if(it.key().contains(".")){ + item = new QListViewItem(lvClasses); + } + else { + item = new QListViewItem(lvTags); + } + + item->setText(0,it.key()); + item->setText(1,it.data().first); + + } + } +} + +QString CSSSelector::generateFormattedStyleSection(){ + QMap< QString,QPair >::Iterator it; + QString styleSection,tmpStr; + unsigned int indentWidth, + indentDisplacement = 2; + for ( unsigned int i=0;i<=m_orderNumber;i++ ) { + for ( it = m_currentStylesheetStructure.begin(); it != m_currentStylesheetStructure.end(); ++it ) { + QString key = it.key(); + if(it.data().second == i){ + if(key.startsWith("@rule")) + styleSection += it.data().first; + else if(key.startsWith("/*")) + styleSection += it.data().first; + else { + key.remove(QRegExp("-v[\\d]+$")); + styleSection += "\n" + key + " {\n"; + indentWidth = indentDisplacement + 2; + QStringList props = QStringList::split(";",it.data().first.simplifyWhiteSpace()); + QString indentStr; + indentStr.fill(' ',indentWidth); + for ( QStringList::Iterator it = props.begin(); it != props.end(); ++it ) { + if((*it).startsWith(" ")) + tmpStr += indentStr + (*it).remove(0,1) + ";\n"; + else + tmpStr += indentStr + (*it) + ";\n"; + } + indentStr.fill(' ', indentDisplacement); + styleSection += tmpStr + indentStr + "}\n\n"; + tmpStr = QString::null; + } + } + } + } + return "\n"+styleSection; +} + +void CSSSelector::enableApplyToFile(){ + tlApplyToFile->setEnabled(true); + kurApplyToFile->setEnabled(true); +} + +void CSSSelector::setStylesheetProcessing(const QString& msg) { + m_stopProcessingStylesheet=true; + KMessageBox::error (0L, msg ); +} + +#include "cssselector.moc" diff --git a/quanta/components/csseditor/cssselector.h b/quanta/components/csseditor/cssselector.h new file mode 100644 index 00000000..f4d42e89 --- /dev/null +++ b/quanta/components/csseditor/cssselector.h @@ -0,0 +1,74 @@ +/*************************************************************************** + cssselector.h - description + ------------------- + begin : mer ago 6 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 CSSSELECTOR_H +#define CSSSELECTOR_H + +#include +#include +#include "cssselectors.h" + +class QListViewItem; +class QStringList; +/** + *@author gulmini luciano + */ + +class CSSSelector : public CSSSelectorS { + Q_OBJECT + + private: + QListViewItem *m_currentItem; + QListView *m_currentListView; + QString m_header, + m_footer, + m_callingFrom, + m_fileToPreview; + QMap > m_currentStylesheetStructure; + unsigned int m_orderNumber; + bool m_stopProcessingStylesheet; + + void Connect(); + + public: + CSSSelector(QWidget *parent=0, const char* name=0); + ~CSSSelector(); + void loadCSSContent(const QString& s); + void setHeader(const QString& h) { m_header = h; } + void setFooter(const QString& f) { m_footer = f; } + void enableApplyToFile(); + void setCallingFrom(const QString& cf){ m_callingFrom = cf ;} + void setFileToPreview(const QString& s){ m_fileToPreview=s;} + bool errorOnProcessingStylesheet() const { return m_stopProcessingStylesheet; } + QString generateFormattedStyleSection(); + + private slots: + void openCSSEditor(QListViewItem *); + void addTag(); + void addClass(); + void addID(); + void addPseudo(); + void removeAll(); + void removeSelected(); + void setCurrentItem(QListViewItem* i) { m_currentItem = i; } + void setCurrentListView(QWidget*); + void setDTDTags(const QString&); + void setStylesheetProcessing(const QString&); +}; + +#endif + diff --git a/quanta/components/csseditor/cssselectors.ui b/quanta/components/csseditor/cssselectors.ui new file mode 100644 index 00000000..1119ccdb --- /dev/null +++ b/quanta/components/csseditor/cssselectors.ui @@ -0,0 +1,985 @@ + +CSSSelectorS + + + CSSSelectorS + + + + 0 + 0 + 621 + 496 + + + + CSS Selector Dialog + + + true + + + + unnamed + + + + layout11 + + + + unnamed + + + + tlApplyToFile + + + false + + + Apply to file: + + + + + kurApplyToFile + + + false + + + + + + + spacer19_2 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + layout1 + + + + unnamed + + + + pbOk + + + &OK + + + + + pbCancel + + + &Cancel + + + + + + + twSelectors + + + + tab + + + Tags + + + + unnamed + + + + layout13 + + + + unnamed + + + + spacer6_2 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + groupBox1 + + + + 5 + 5 + 1 + 0 + + + + Remove Selector + + + + unnamed + + + + pbRemoveSelectedTag + + + + + + + Selected + + + + + pbRemoveAllTags + + + All + + + + + + + spacer6 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + groupBox2 + + + DTD Selection + + + + unnamed + + + + cbDTD + + + + + + + spacer7_3 + + + Vertical + + + Expanding + + + + 20 + 24 + + + + + + groupBox3 + + + Add Selector + + + + unnamed + + + + cbTag + + + true + + + + + pbAddTag + + + Add + + + + + + + spacer6_3 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + + + + Selector + + + true + + + true + + + + + Properties + + + true + + + true + + + + lvTags + + + + 7 + 7 + 1 + 0 + + + + true + + + true + + + LastColumn + + + + + spacer15 + + + Horizontal + + + Minimum + + + + 40 + 20 + + + + + + + + tab + + + IDs + + + + unnamed + + + + + Selector + + + true + + + true + + + + + Properties + + + true + + + true + + + + lvIDs + + + + 7 + 7 + 1 + 0 + + + + true + + + true + + + LastColumn + + + + + spacer18 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + layout14 + + + + unnamed + + + + spacer12 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox4_2 + + + Remove Selector + + + + unnamed + + + + pbRemoveSelectedID + + + + + + + Selected + + + + + pbRemoveAllIDs + + + All + + + + + + + spacer13 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox7_2 + + + Add Selector + + + + unnamed + + + + leID + + + + + pbAddID + + + Add + + + + + + + spacer14 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + + tab + + + Classes + + + + unnamed + + + + + Selector + + + true + + + true + + + + + Properties + + + true + + + true + + + + lvClasses + + + + 7 + 7 + 1 + 0 + + + + true + + + true + + + LastColumn + + + + + spacer19 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + layout13 + + + + unnamed + + + + spacer9 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox4_3 + + + Remove Selector + + + + unnamed + + + + pbRemoveSelectedClass + + + + + + + Selected + + + + + pbRemoveAllClasses + + + All + + + + + + + spacer11 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox7 + + + Add Selector + + + + unnamed + + + + leClass + + + + + pbAddClass + + + Add + + + + + + + spacer10 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + + tab + + + Pseudo + + + + unnamed + + + + + Selector + + + true + + + true + + + + + Properties + + + true + + + true + + + + lvPseudo + + + + 7 + 7 + 1 + 0 + + + + true + + + true + + + LastColumn + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + layout17 + + + + unnamed + + + + spacer15_2 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox4 + + + Remove Selector + + + + unnamed + + + + pbRemoveAllPseudo + + + All + + + + + pbRemoveSelectedPseudo + + + + + + + Selected + + + + + + + spacer16 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + groupBox7_3 + + + Add Selector + + + + unnamed + + + + lePseudoSelector + + + + + cbPseudo + + + true + + + + + pbAddPseudo + + + Add + + + + + + + spacer17 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 380 + 20 + + + + + + pbHelp + + + false + + + &Help + + + + + + + + + pbOk + clicked() + CSSSelectorS + accept() + + + pbCancel + clicked() + CSSSelectorS + reject() + + + + + kurlrequester.h + klineedit.h + kpushbutton.h + kpushbutton.h + + diff --git a/quanta/components/csseditor/cssshpropertyparser.cpp b/quanta/components/csseditor/cssshpropertyparser.cpp new file mode 100644 index 00000000..d02c39a5 --- /dev/null +++ b/quanta/components/csseditor/cssshpropertyparser.cpp @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2003 by Gulmini Luciano * + * gulmini.luciano@student.unife.it * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "cssshpropertyparser.h" +#include +//#include + +CSSSHPropertyParser::CSSSHPropertyParser(const QString& s){ + QStringList l1, + l2=QStringList::split(",",s); + + for ( QStringList::Iterator it = l2.begin(); it != l2.end(); ++it ) { + QString temp; + temp=removeBeginningWhiteSpaces((*it)); + temp=removeEndingWhiteSpaces(temp); + l1.append(temp); + } + + m_propertyToParse = l1.join(",");// we eliminte blanks before after a comma in things like "something" , something , serif +} + +CSSSHPropertyParser::~CSSSHPropertyParser(){} + +QString CSSSHPropertyParser::removeEndingWhiteSpaces(const QString& s){ + int index = s.length()-1; + while(s[index] == ' ' ) index--; + return s.left(index+1); +} + +QString CSSSHPropertyParser::removeBeginningWhiteSpaces(const QString& s){ + int index = 0; + while(s[index] == ' ' ) index++; + return s.right(s.length()-index); +} + +QString CSSSHPropertyParser::extractFunctionList(){ + QRegExp functionListPattern("\\s*([a-zA-Z0-9_]*\\([\\W\\w]*\\))\\s*"); + functionListPattern.search(m_propertyToParse); + return functionListPattern.cap(1); +} + +QString CSSSHPropertyParser::extractQuotedStringList(){ + QString temp; + bool stop = false; + unsigned int i=0; + while(!stop && i + +class CSSSHPropertyParser{ + + public: + CSSSHPropertyParser(const QString& s); + ~CSSSHPropertyParser(); + QStringList parse(); + + private: + QString m_propertyToParse; + + private: + QString extractURIList(); + QString extractFunctionList(); + QString extractQuotedStringList(); + QString removeBeginningWhiteSpaces(const QString& s); + QString removeEndingWhiteSpaces(const QString& s); +}; + +#endif diff --git a/quanta/components/csseditor/data/Makefile.am b/quanta/components/csseditor/data/Makefile.am new file mode 100644 index 00000000..01ddeee5 --- /dev/null +++ b/quanta/components/csseditor/data/Makefile.am @@ -0,0 +1,3 @@ +cssxmldir= ${quanta_datadir}/csseditor +cssxml_DATA = config.xml pseudo.xml atrules.xml dtdTags.xml + diff --git a/quanta/components/csseditor/data/atrules.xml b/quanta/components/csseditor/data/atrules.xml new file mode 100644 index 00000000..4d9f0d38 --- /dev/null +++ b/quanta/components/csseditor/data/atrules.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/quanta/components/csseditor/data/config.xml b/quanta/components/csseditor/data/config.xml new file mode 100644 index 00000000..15fd659f --- /dev/null +++ b/quanta/components/csseditor/data/config.xml @@ -0,0 +1,609 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/quanta/components/csseditor/data/dtdTags.xml b/quanta/components/csseditor/data/dtdTags.xml new file mode 100644 index 00000000..1ce44d82 --- /dev/null +++ b/quanta/components/csseditor/data/dtdTags.xml @@ -0,0 +1,19 @@ + + + style,link,h1,h2,h3,h4,h5,h6,ul,pre,tt,i,b,big,em,strong,dfn,code,samp,kbd,var,cite,abbr,acronym,img,br,script,map,span,bdo,select,textarea,label,button,p,dl,div,noscript,blockquote,hr,table,fieldset,body,address,a,area,object,param,small,sub,sup,q,dt,dd,ol,li,form,text,password,checkbox,radio,submit,reset,file,hidden,input,optgroup,option,legend,caption,thead,tfoot,tbody,colgroup,col,tr,th,td,head,title,base,meta,html + a,abbr,acronym,address,applet,area,b,base,basefont,bdo,big,blockquote,body,br,button,caption,center,cite,code,col,colgroup,div,dfn,del,dl,dt,dd,dir,em,fieldset,frameset,frame,font,form,kbd,head,html,hr,h1,h2,h3,h4,h5,h6,i,iframe,img,input,ins,isindex,label,legend,li,link,map,menu,meta,noframes,noscript,object,ol,optgroup,option,p,param,pre,q,s,samp,script,select,small,span,strike,strong,style,sub,sup,table,textarea,tt,thead,tfoot,tbody,tr,th,td,title,u,ul,usemap,var + mi,mn,mo,mtext,mspace,ms,mglyph,mrow,mfrac,msrqt,mroot,mstyle,merror,mpadded,mphantom,mfenced,menclose,msub,msup,msubsup,munder,mover,munderover,nmultiscripts,mtable,mtr,mlabeldtr,mtd,maction + + + + + + + + + + + + + + diff --git a/quanta/components/csseditor/data/pseudo.xml b/quanta/components/csseditor/data/pseudo.xml new file mode 100644 index 00000000..354544ff --- /dev/null +++ b/quanta/components/csseditor/data/pseudo.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quanta/components/csseditor/doubleeditors.cpp b/quanta/components/csseditor/doubleeditors.cpp new file mode 100644 index 00000000..6fab0547 --- /dev/null +++ b/quanta/components/csseditor/doubleeditors.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + doubleeditors.cpp - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "doubleeditors.h" + #include "specialsb.h" + #include + #include "csseditor_globals.h" + #include "propertysetter.h" + #include + + + +doubleEditorBase::doubleEditorBase(QWidget *parent, const char *name) : miniEditor(parent,name){ +} + +void doubleEditorBase::sxValueSlot(const QString& v){ + m_sxValue=v; + emit valueChanged( m_sxValue +" " + m_dxValue); +} + +void doubleEditorBase::dxValueSlot(const QString& v){ + m_dxValue=v; + emit valueChanged( m_sxValue +" " + m_dxValue); +} + + doubleLengthEditor::doubleLengthEditor(QWidget *parent, const char *name) : doubleEditorBase(parent,name){ + + m_ssbSx = new specialSB(this); + m_ssbSx->insertItem("cm"); + m_ssbSx->insertItem("em"); + m_ssbSx->insertItem("ex"); + m_ssbSx->insertItem("in"); + m_ssbSx->insertItem("mm"); + m_ssbSx->insertItem("pc"); + m_ssbSx->insertItem("pt"); + m_ssbSx->insertItem("px"); + + m_ssbDx = new specialSB(this); + m_ssbDx->insertItem("cm"); + m_ssbDx->insertItem("em"); + m_ssbDx->insertItem("ex"); + m_ssbDx->insertItem("in"); + m_ssbDx->insertItem("mm"); + m_ssbDx->insertItem("pc"); + m_ssbDx->insertItem("pt"); + m_ssbDx->insertItem("px"); + + connect(m_ssbSx, SIGNAL(valueChanged(const QString&)), this, SLOT(sxValueSlot(const QString&))); + connect(m_ssbDx, SIGNAL(valueChanged(const QString&)), this, SLOT(dxValueSlot(const QString&))); +} + +doubleLengthEditor::~doubleLengthEditor(){ + delete m_ssbSx; + delete m_ssbDx; +} + +void doubleLengthEditor::connectToPropertySetter(propertySetter* p){ + connect(this, SIGNAL(valueChanged(const QString&)), p ,SIGNAL(valueChanged(const QString&))); +} + +void doubleLengthEditor::setInitialValue(const QString& sx, const QString& dx){ + m_ssbSx->setInitialValue(sx); + m_ssbDx->setInitialValue(dx); +} + +doubleComboBoxEditor::doubleComboBoxEditor(QWidget *parent, const char *name) : doubleEditorBase(parent,name){ + m_cbSx = new QComboBox(this); + m_cbDx = new QComboBox(this); + connect(m_cbSx, SIGNAL(activated ( const QString & )), this, SLOT(sxValueSlot(const QString&))); + connect(m_cbDx, SIGNAL(activated ( const QString & )), this, SLOT(dxValueSlot(const QString&))); +} + +doubleComboBoxEditor::~doubleComboBoxEditor(){ + delete m_cbSx; + delete m_cbDx; +} + +void doubleComboBoxEditor::connectToPropertySetter(propertySetter* p){ + connect(this, SIGNAL(valueChanged(const QString&)), p ,SIGNAL(valueChanged(const QString&))); +} + +doublePercentageEditor::doublePercentageEditor(QWidget *parent, const char *name) : doubleEditorBase(parent,name){ + m_sbSx = new mySpinBox(this); + m_sbDx = new mySpinBox(this); + m_sbSx->setSuffix("%"); + m_sbDx->setSuffix("%"); + connect(m_sbSx,SIGNAL(valueChanged(const QString&)),this,SLOT(sxValueSlot(const QString&))); + connect(m_sbDx,SIGNAL(valueChanged(const QString&)),this,SLOT(dxValueSlot(const QString&))); +} + +doublePercentageEditor::~doublePercentageEditor(){ + delete m_sbSx; + delete m_sbDx; +} + +void doublePercentageEditor::connectToPropertySetter(propertySetter* p){ + connect(this, SIGNAL(valueChanged(const QString&)), p ,SIGNAL(valueChanged(const QString&))); +} + +void doublePercentageEditor::setInitialValue(const QString& a_sx, const QString& a_dx){ + QString sx = a_sx; + QString dx = a_dx; + m_sbSx->setValue(sx.remove("%").toInt()); + m_sbDx->setValue(dx.remove("%").toInt()); +} + +#include "doubleeditors.moc" diff --git a/quanta/components/csseditor/doubleeditors.h b/quanta/components/csseditor/doubleeditors.h new file mode 100644 index 00000000..6496a6fa --- /dev/null +++ b/quanta/components/csseditor/doubleeditors.h @@ -0,0 +1,86 @@ +/*************************************************************************** + doubleeditors.h - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 DOUBLEEDITORS_H + #define DOUBLEEDITORS_H + #include "minieditor.h" + + class mySpinBox; + class specialSB; + class QSpinBox; + class QComboBox; + +class doubleEditorBase : public miniEditor { + Q_OBJECT + protected: + QString m_sxValue, + m_dxValue; + + public: + doubleEditorBase(QWidget *parent=0, const char *name=0); + virtual ~doubleEditorBase(){} + virtual void setInitialValue(){} + virtual void connectToPropertySetter(propertySetter* /*p*/){} + + public slots: + void sxValueSlot(const QString&); + void dxValueSlot(const QString&); + + signals: + void valueChanged(const QString&); +}; + +class doublePercentageEditor : public doubleEditorBase { + Q_OBJECT + private: + mySpinBox *m_sbSx, + *m_sbDx; + + public: + doublePercentageEditor(QWidget *parent=0, const char *name=0); + virtual ~doublePercentageEditor(); + virtual void setInitialValue(const QString& sx, const QString& dx); + virtual void connectToPropertySetter(propertySetter* p); +}; + +class doubleComboBoxEditor : public doubleEditorBase { + Q_OBJECT + private: + QComboBox *m_cbSx, + *m_cbDx; + + public: + doubleComboBoxEditor(QWidget *parent=0, const char *name=0); + virtual ~doubleComboBoxEditor(); + QComboBox* cbSx() const { return m_cbSx;} + QComboBox* cbDx() const { return m_cbDx;} + virtual void connectToPropertySetter(propertySetter* p); +}; + +class doubleLengthEditor : public doubleEditorBase { + Q_OBJECT + private: + specialSB *m_ssbSx, + *m_ssbDx; + + public: + doubleLengthEditor(QWidget *parent=0, const char *name=0); + virtual ~doubleLengthEditor(); + virtual void setInitialValue(const QString& sx, const QString& dx); + virtual void connectToPropertySetter(propertySetter* p); +}; + +#endif diff --git a/quanta/components/csseditor/encodingselector.cpp b/quanta/components/csseditor/encodingselector.cpp new file mode 100644 index 00000000..3eeb593b --- /dev/null +++ b/quanta/components/csseditor/encodingselector.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + encodingselector.cpp - description + ------------------- + begin : mer ago 6 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "encodingselector.h" +#include +#include +#include + +/** + *@author gulmini luciano + */ + +encodingSelector::encodingSelector(QWidget *parent, const char* name) : encodingSelectorS(parent,name){ + QStringList encodings (KGlobal::charsets()->availableEncodingNames()); + int insert = 0; + for (uint i=0; i < encodings.count(); i++) { + bool found = false; + QTextCodec *codecForEnc = KGlobal::charsets()->codecForName(encodings[i], found); + + if (found){ + cbEncoding->insertItem (encodings[i]); + insert++; + } + } +} + +encodingSelector::~encodingSelector(){} + + + +#include "encodingselector.moc" diff --git a/quanta/components/csseditor/encodingselector.h b/quanta/components/csseditor/encodingselector.h new file mode 100644 index 00000000..3b10fa23 --- /dev/null +++ b/quanta/components/csseditor/encodingselector.h @@ -0,0 +1,40 @@ +/*************************************************************************** + encodingselector.h - description + ------------------- + begin : mer ago 6 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 ENCODINGSELECTOR_H +#define ENCODINGSELECTOR_H + + +#include "encodingselectors.h" +#include + +/** + *@author gulmini luciano + */ + +class encodingSelector : public encodingSelectorS { + Q_OBJECT + + public: + encodingSelector(QWidget *parent=0, const char* name=0); + ~encodingSelector(); + QString encodingSet() const { return cbEncoding->currentText();} + + }; + +#endif + diff --git a/quanta/components/csseditor/encodingselectors.ui b/quanta/components/csseditor/encodingselectors.ui new file mode 100644 index 00000000..45d269de --- /dev/null +++ b/quanta/components/csseditor/encodingselectors.ui @@ -0,0 +1,115 @@ + +encodingSelectorS + + + encodingSelectorS + + + + 0 + 0 + 228 + 109 + + + + Encoding Selector + + + + unnamed + + + + layout3 + + + + unnamed + + + + layout1 + + + + unnamed + + + + textLabel1 + + + Select encoding: + + + + + cbEncoding + + + + + + + layout2 + + + + unnamed + + + + pbOk + + + &OK + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + pbCancel + + + &Cancel + + + + + + + + + + + pbOk + clicked() + encodingSelectorS + accept() + + + pbCancel + clicked() + encodingSelectorS + reject() + + + + diff --git a/quanta/components/csseditor/fontfamilychooser.cpp b/quanta/components/csseditor/fontfamilychooser.cpp new file mode 100644 index 00000000..d42139f8 --- /dev/null +++ b/quanta/components/csseditor/fontfamilychooser.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + fontfamilychooser.cpp - description + ------------------- + begin : mer lug 23 11:20:17 CEST 2003 + copyright : (C) |YEAR| by si2003 email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "fontfamilychooser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +fontFamilyChooser::fontFamilyChooser(QWidget* parent, const char *name) : fontFamilyChooserS(parent,name){ + + QFont tmpFont( KGlobalSettings::generalFont().family(), 64, QFont::Black ); + lePreview->setMinimumHeight( lePreview->fontMetrics().lineSpacing() ); + lePreview->setAlignment(Qt::AlignCenter); + QFont font; + font.setPointSize(20); + lePreview->setFont(font); + lePreview->setText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog")); + + QFontDatabase fdb; + QStringList families = fdb.families(); + for ( QStringList::Iterator it = families.begin(); it != families.end(); ++it ) { + if( (*it).contains('[') !=0 ) + it = families.remove(it); + } + + if( families.count() != 0 ) lbAvailable->insertStringList(families); + + + QIconSet iconSet = SmallIconSet(QString::fromLatin1("forward")); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + pbAdd->setIconSet(iconSet); + pbAdd->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + + iconSet = SmallIconSet(QString::fromLatin1("back")); + pbRemove->setIconSet(iconSet); + pbRemove->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + + iconSet = SmallIconSet(QString::fromLatin1("up")); + pbMoveUp->setIconSet(iconSet); + pbMoveUp->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + + iconSet = SmallIconSet(QString::fromLatin1("down")); + pbMoveDown->setIconSet(iconSet); + pbMoveDown->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + + connect(pbAdd, SIGNAL(clicked()), this ,SLOT( addFont() )); + connect( lbAvailable, SIGNAL( highlighted( const QString& ) ), this, SLOT( updatePreview( const QString&) ) ); + connect( lbAvailable, SIGNAL( highlighted( const QString& ) ), this, SLOT( setCurrentSelectedAvailableFamilyFont( const QString&) ) ); + connect( lbGeneric, SIGNAL( highlighted( const QString& ) ), this, SLOT( updatePreview( const QString&) ) ); + connect( lbGeneric, SIGNAL( highlighted( const QString& ) ), this, SLOT( setCurrentSelectedGenericFamilyFont( const QString&) ) ); + connect( lbSelected, SIGNAL( highlighted( const QString& ) ), this, SLOT( updatePreview( const QString&) ) ); + connect( lbSelected, SIGNAL( highlighted( int ) ), this, SLOT( setCurrentSelectedFont( int ) ) ); + connect( lbSelected, SIGNAL( highlighted( const QString& ) ), this, SLOT( setCurrentSelectedFont( const QString&) ) ); + connect( pbRemove, SIGNAL( clicked() ), this, SLOT( removeFont() ) ); + connect( pbMoveUp, SIGNAL( clicked() ), this, SLOT( moveFontUp() ) ); + connect( pbMoveDown, SIGNAL( clicked() ), this, SLOT( moveFontDown() ) ); + + QWhatsThis::add(lbAvailable,i18n("These are the names of the available fonts on your system")); + QWhatsThis::add(lbGeneric,i18n("These are the names of the generic fonts ")); + QWhatsThis::add(lbSelected,i18n("These are the names of the generic fonts you have selected ")); + QWhatsThis::add(pbAdd,i18n("Click this to add a font to your style sheet")); + QWhatsThis::add(pbRemove,i18n("Click this to remove a font from your style sheet")); + QWhatsThis::add(pbMoveUp,i18n("Click this to make the font more preferable than the preceeding one")); + QWhatsThis::add(pbMoveDown,i18n("Click this to make the font less preferable than the following one")); + +} + +fontFamilyChooser::~fontFamilyChooser(){} + +void fontFamilyChooser::updatePreview(const QString& s){ + lePreview->setFont(QFont(s,20)); +} + +void fontFamilyChooser::addFont(){ + lbSelected->insertItem( m_currentSelectedFont ); + switch(m_fontOrigin) { + case available: lbAvailable->removeItem(lbAvailable->index(lbAvailable->findItem(m_currentSelectedFont))); + break; + case generic : lbGeneric->removeItem(lbGeneric->index(lbGeneric->findItem(m_currentSelectedFont))); + break; + } +} + +void fontFamilyChooser::setCurrentSelectedAvailableFamilyFont(const QString& f){ + m_fontOrigin = available; + m_currentSelectedFont = f; + m_selectedFontMap[f] = available; +} + +void fontFamilyChooser::setCurrentSelectedGenericFamilyFont(const QString& f){ + m_fontOrigin = generic; + m_currentSelectedFont =f; + m_selectedFontMap[f] = generic; +} + +void fontFamilyChooser::moveFontUp(){ + if(m_currentSelectedFontIndex == 0) return; + int dummyIndex = m_currentSelectedFontIndex; + lbSelected->insertItem( lbSelected->text(m_currentSelectedFontIndex ), dummyIndex -1); + lbSelected->removeItem(dummyIndex + 1); + lbSelected->setSelected( dummyIndex -1, true); +} + +void fontFamilyChooser::moveFontDown(){ + if((unsigned int)m_currentSelectedFontIndex == lbSelected->count()) return; + int dummyIndex = m_currentSelectedFontIndex; + lbSelected->insertItem( lbSelected->text(m_currentSelectedFontIndex ), dummyIndex + 2); + lbSelected->removeItem(dummyIndex); + lbSelected->setSelected(dummyIndex +1, true); +} + +void fontFamilyChooser::removeFont(){ + QString dummyFont(m_currentSelectedFont);// since removeItem emits highlighted signal, after + // removeItem call the value of m_currentSelectedFont + // is actually the font after m_currentSelectedFont and so + // we must save m_currentSelectedFont value in dummyFont + lbSelected->removeItem( m_currentSelectedFontIndex ); + switch(m_selectedFontMap[dummyFont]) { + case available: lbAvailable->insertItem(dummyFont); + lbAvailable->sort(); + break; + case generic : lbGeneric->insertItem(dummyFont); + lbGeneric->sort(); + break; + } + +} + +QStringList fontFamilyChooser::fontList(){ + QStringList list; + QListBoxItem *item = lbSelected->firstItem(); + while( item != 0 ){ + if( item->text().contains( QRegExp("\\W") ) ) list.append( "'" + item->text() + "'" ); + else list.append( item->text() ); + item = item->next(); + } + return list; +} + +void fontFamilyChooser::setInitialValue(const QString& s){ + QStringList familyList = QStringList::split(",",s); + for ( QStringList::Iterator it = familyList.begin(); it != familyList.end(); ++it ) { + (*it).remove("'"); + (*it).remove("\""); + lbSelected->insertItem((*it).stripWhiteSpace()); + } +} + +#include "fontfamilychooser.moc" diff --git a/quanta/components/csseditor/fontfamilychooser.h b/quanta/components/csseditor/fontfamilychooser.h new file mode 100644 index 00000000..c812e774 --- /dev/null +++ b/quanta/components/csseditor/fontfamilychooser.h @@ -0,0 +1,52 @@ +/*************************************************************************** + fontfamilychooser.h - description + ------------------- + begin : mer lug 23 11:20:17 CEST 2003 + copyright : (C) |YEAR| by si2003 email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 FONTFAMILYCHOOSER_H +#define FONTFAMILYCHOOSER_H + +#include "fontfamilychoosers.h" +#include +class QStringList; + +class fontFamilyChooser : public fontFamilyChooserS +{ + Q_OBJECT + private: + enum FontOrigin { available, generic }; + QString m_currentSelectedFont; + FontOrigin m_fontOrigin; + int m_currentSelectedFontIndex; + QMap m_selectedFontMap; + + private slots: + void updatePreview(const QString &); + void setCurrentSelectedAvailableFamilyFont(const QString&); + void setCurrentSelectedGenericFamilyFont(const QString&); + void setCurrentSelectedFont( int i) { m_currentSelectedFontIndex = i; } + void setCurrentSelectedFont( const QString& f ) { m_currentSelectedFont = f; } + void addFont(); + void removeFont(); + void moveFontUp(); + void moveFontDown(); + + public: + fontFamilyChooser(QWidget* parent, const char *name=0); + ~fontFamilyChooser(); + QStringList fontList(); + void setInitialValue(const QString& s); +}; + +#endif diff --git a/quanta/components/csseditor/fontfamilychoosers.ui b/quanta/components/csseditor/fontfamilychoosers.ui new file mode 100644 index 00000000..1b846446 --- /dev/null +++ b/quanta/components/csseditor/fontfamilychoosers.ui @@ -0,0 +1,441 @@ + +fontFamilyChooserS + + + fontFamilyChooserS + + + + 0 + 0 + 487 + 399 + + + + + 5 + 5 + 0 + 0 + + + + Font Family Chooser + + + true + + + + unnamed + + + + layout42 + + + + unnamed + + + + layout40 + + + + unnamed + + + + layout39 + + + + unnamed + + + + layout36 + + + + unnamed + + + + layout20 + + + + unnamed + + + + textLabel1 + + + Available system font families: + + + + + lbAvailable + + + + + + + layout15 + + + + unnamed + + + + textLabel3 + + + Generic family: + + + + + + cursive + + + + + fantasy + + + + + monospace + + + + + sans-serif + + + + + serif + + + + lbGeneric + + + + 7 + 7 + 0 + 0 + + + + + + + + + + layout38 + + + + unnamed + + + 0 + + + + spacer20 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + buttonGroup1 + + + true + + + NoFrame + + + Plain + + + 2 + + + 0 + + + + + + AlignCenter + + + false + + + false + + + -1 + + + + unnamed + + + 0 + + + 0 + + + + pbMoveUp + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + pbAdd + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + pbRemove + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + pbMoveDown + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + + + spacer21 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + layout6 + + + + unnamed + + + + textLabel2 + + + Selected font families: + + + + + lbSelected + + + + 7 + 7 + 0 + 0 + + + + + + + + + + lePreview + + + + + + + layout41 + + + + unnamed + + + + spacer1 + + + Horizontal + + + Expanding + + + + 313 + 20 + + + + + + layout9 + + + + unnamed + + + + pbOK + + + &OK + + + + + pbCancel + + + &Cancel + + + + + + + + + + + + + + + pbCancel + clicked() + fontFamilyChooserS + reject() + + + pbOK + clicked() + fontFamilyChooserS + accept() + + + + + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + + diff --git a/quanta/components/csseditor/minieditor.h b/quanta/components/csseditor/minieditor.h new file mode 100644 index 00000000..773ed285 --- /dev/null +++ b/quanta/components/csseditor/minieditor.h @@ -0,0 +1,37 @@ +/*************************************************************************** + minieditor.h - description + ------------------- + begin : lun ago 9 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 MINIEDITOR_H +#define MINIEDITOR_H + +#include + +/** + *@author gulmini luciano + */ + +class propertySetter; + +class miniEditor : public QHBox{ + public: + miniEditor(QWidget *parent=0, const char *name=0):QHBox(parent,name){} + ~miniEditor(){} + virtual void connectToPropertySetter(propertySetter* p)=0; +}; + + +#endif diff --git a/quanta/components/csseditor/percentageeditor.cpp b/quanta/components/csseditor/percentageeditor.cpp new file mode 100644 index 00000000..0c8a9d6c --- /dev/null +++ b/quanta/components/csseditor/percentageeditor.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + percentageeditor.cpp - description + ------------------- + begin : lun ago 9 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "percentageeditor.h" +#include "propertysetter.h" + +percentageEditor::percentageEditor(const QString& initialValue, QWidget *parent, const char *name) : miniEditor(parent,name) +{ + QString temp(initialValue); + m_sb = new mySpinBox(0,9999,1,this); + m_sb->setValue(temp.remove("%").toInt()); + m_sb->setSuffix("%"); + connect(m_sb, SIGNAL(valueChanged ( const QString & )), this, SIGNAL(valueChanged(const QString&))); +} + +percentageEditor::~percentageEditor() +{ + delete m_sb; +} + +void percentageEditor::connectToPropertySetter(propertySetter* p){ + connect( this, SIGNAL(valueChanged(const QString&)), p, SIGNAL(valueChanged(const QString&))); +} + +#include "percentageeditor.moc" diff --git a/quanta/components/csseditor/percentageeditor.h b/quanta/components/csseditor/percentageeditor.h new file mode 100644 index 00000000..d6931aec --- /dev/null +++ b/quanta/components/csseditor/percentageeditor.h @@ -0,0 +1,52 @@ +/*************************************************************************** + percentageeeditor.h - description + ------------------- + begin : lun ago 9 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 PERCENTAGEEDITOR_H +#define PERCENTAGEEDITOR_H + +#include +#include +#include "doubleeditors.h" +#include +#include + +#include "csseditor_globals.h" +#include "minieditor.h" + +class KPushButton; + + +/** + *@author gulmini luciano + */ + +class propertySetter; + +class percentageEditor : public miniEditor { + Q_OBJECT + private: + mySpinBox *m_sb; + public: + percentageEditor(const QString& initialValue="0",QWidget *parent=0, const char *name=0); + ~percentageEditor(); + virtual void connectToPropertySetter(propertySetter* p); + signals: + void valueChanged(const QString&); +}; + + +#endif diff --git a/quanta/components/csseditor/propertysetter.cpp b/quanta/components/csseditor/propertysetter.cpp new file mode 100644 index 00000000..683320ae --- /dev/null +++ b/quanta/components/csseditor/propertysetter.cpp @@ -0,0 +1,129 @@ +/*************************************************************************** + propertysetter.cpp - description + ------------------- + begin : gio lug 24 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "propertysetter.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include "csseditor_globals.h" +#include "minieditor.h" + +propertySetter::propertySetter(QWidget *parent, const char *name ) : QHBox(parent,name) { + m_ind = 0; + m_cb = 0L; + m_list.setAutoDelete(true); + m_pb = 0L; + setSpacing( KDialog::spacingHint() ); +} + +propertySetter::~propertySetter(){ + reset(); +} + +void propertySetter::reset(){ + if(!m_list.isEmpty()) m_list.clear(); + if(m_pb) { + delete m_pb; + m_pb=0L; + } + m_ind=0; +} + +void propertySetter::setComboBox() +{ + m_cb = new QComboBox(this); + connect(m_cb, SIGNAL(activated(const QString&)), this, SIGNAL(valueChanged(const QString&))); + connect(m_cb, SIGNAL(textChanged(const QString&)), this, SIGNAL(valueChanged(const QString&))); + m_list.append(m_cb); +} + +void propertySetter::setSpinBox(const QString& initialValue, const QString& min, const QString& max, const QString& s) +{ + mySpinBox *editor = new mySpinBox(min.toInt(), max.toInt(), 1, this); + editor->setSuffix(s); + editor->setValue(initialValue.toInt()); + connect(editor, SIGNAL(valueChanged(const QString&)), this ,SIGNAL(valueChanged(const QString&))); + m_list.append(editor); +} + +void propertySetter::setLineEdit() +{ + QLineEdit *editor = new QLineEdit(this); + connect(editor,SIGNAL(textChanged ( const QString & )), this, SIGNAL(valueChanged ( const QString & ))); + m_list.append(editor); +} + +void propertySetter::setPredefinedColorListEditor() +{ + QComboBox *editor = new QComboBox(this); + editor->insertStringList(CSSEditorGlobals::HTMLColors); + connect(editor, SIGNAL(activated(const QString&)), this, SIGNAL(valueChanged(const QString&))); + m_list.append(editor); +} + +void propertySetter::Show(){ + QWidget *w; + for ( w = m_list.first(); w; w = m_list.next() ) + w->hide(); + + m_list.at(m_ind)->show(); + + if(m_list.count() == 1) { + if(m_pb) + m_pb->hide(); + } + else + if(m_ind<(m_list.count()-1)) { + m_ind++; + m_pb->show(); + } + else + m_ind=0; +} + +void propertySetter::addButton(){ + + m_pb = new KPushButton(this); + QToolTip::add(m_pb, i18n( "More..." )); + QIconSet iconSet = SmallIconSet(QString::fromLatin1("2rightarrow")); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + m_pb->setIconSet(iconSet); + m_pb->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + m_pb->hide(); + connect(m_pb, SIGNAL(clicked()), this ,SLOT(Show())); +} + +void propertySetter::installMiniEditor(miniEditor *m){ + m->connectToPropertySetter(this); + m_list.append(m); +} + +#include "propertysetter.moc" diff --git a/quanta/components/csseditor/propertysetter.h b/quanta/components/csseditor/propertysetter.h new file mode 100644 index 00000000..3f13b8ba --- /dev/null +++ b/quanta/components/csseditor/propertysetter.h @@ -0,0 +1,64 @@ +/*************************************************************************** + propertysetter.h - description + ------------------- + begin : gio lug 24 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 PROPERTYSETTER_H +#define PROPERTYSETTER_H + +#include +#include +#include + + +class miniEditor; +class KPushButton; + + +/** + *@author gulmini luciano + */ + +class propertySetter : public QHBox { + Q_OBJECT + + private: + unsigned int m_ind; + QPtrList m_list; + QComboBox *m_cb; + KPushButton *m_pb; + + public: + propertySetter(QWidget *parent=0, const char *name=0); + ~propertySetter(); + + void installMiniEditor(miniEditor *m); + + void setComboBox(); + void setSpinBox(const QString& initialValue="0", const QString& min="0", const QString& max="9999", const QString& s=QString::null); + void setLineEdit(); + void setPredefinedColorListEditor(); + void reset(); + void addButton(); + QComboBox* ComboBox() const { return m_cb; } + + public slots: + void Show(); + + signals: + void valueChanged(const QString&); +}; + +#endif diff --git a/quanta/components/csseditor/qmyhighlighter.cpp b/quanta/components/csseditor/qmyhighlighter.cpp new file mode 100644 index 00000000..431bf6a5 --- /dev/null +++ b/quanta/components/csseditor/qmyhighlighter.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** + bashhighlighter.cpp - description + ------------------- + begin : dom mar 16 2003 + copyright : (C) 2003 by Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qmyhighlighter.h" +#include +QMyHighlighter::QMyHighlighter(QTextEdit* Qtxt):QSyntaxHighlighter(Qtxt){ +} +/*****************************************************************************/ +QMyHighlighter::~QMyHighlighter(){ +} + +/*****************************************************************************/ +int QMyHighlighter::highlightParagraph( const QString & text, int /*endStateOfLastPara*/ ) +{ + //QRegExp pattern("\\s*\\{([\\w\\s\\d:;-\"]*)\\}\\s*"); + QRegExp pattern("([#:\\.\\w]*)\\s*\\{"); + int pos=pattern.search(text,0); + int l=int(pattern.cap(1).length()); + + setFormat(pos,l,QColor("red")); + + if( pos== -1) + pos = 0; + + const int npos = pos+l; + + pattern.setPattern("\\s*([\\s\\w\\d-]*)\\s*:"); + pos=npos; + while ( pos >= 0 ) { + pos = pattern.search( text, pos ); + if ( pos > -1 ) { + l = pattern.matchedLength(); + + setFormat(pos,l,QColor("mediumvioletred")); + pos += pattern.matchedLength(); + } + } + pattern.setPattern(":\\s*([\\.\\#\\w\\s\\d-\\(\\)\",%/]*)\\s*;"); + pattern.setPattern(":\\s*([\\W\\w]*)\\s*;"); + pos=npos; + while ( pos >= 0 ) { + pos = pattern.search( text, pos ); + if ( pos > -1 ) { + l = pattern.cap(1).length(); + setFormat(pos + 2 ,l,QColor("steelblue")); + pos += pattern.matchedLength(); + } + } + return 0; +} + diff --git a/quanta/components/csseditor/qmyhighlighter.h b/quanta/components/csseditor/qmyhighlighter.h new file mode 100644 index 00000000..a75d6d00 --- /dev/null +++ b/quanta/components/csseditor/qmyhighlighter.h @@ -0,0 +1,36 @@ +/*************************************************************************** + bashhighlighter.h - description + ------------------- + begin : dom mar 16 2003 + copyright : (C) 2003 by Emiliano Gulmini + email : emi_barbarossa@yahoo.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QMYHIGHLIGHTER_H +#define QMYHIGHLIGHTER_H + +#include + +/** + *@author Emiliano Gulmini + */ + +class QMyHighlighter : public QSyntaxHighlighter { +public: + QMyHighlighter(QTextEdit* Qtxt); + + ~QMyHighlighter(); + int highlightParagraph ( const QString & text, int endStateOfLastPara ); + +}; + +#endif diff --git a/quanta/components/csseditor/shorthandformer.cpp b/quanta/components/csseditor/shorthandformer.cpp new file mode 100644 index 00000000..e8b7a837 --- /dev/null +++ b/quanta/components/csseditor/shorthandformer.cpp @@ -0,0 +1,781 @@ +/*************************************************************************** + * Copyright (C) 2003 by Gulmini Luciano * + * gulmini.luciano@student.unife.it * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "shorthandformer.h" +#include +#include "cssshpropertyparser.h" +#include +#include "csseditor_globals.h" + +QRegExp globalPercentagePattern("\\d%"), + globalLengthPattern("\\d(ex|em|px|cm|pt|pc|in|mm)"), + globalColorPattern("#[\\w\\d]*"), + globalNumberPattern("\\d*"); + +static const QString borderStyleValueString("none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset,inherit"); +static const QString widthValueString("thin,medium,thick,inherit"); +static const QString listTypeValueString("disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-alpha,lower-latin,upper-alpha,upper-latin,hebrew,armenian,georgian,cjk-ideographic,hiragana,katakana,hiragana-iroha,katakana-iroha,none,inherit"); +static const QString fontSizeValueString("smaller,larger,xx-large,x-large,large,medium,small,x-small,xx-small,inherit"); +static const QString fontWeightValueString("900,800,700,600,500,400,300,200,100,lighter,bolder,normal,bold,inherit"); +static const QString fontVariantValueString("normal,small-caps,inherit"); +static const QString fontStyleValueString("oblique,italic,normal,inherit"); +static const QString backgroundRepeatValueString("repeat,repeat-x,repeat-y,no-repeat,inherit"); + + +static const QStringList borderStyleValueList = QStringList::split(",",borderStyleValueString); +static const QStringList widthValueList = QStringList::split(",",widthValueString); +static const QStringList listTypeValueList = QStringList::split(",",listTypeValueString); +static const QStringList fontSizeValueList = QStringList::split(",",fontSizeValueString); +static const QStringList fontWeightValueList = QStringList::split(",",fontWeightValueString); +static const QStringList fontStyleValueList = QStringList::split(",",fontStyleValueString); +static const QStringList fontVariantValueList = QStringList::split(",",fontVariantValueString); +static const QStringList backgroundRepeatValueList = QStringList::split(",",backgroundRepeatValueString); + + + +ShorthandFormer::ShorthandFormer( QMap m){ + + m_properties = m; + if(m_properties.contains("cue-after")){ + cue_after= m_properties["cue-after"]; + m_properties.remove("cue-after"); + } + if(m_properties.contains("cue-before")){ + cue_before = m_properties["cue-before"]; + m_properties.remove("cue-before"); + } + if(m_properties.contains("pause-before")){ + pause_before= m_properties["pause-before"]; + m_properties.remove("pause-before"); + } + if(m_properties.contains("pause-after")){ + pause_after = m_properties["pause-after"]; + m_properties.remove("pause-after"); + } + if(m_properties.contains("background-color")){ + background_color = m_properties["background-color"]; + m_properties.remove("background-color"); + } + if(m_properties.contains("background-image")){ + background_image = m_properties["background-image"]; + m_properties.remove("background-image"); + } + if(m_properties.contains("background-repeat")){ + background_repeat = m_properties["background-repeat"]; + m_properties.remove("background-repeat"); + } + if(m_properties.contains("background-attachment")){ + background_attachment = m_properties["background-attachment"]; + m_properties.remove("background-attachment"); + } + if(m_properties.contains("background-position")){ + background_position = m_properties["background-position"]; + m_properties.remove("background-position"); + } + if(m_properties.contains("border-top-style")){ + border_top_style = m_properties["border-top-style"]; + m_properties.remove("border-top-style"); + } + if(m_properties.contains("border-top-color")){ + border_top_color = m_properties["border-top-color"]; + m_properties.remove("border-top-color"); + } + if(m_properties.contains("border-top-width")){ + border_top_width = m_properties["border-top-width"]; + m_properties.remove("border-top-width"); + } + if(m_properties.contains("border-left-style")){ + border_left_style = m_properties["border-left-style"]; + m_properties.remove("border-left-style"); + } + if(m_properties.contains("border-left-color")){ + border_left_color = m_properties["border-left-color"]; + m_properties.remove("border-left-color"); + } + if(m_properties.contains("border-left-width")){ + border_left_width = m_properties["border-left-width"]; + m_properties.remove("border-left-width"); + } + if(m_properties.contains("border-right-style")){ + border_right_style = m_properties["border-right-style"]; + m_properties.remove("border-right-style"); + } + if(m_properties.contains("border-right-color")){ + border_right_color = m_properties["border-right-color"]; + m_properties.remove("border-right-color"); + } + if(m_properties.contains("border-right-width")){ + border_right_width= m_properties["border-right-width"]; + m_properties.remove("border-right-width"); + } + if(m_properties.contains("border-bottom-style")){ + border_bottom_style = m_properties["border-bottom-style"]; + m_properties.remove("border-bottom-style"); + } + if(m_properties.contains("border-bottom-color")){ + border_bottom_color = m_properties["border-bottom-color"]; + m_properties.remove("border-bottom-color"); + } + if(m_properties.contains("border-bottom-width")){ + border_bottom_width = m_properties["border-bottom-width"]; + m_properties.remove("border-bottom-width"); + } + if(m_properties.contains("outline-style")){ + outline_style = m_properties["outline-style"]; + m_properties.remove("outline-style"); + } + if(m_properties.contains("outline-color")){ + outline_color = m_properties["outline-color"]; + m_properties.remove("outline-color"); + } + if(m_properties.contains("outline-width")){ + outline_width = m_properties["outline-width"]; + m_properties.remove("outline-width"); + } + if(m_properties.contains("list-style-type")){ + list_style_type= m_properties["list-style-type"]; + m_properties.remove("list-style-type"); + } + if(m_properties.contains("list-style-image")){ + list_style_image = m_properties["list-style-image"]; + m_properties.remove("list-style-image"); + } + if(m_properties.contains("list-style-position")){ + list_style_position = m_properties["list-style-position"]; + m_properties.remove("list-style-position"); + } + if(m_properties.contains("font-style")){ + font_style = m_properties["font-style"]; + m_properties.remove("font-style"); + } + if(m_properties.contains("font-variant")){ + font_variant = m_properties["font-variant"]; + m_properties.remove("font-variant"); + } + if(m_properties.contains("font-weight")){ + font_weight = m_properties["font-weight"]; + m_properties.remove("font-weight"); + } + if(m_properties.contains("font-size")){ + font_size = m_properties["font-size"]; + m_properties.remove("font-size"); + } + if(m_properties.contains("line-height")){ + line_height= m_properties["line-height"]; + m_properties.remove("line-height"); + } + if(m_properties.contains("font-family")){ + font_family = m_properties["font-family"]; + m_properties.remove("font-family"); + } + if(m_properties.contains("margin-top")){ + margin_top = m_properties["margin-top"]; + m_properties.remove("margin-top"); + } + if(m_properties.contains("margin-bottom")){ + margin_bottom = m_properties["margin-bottom"]; + m_properties.remove("margin-bottom"); + } + if(m_properties.contains("margin-left")){ + margin_left = m_properties["margin-left"]; + m_properties.remove("margin-left"); + } + if(m_properties.contains("margin-right")){ + margin_right = m_properties["margin-right"]; + m_properties.remove("margin-right"); + } + if(m_properties.contains("padding-top")){ + padding_top = m_properties["padding-top"]; + m_properties.remove("padding-top"); + } + if(m_properties.contains("padding-bottom")){ + padding_bottom = m_properties["padding-bottom"]; + m_properties.remove("padding-bottom"); + } + if(m_properties.contains("padding-left")){ + padding_left = m_properties["padding-left"]; + m_properties.remove("padding-left"); + } + if(m_properties.contains("padding-right")){ + padding_right = m_properties["padding-right"]; + m_properties.remove("padding-right"); + } +} + +QString ShorthandFormer::compress(){ + QString props; + + props += compressCueProp(); + props += compressPauseProp(); + props += compressBackgroundProp(); + props += compressFontProp(); + props += compressPaddingProp(); + props += compressMarginProp(); + props += compressOutlineProp(); + props += compressListStyleProp(); + props += compressBorderProp(); + + QMap::Iterator it; + for ( it = m_properties.begin(); it != m_properties.end(); ++it ) + props += it.key() + " : " + it.data().stripWhiteSpace() + "; " ; + + props.truncate(props.length()-1);//the last white space creates some problem: better remove it + //props.chop(1); + return props; +} + +QString ShorthandFormer::compressBorderProp(){ + QString props; + + bool allColorSidesSet = false, + allStyleSidesSet = false, + allWidthSidesSet = false; + + if(!border_left_color.isEmpty()) + if( ( border_left_color == border_top_color ) && ( border_top_color == border_right_color ) && ( border_right_color == border_bottom_color ) ) + allColorSidesSet = true; + + if(!border_left_style.isEmpty()) + if( ( border_left_style == border_top_style ) && ( border_top_style == border_right_style ) && ( border_right_style == border_bottom_style ) ) + allStyleSidesSet = true; + + if(!border_left_width.isEmpty()) + if( ( border_left_width == border_top_width ) && ( border_top_width == border_right_width ) && ( border_right_width == border_bottom_width ) ) + allWidthSidesSet = true; + + if ( allColorSidesSet ) { + if ( allStyleSidesSet ) { + if ( allWidthSidesSet ) { + props += "border : " + border_left_color + " " + border_left_style + " " + border_left_width +"; "; + + } + else { + props += "border : " + border_left_color + " " + border_left_style +"; "; + props += compressBorderWidthProp(); + } + } + else { + if ( allWidthSidesSet ) { + props += "border : " + border_left_color + " " + border_left_width +"; "; + props += compressBorderStyleProp(); + } + else { + props += "border : " + border_left_color +"; "; + props += compressBorderWidthProp(); + props += compressBorderStyleProp(); + } + + } + } + else { // allColorSidesSet is false + if ( allStyleSidesSet ) { + if ( allWidthSidesSet ) { + props += "border : " + border_left_style + " " + border_left_width +"; "; + props += compressBorderColorProp(); + } + else { + props += compressBorderStyleProp(); + props += compressBorderWidthProp(); + props += compressBorderColorProp(); + } + } + else { + + props += compressBorderStyleProp(); + props += compressBorderWidthProp(); + props += compressBorderColorProp(); + } + } + + return props; +} + +QString ShorthandFormer::compressBorderStyleProp(){ + return compressImplementation( "border-style" ,border_top_style, border_bottom_style, border_right_style, border_left_style, "none"); +} + +QString ShorthandFormer::compressBorderWidthProp(){ + return compressImplementation( "border-width" ,border_top_width, border_bottom_width, border_right_width, border_left_width, "medium"); +} + +QString ShorthandFormer::compressBorderColorProp(){ +//because the default value of color property is browser dependant, this method doesn't compress the color value + QString props; + if( !border_top_color.isEmpty() ) + props += "border-top-color : " + border_top_color +"; "; + if( !border_right_color.isEmpty() ) + props += "border-right-color : " + border_right_color +"; "; + if( !border_bottom_color.isEmpty() ) + props += "border-bottom-color : " + border_bottom_color +"; "; + if( !border_left_color.isEmpty() ) + props += "border-left-color : " + border_left_color +"; "; + return props; +} + +QString ShorthandFormer::compressFontProp(){ + QString fontProp, + props; + //bool appendLineHeight = false; + + if( font_style.isEmpty() && font_variant.isEmpty() && font_weight.isEmpty() && font_size.isEmpty() && font_family.isEmpty() ) { + if( !line_height.isEmpty() ) + props += "line-height : " + line_height + "; "; + } + else { + if( !font_style.isEmpty() ) + fontProp += " " + font_style; + if( !font_variant.isEmpty() ) + fontProp += " " + font_variant; + if( !font_weight.isEmpty() ) + fontProp += " " + font_weight; + if( !font_size.isEmpty() ){ + fontProp += " " + font_size; + if( !line_height.isEmpty() ) + fontProp += "/" + line_height.stripWhiteSpace() ; + } + else { + fontProp += ( " medium"); + /*if( !line_height.isEmpty() ) + appendLineHeight = true; */ + if( !line_height.isEmpty() ) + fontProp += ( "/" + line_height.stripWhiteSpace() ); + } + + if( !font_family.isEmpty() ) + fontProp += ( " " + font_family); + else fontProp += " serif"; + if( !fontProp.isEmpty() ) + props += ( "font :" + fontProp + "; "); + /* if(appendLineHeight) + props += ( "line-height : " + line_height + "; ");*/ + } + return props; +} + +QString ShorthandFormer::compressCueProp(){ + return compressImplementation2( "cue", cue_after, cue_before, "none"); +} + +QString ShorthandFormer::compressPauseProp(){ + return compressImplementation2( "pause", pause_after, pause_before, "0"); +} + +QString ShorthandFormer::compressBackgroundProp(){ + QString backgroundProp; + if( !background_color.isEmpty() ) backgroundProp += (" " + background_color ); + if( !background_image.isEmpty() ) backgroundProp += (" " + background_image ); + if( !background_repeat.isEmpty() ) backgroundProp += (" " + background_repeat ); + if( !background_attachment.isEmpty() ) backgroundProp += (" " + background_attachment ); + if( !background_position.isEmpty() ) backgroundProp += (" " + background_position ); + if( !backgroundProp.isEmpty() ) return ( "background :" + backgroundProp + "; "); + return QString::null; +} + +QString ShorthandFormer::compressPaddingProp(){ + return compressImplementation( "padding" ,padding_top, padding_bottom, padding_right, padding_left, "0"); +} + +QString ShorthandFormer::compressMarginProp(){ + return compressImplementation( "margin" ,margin_top, margin_bottom, margin_right, margin_left, "0"); +} + +QString ShorthandFormer::compressOutlineProp(){ + return compressImplementation3("outline", outline_color, outline_style, outline_width); +} +QString ShorthandFormer::compressListStyleProp(){ + return compressImplementation3("list-style", list_style_type, list_style_image, list_style_position); +} + +QString ShorthandFormer::compressImplementation3( const QString& prop, const QString& p1, const QString& p2, const QString& p3){ + QString props; + if( !p1.isEmpty() ) props += (" " + p1 ); + if( !p2.isEmpty() ) props += (" " + p2 ); + if( !p3.isEmpty() ) props += (" " + p3 ); + if( !props.isEmpty() ) return ( prop + " :" + props + "; "); + return QString::null; +} + +QString ShorthandFormer::compressImplementation2( const QString& prop, const QString& after, const QString& before, const QString& defValue){ + QString props; + if(after == before){ + if(!after.isEmpty()) props+=( prop + " : " + after + "; "); + } + else { + if(before.isEmpty()) props+=( prop + " : " + defValue + " " + after + "; "); + else + if(after.isEmpty()) props+=( prop + " : " + before + " " + defValue + "; "); + else props+=( prop + " : " + before + " " + after + "; "); + } + return props; +} + +QString ShorthandFormer::compressImplementation( const QString& prop, const QString& t, const QString& b, const QString& r, const QString& l, const QString& defValue){ + + QString props, + top(t.stripWhiteSpace()), + bottom(b.stripWhiteSpace()), + left(l.stripWhiteSpace()), + right(r.stripWhiteSpace()); + + if( top.isEmpty() ) top = defValue; + if( bottom.isEmpty() ) bottom = defValue; + if( left.isEmpty() ) left = defValue; + if( right.isEmpty() ) right = defValue; + + + if( top == defValue && bottom == defValue && right == defValue && left == defValue) + return QString::null; + + if( top == bottom && bottom == right && right == left ) + return ( prop +" : " + top + "; "); + + if( right == left ) { + if( top == bottom ) return ( prop +" : " + top + " " + right + "; "); + else return ( prop +" : " + top + " " + right + " " + bottom + "; "); + } + else return (prop +" : " + top + " " + right + " " + bottom + " " + left + "; "); +} + + +//+++++++++++++++++++++EXPANDING METHODS+++++++++++++++++++++++++++++++++++ + + +QMap ShorthandFormer::expand( const QString& propertyName, const QString& propertyValue ){ + CSSSHPropertyParser parser(propertyValue); + QStringList foundValues = parser.parse(); + + if( propertyName == "cue" ) return expandCueProp(foundValues); + if( propertyName == "pause") return expandPauseProp(foundValues); + if( propertyName == "background") return expandBackgroundProp(foundValues); + if( propertyName == "border-color") return expandBox("color", foundValues); + if( propertyName == "border-style") return expandBox("style", foundValues); + if( propertyName == "border-width") return expandBox("width", foundValues); + if( propertyName == "font") return expandFontProp(foundValues); + if( propertyName == "outline") return expandOutlineProp(foundValues); + if( propertyName == "list-style") return expandListstyleProp(foundValues); + if( propertyName == "border-bottom") return expandBoxSide("bottom",foundValues); + if( propertyName == "border-top") return expandBoxSide("top",foundValues); + if( propertyName == "border-left") return expandBoxSide("left",foundValues); + if( propertyName == "border-right") return expandBoxSide("right",foundValues); + if( propertyName == "border") return expandBorderProp(foundValues); + if( propertyName == "padding") return expandPaddingProp(foundValues); + if( propertyName == "margin") return expandMarginProp(foundValues); + return QMap();//dummy instruction avoiding a pedantic warning; can never be reached +} + +QMap ShorthandFormer::expandCueProp(const QStringList& l){ + return expandImplementation("cue",l); +} + +QMap ShorthandFormer::expandPauseProp(const QStringList& l){ + return expandImplementation("pause",l); +} + +QMap ShorthandFormer::expandImplementation(const QString& propertyName, const QStringList& l){ + QMap expandedProps; + if( l.count()==1) { + expandedProps[propertyName + "-before"] = l[0] ; + expandedProps[propertyName + "-after"] = l[0] ; + return expandedProps; + } + else + { + expandedProps[propertyName + "-before"] = l[0] ; + expandedProps[propertyName + "-after"] = l[1] ; + return expandedProps; + } +} + +QMap ShorthandFormer::expandBackgroundProp(const QStringList& l){ + QMap expandedProps; + if(l.count()==1 && l[0] == "inherit"){ // it works also as protection against wrong single value inserted + expandedProps["background-color"] = l[0]; + expandedProps["background-image"] = l[0]; + expandedProps["background-repeat"] = l[0]; + expandedProps["background-attachment"] =l[0]; + expandedProps["background-position"] = l[0]; + } + else { + + QStringList::ConstIterator it = l.begin(); + + while ( it != l.end() ) { + QString temp((*it).stripWhiteSpace()); + if( (*it).contains("url(") || temp == "none" || temp == "inherit" ){ + expandedProps["background-image"] = (*it); + } + else + if( backgroundRepeatValueList.contains(temp)!=0 ) { + expandedProps["background-repeat"] = (*it); + } + else + if( temp == "scroll" || temp == "fixed" || temp == "inherit"){ + expandedProps["background-attachment"] = (*it); + } + else + if( (*it).contains("rgb(") || (*it).contains(globalColorPattern) || CSSEditorGlobals::HTMLColors.contains((*it))!=0 || temp == "transparent" || temp == "inherit" ){ + expandedProps["background-color"] = (*it); + } + else + if( temp == "top" || temp == "center" || temp == "bottom" || temp == "left" || temp == "right" || (*it).contains(globalPercentagePattern) || (*it).contains(globalLengthPattern) || temp == "inherit"){ + if( expandedProps.contains("background-position") ) + expandedProps["background-position"] = ( expandedProps["background-position"] + " " + (*it) ); + else + expandedProps["background-position"] = (*it); + } + + ++it; + } + } + return expandedProps; +} + +QMap ShorthandFormer::expandBox(const QString& subPropName, const QStringList& l){ + + QMap expandedProps; + expandedProps["border-top-" + subPropName] = l[0]; + switch(l.count()){ + case 1 : + expandedProps["border-right-" + subPropName] = l[0]; + expandedProps["border-bottom-" + subPropName] = l[0]; + expandedProps["border-left-" + subPropName] = l[0]; + break; + case 2 : + expandedProps["border-right-" + subPropName] = l[1]; + expandedProps["border-bottom-" + subPropName] = l[0]; + expandedProps["border-left-" + subPropName] = l[1]; + break; + case 3 : + expandedProps["border-right-" + subPropName] = l[1]; + expandedProps["border-bottom-" + subPropName] = l[2]; + expandedProps["border-left-" + subPropName] = l[1]; + break; + case 4 : + expandedProps["border-right-" + subPropName] = l[1]; + expandedProps["border-bottom-" + subPropName] = l[2]; + expandedProps["border-left-" + subPropName] = l[3]; + break; + default:break; + } + return expandedProps; +} + +QMap ShorthandFormer::expandFontProp(const QStringList& l){ + QMap expandedProps; + + QRegExp percentagePattern("/"+globalPercentagePattern.pattern()), + lengthPattern("/"+globalLengthPattern.pattern()), + numberPattern("/"+globalNumberPattern.pattern()); + + QStringList fontPseudoSHFormValues; + fontPseudoSHFormValues.append("caption"); + fontPseudoSHFormValues.append("icon"); + fontPseudoSHFormValues.append("menu"); + fontPseudoSHFormValues.append("message-box"); + fontPseudoSHFormValues.append("small-caption"); + fontPseudoSHFormValues.append("status-bar"); + if( l.count()==1 && fontPseudoSHFormValues.contains(l[0]) != 0) { + expandedProps["font"] = l[0]; + return expandedProps; + } + else { + QStringList::ConstIterator it = l.begin(); + while ( it != l.end() ) { + QString currentIt = (*it); + QString temp(currentIt.stripWhiteSpace()); + if( fontStyleValueList.contains(temp)!=0 ) expandedProps["font-style"] = (*it); + else + if( fontVariantValueList.contains(temp)!=0 ) expandedProps["font-variant"] = currentIt ; + else + if( fontWeightValueList.contains(temp)!=0) expandedProps["font-weight"] = currentIt; + else + if( (fontSizeValueList.contains(temp)!=0 || currentIt.contains(globalPercentagePattern)!=0 || currentIt.contains(globalLengthPattern)!=0) && expandedProps["font-size"].isEmpty() ) + { + expandedProps["font-size"] = currentIt; + } + else + if( currentIt.contains(percentagePattern)!=0 || currentIt.contains(numberPattern)!=0 || currentIt.contains(lengthPattern)!=0 || temp == "/normal" || temp == "/inherit" ) + { + expandedProps["line-height"] = (currentIt.remove('/')); + } + else expandedProps["font-family"] = currentIt; + ++it; + } + return expandedProps; + } +} + +QMap ShorthandFormer::expandListstyleProp( const QStringList& l){ + QMap expandedProps; + if( (l.count() == 1) && (l[0] == "inherit")){ + expandedProps["list-style-image"] ="inherit"; + expandedProps["list-style-type"] ="inherit"; + expandedProps["list-style-position"] ="inherit"; + return expandedProps; + } + + if( (l.count() == 1) && (l[0] == "none")){ + expandedProps["list-style-image"] ="none"; + expandedProps["list-style-type"] ="none"; + return expandedProps; + } + + + QStringList::ConstIterator it = l.begin(); + while ( it != l.end() ) { + QString temp((*it).stripWhiteSpace()); + if( listTypeValueList.contains(temp)!=0) { + expandedProps["list-style-type"] = (*it) ; + } + else + if( temp == "inside" || temp == "outside" || temp == "inherit") { + expandedProps["list-style-position"] = (*it); + } + else + if( (*it).contains("url(") || temp == "none" || temp == "inherit" ) + expandedProps["list-style-image"] = (*it); + + ++it; + } + return expandedProps; +} + +QMap ShorthandFormer::expandOutlineProp( const QStringList& l){ + QMap expandedProps; + QStringList::ConstIterator it = l.begin(); + while ( it != l.end() ) { + QString temp((*it).stripWhiteSpace()); + if( borderStyleValueList.contains(temp)!=0 ) expandedProps["outline-style"] = (*it); + else + if( (*it).contains(globalColorPattern) || CSSEditorGlobals::HTMLColors.contains((*it))!=0 || temp == "invert" || temp == "inherit") + expandedProps["outline-color"] = (*it) ; + else + if( (*it).contains(globalLengthPattern) || widthValueList.contains(temp)!=0) + expandedProps["outline-width"] = (*it); + ++it; + } + return expandedProps; +} + +QMap ShorthandFormer::expandBoxSide(const QString& subPropName, const QStringList& l){ + QMap expandedProps; + + QStringList::ConstIterator it = l.begin(); + while ( it != l.end() ) { + QString temp((*it).stripWhiteSpace()); + if( borderStyleValueList.contains(temp)!=0 ) expandedProps[subPropName + "-style"] = (*it); + else + if( (*it).contains(globalColorPattern) || CSSEditorGlobals::HTMLColors.contains((*it))!=0 || temp == "transparent" || temp == "inherit") + expandedProps[subPropName + "-color"] = (*it) ; + else + if( (*it).contains(globalLengthPattern) || widthValueList.contains(temp)!=0) + expandedProps[subPropName + "-width"] = (*it); + ++it; + } + return expandedProps; +} + +QMap ShorthandFormer::expandBorderProp(const QStringList& l){ + QMap expandedProps; + QStringList::ConstIterator it = l.begin(); + while ( it != l.end() ) { + QString temp((*it).stripWhiteSpace()); + if( borderStyleValueList.contains(temp)!=0 ){ + expandedProps["border-top-style"] = (*it); + expandedProps["border-left-style"] = (*it); + expandedProps["border-right-style"] = (*it); + expandedProps["border-bottom-style"] = (*it); + } + else + if( (*it).contains(globalColorPattern) || CSSEditorGlobals::HTMLColors.contains((*it))!=0 || temp == "transparent" || temp == "inherit"){ + expandedProps["border-top-color"] = (*it); + expandedProps["border-left-color"] = (*it); + expandedProps["border-right-color"] = (*it); + expandedProps["border-bottom-color"] = (*it); + } + else + if( (*it).contains(globalLengthPattern) || widthValueList.contains(temp)!=0){ + expandedProps["border-top-width"] = (*it); + expandedProps["border-left-width"] = (*it); + expandedProps["border-right-width"] = (*it); + expandedProps["border-bottom-width"] = (*it); + } + ++it; + } + return expandedProps; +} + +QMap ShorthandFormer::expandImplementation2(const QString& propertyName, const QStringList& l){ + QMap expandedProps; + expandedProps[ propertyName + "-top" ] = l[0]; + switch(l.count()){ + case 1 : + expandedProps[ propertyName + "-right" ] = l[0]; + expandedProps[ propertyName + "-bottom" ] = l[0]; + expandedProps[ propertyName + "-left" ] = l[0]; + break; + case 2 : + expandedProps[ propertyName + "-right" ] = l[1]; + expandedProps[ propertyName + "-bottom" ] = l[0]; + expandedProps[ propertyName + "-left" ] = l[1]; + break; + case 3 : + expandedProps[ propertyName + "-right" ] = l[1]; + expandedProps[ propertyName + "-bottom" ] = l[2]; + expandedProps[ propertyName + "-left" ] = l[1]; + break; + case 4 : + expandedProps[ propertyName + "-right" ] = l[1]; + expandedProps[ propertyName + "-bottom" ] = l[2]; + expandedProps[ propertyName + "-left" ] = l[3]; + break; + default:break; + } + return expandedProps; + } + + QMap ShorthandFormer::expandPaddingProp(const QStringList& l){ + return expandImplementation2("padding", l); +} + + QMap ShorthandFormer::expandMarginProp(const QStringList& l){ + return expandImplementation2("margin", l); + } + +QStringList ShorthandFormer::SHFormList() { + QStringList l; + l.append("cue"); + l.append("pause"); + l.append("font"); + l.append("background"); + l.append("border"); + l.append("border-top"); + l.append("border-bottom"); + l.append("border-left"); + l.append("border-right"); + l.append("border-color"); + l.append("border-style"); + l.append("border-width"); + l.append("outline"); + l.append("list-style"); + l.append("padding"); + l.append("margin"); + return l; +} + diff --git a/quanta/components/csseditor/shorthandformer.h b/quanta/components/csseditor/shorthandformer.h new file mode 100644 index 00000000..f5b0f291 --- /dev/null +++ b/quanta/components/csseditor/shorthandformer.h @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 2003 by Gulmini Luciano * + * gulmini.luciano@student.unife.it * + * * + * 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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef SHORTHANDFORMER_H +#define SHORTHANDFORMER_H + +/** +@author Gulmini Luciano +*/ +#include +class QString; +class QStringList; + +class ShorthandFormer{ +public: + ShorthandFormer(){} + ShorthandFormer( QMap m ); + ~ShorthandFormer(){} + QString compress(); + QMap expand(const QString& propertyName, const QString& propertyValue); + static QStringList SHFormList(); + +private: + QMap m_properties; + QString cue_after, + cue_before, + pause_before, + pause_after, + background_color, + background_image, + background_repeat, + background_attachment, + background_position, + border_top_style, + border_top_color, + border_top_width, + border_left_style, + border_left_color, + border_left_width, + border_right_style, + border_right_color, + border_right_width, + border_bottom_style, + border_bottom_color, + border_bottom_width, + outline_style, + outline_color, + outline_width, + list_style_type, + list_style_image, + list_style_position, + font_style, + font_variant, + font_weight, + font_size, + line_height, + font_family, + margin_top, + margin_bottom, + margin_left, + margin_right, + padding_top, + padding_bottom, + padding_left, + padding_right; + +private: + QString compressCueProp(); + QString compressPauseProp(); + QString compressPaddingProp(); + QString compressMarginProp(); + QString compressFontProp(); + QString compressBackgroundProp(); + QString compressOutlineProp(); + QString compressListStyleProp(); + QString compressBorderStyleProp(); + QString compressBorderWidthProp(); + QString compressBorderColorProp(); + QString compressBorderProp(); + + QString compressImplementation( const QString& prop, const QString& t, const QString& b, const QString& r, const QString& l, const QString& defValue); + QString compressImplementation2( const QString& prop, const QString& after, const QString& before, const QString& defValue); + QString compressImplementation3( const QString& prop, const QString& p1, const QString& p2, const QString& p3); + + QMap expandCueProp(const QStringList& l); + QMap expandPauseProp(const QStringList& l); + QMap expandBackgroundProp(const QStringList& l); + QMap expandFontProp(const QStringList& l); + QMap expandOutlineProp(const QStringList& l); + QMap expandListstyleProp(const QStringList& l); + QMap expandBoxSide(const QString& subPropName, const QStringList& l); + QMap expandBorderProp(const QStringList& l); + QMap expandBox(const QString& subPropName, const QStringList& l); + QMap expandPaddingProp(const QStringList& l); + QMap expandMarginProp(const QStringList& l); + + QMap expandImplementation(const QString& propertyName, const QStringList& l); + QMap expandImplementation2(const QString& propertyName, const QStringList& l); + }; + +#endif diff --git a/quanta/components/csseditor/specialsb.cpp b/quanta/components/csseditor/specialsb.cpp new file mode 100644 index 00000000..eb26e05f --- /dev/null +++ b/quanta/components/csseditor/specialsb.cpp @@ -0,0 +1,127 @@ +/*************************************************************************** + specialsb.cpp - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "specialsb.h" +#include "propertysetter.h" +#include "csseditor_globals.h" + +#include + +specialSB::specialSB(QWidget *parent, const char *name, bool useLineEdit ) : miniEditor(parent,name) { + if (useLineEdit) + { + m_lineEdit = new KLineEdit(this); + m_sb = 0L; + connect(m_lineEdit, SIGNAL(textChanged ( const QString & )), this, SLOT(lineEditValueSlot ( const QString & ))); + } + else + { + m_sb=new mySpinBox(this); + connect(m_sb, SIGNAL(valueChanged ( const QString & )), this, SLOT(sbValueSlot(const QString&))); + m_lineEdit = 0L; + } + m_cb = new QComboBox(this); + connect(m_cb, SIGNAL(activated ( const QString & )), this, SLOT(cbValueSlot(const QString&))); +} + +specialSB::~specialSB(){ + delete m_cb; + delete m_sb; + delete m_lineEdit; +} + +void specialSB::connectToPropertySetter(propertySetter* p){ + connect(this, SIGNAL(valueChanged(const QString&)), p,SIGNAL(valueChanged(const QString&))); +} + + +void specialSB::cbValueSlot(const QString& s){ + if (m_sb) + emit valueChanged( m_sb->text() +s ); + else + emit valueChanged( m_lineEdit->text() +s ); +} + +void specialSB::sbValueSlot(const QString& s){ + emit valueChanged( s + m_cb->currentText()); +} + +void specialSB::lineEditValueSlot(const QString& s){ + emit valueChanged( s + m_cb->currentText()); +} + +void specialSB::setInitialValue(const QString& s){ + + QRegExp pattern("\\d("+ cbValueList().join("|")+")"); + + if (pattern.search(s) != -1) { + QString temp(s.stripWhiteSpace()); + QString cbValue = pattern.cap(1); + + if (m_sb) + m_sb->setValue(temp.remove(cbValue).toInt()); + else + m_lineEdit->setText(temp.remove(cbValue)); + m_cb->setCurrentText(cbValue); + } + else return; +} + +QStringList specialSB::cbValueList(){ + QStringList l; + for(int i=0; icount();i++) l.append(m_cb->text(i)); + return l; +} + +frequencyEditor::frequencyEditor(QWidget *parent, const char *name ) : specialSB(parent,name) { + m_cb->insertItem("Hz"); + m_cb->insertItem("kHz"); + m_sb->setMaxValue(9999); +} + +angleEditor::angleEditor(QWidget *parent, const char *name) : specialSB(parent,name){ + m_cb->insertItem("deg"); + m_cb->insertItem("grad"); + m_cb->insertItem("rad"); + m_sb->setMaxValue(-400); + m_sb->setMaxValue(400); +} + +timeEditor::timeEditor(QWidget *parent, const char *name ) : specialSB(parent,name) { + m_cb->insertItem("ms"); + m_cb->insertItem("s"); + m_sb->setMaxValue(99999); +} + +lengthEditor::lengthEditor(QWidget *parent, const char *name ) : specialSB(parent,name, true) { + m_cb->insertItem("px"); + m_cb->insertItem("em"); + m_cb->insertItem("ex"); + m_cb->insertItem("in"); + m_cb->insertItem("cm"); + m_cb->insertItem("mm"); + m_cb->insertItem("pt"); + m_cb->insertItem("pc"); + if (m_sb) + m_sb->setMaxValue(99999); +} + + + + + +#include "specialsb.moc" diff --git a/quanta/components/csseditor/specialsb.h b/quanta/components/csseditor/specialsb.h new file mode 100644 index 00000000..43d6273e --- /dev/null +++ b/quanta/components/csseditor/specialsb.h @@ -0,0 +1,79 @@ +/*************************************************************************** + specialsb.h - description + ------------------- + begin : dom ago 3 2003 + copyright : (C) 2003 by Gulmini Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SPECIALSB_H +#define SPECIALSB_H + +#include "minieditor.h" +#include +class mySpinBox; +class KLineEdit; + +/** + *@author gulmini luciano + */ + +class specialSB : public miniEditor { + Q_OBJECT + protected: + QComboBox *m_cb; + mySpinBox *m_sb; + KLineEdit *m_lineEdit; + + public: + specialSB(QWidget *parent=0, const char *name=0, bool useLineEdit = false); + ~specialSB(); + void insertItem(const QString& s){ m_cb->insertItem(s); } + void setInitialValue(const QString& s); + QStringList cbValueList(); + virtual void connectToPropertySetter(propertySetter* p); + + public slots: + void cbValueSlot(const QString&); + void sbValueSlot(const QString&); + void lineEditValueSlot(const QString&); + + signals: + void valueChanged(const QString&); + +}; + +class angleEditor : public specialSB { + Q_OBJECT + public: + angleEditor(QWidget *parent=0, const char *name=0); +}; + +class frequencyEditor : public specialSB { + Q_OBJECT + public: + frequencyEditor(QWidget *parent=0, const char *name=0); +}; + +class timeEditor : public specialSB { + Q_OBJECT + public: + timeEditor(QWidget *parent=0, const char *name=0); +}; + +class lengthEditor : public specialSB { + Q_OBJECT + public: + lengthEditor(QWidget *parent=0, const char *name=0); +}; + +#endif diff --git a/quanta/components/csseditor/styleeditor.cpp b/quanta/components/csseditor/styleeditor.cpp new file mode 100644 index 00000000..63d4af79 --- /dev/null +++ b/quanta/components/csseditor/styleeditor.cpp @@ -0,0 +1,109 @@ +/*************************************************************************** + styleeditor - implementation + begin : Wed Apr 7 2004 + copyright : (C) 2004 by Luciano Gulmini + ***************************************************************************/ + +/*************************************************************************** + * + * 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; version 2 of the License. + * + ***************************************************************************/ + +//qt includes +#include +#include +#include +#include +#include + +//kde includes +#include +#include +#include +#include +#include +#include +#include + +//app includes +#include "parser.h" +#include "tag.h" +#include "node.h" +#include "project.h" +#include "resource.h" +#include "document.h" +#include "styleeditor.h" +#include "viewmanager.h" +#include "csseditor.h" + +StyleEditor::StyleEditor(QWidget *parent, const char* name) : TLPEditor(parent,name){ + connect(m_pb, SIGNAL(clicked()), this, SLOT(openCSSEditor())); + setToolTip(i18n("Open css dialog")); + QIconSet iconSet = SmallIconSet(QString::fromLatin1("stylesheet")); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + m_pb->setIconSet(iconSet); + m_iconWidth = pixMap.width(); + m_iconHeight = pixMap.height(); + m_pb->setFixedSize( m_iconWidth+8, m_iconHeight+8 ); + m_label->hide(); +} + +void StyleEditor::setButtonIcon(int width, int height){ + m_pb->setFixedSize( m_iconWidth+width, m_iconHeight+height ); +} + +void StyleEditor::openCSSEditor(){ + Document *w = ViewManager::ref()->activeDocument(); + if (!w) return; + uint line, col; + int bLine, bCol, eLine, eCol; + bLine = bCol = eLine = eCol = 0; + w->viewCursorIf->cursorPositionReal(&line, &col); + if (line == 0 && col == 0) + col++; + //parser->rebuild(w); + Node *node = parser->nodeAt(line, col, false); + unsigned int lastLine = w->editIf->numLines() - 1; + unsigned int lastCol = w->editIf->lineLength(lastLine); + Node *styleNode = node; + + if (styleNode->tag->type == Tag::XmlTagEnd && styleNode->prev) + styleNode = styleNode->prev; + + QString fullDocument = w->editIf->text().stripWhiteSpace(); + + if (styleNode && (styleNode->tag->type == Tag::XmlTag || styleNode->tag->type == Tag::Empty) ) { + CSSEditor *dlg = new CSSEditor(this); + QFileInfo fi(ViewManager::ref()->currentURL()); + dlg->setFileToPreview(Project::ref()->projectBaseURL().path() + fi.baseName(),false); + + styleNode->tag->beginPos(bLine, bCol); + styleNode->tag->endPos(eLine, eCol); + dlg->setFooter(">" + w->text(eLine, eCol + 1, lastLine, lastCol)); + + QString temp; + if (styleNode->tag->hasAttribute("style")) { + dlg->setInlineStyleContent(styleNode->tag->attributeValue("style")); + Tag tempTag(*(styleNode->tag)); + tempTag.deleteAttribute("style"); + temp = tempTag.toString(); + } + else { + dlg->setInlineStyleContent(QString::null); + temp = styleNode->tag->toString(); + } + + temp = temp.left(temp.length()-1);//remove > + temp = temp.right(temp.length()-1);//remove < + dlg->setHeader(w->text(0, 0, bLine, bCol) + temp); + + dlg->initialize(); + if( dlg->exec() ) m_le->setText(dlg->generateProperties()); + delete dlg; + } +} + +#include "styleeditor.moc" diff --git a/quanta/components/csseditor/styleeditor.h b/quanta/components/csseditor/styleeditor.h new file mode 100644 index 00000000..582ac848 --- /dev/null +++ b/quanta/components/csseditor/styleeditor.h @@ -0,0 +1,42 @@ +/*************************************************************************** + styleeditor - description + begin : Wed Apr 7 2004 + copyright : (C) 2004 by Luciano Gulmini + ***************************************************************************/ + +/*************************************************************************** + * + * 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; version 2 of the License. + * + ***************************************************************************/ + +#ifndef STYLEEDITOR_H +#define STYLEEDITOR_H + +//qt includes +#include "tlpeditors.h" +//kde includes + +//app includes + +//forward declarations +class propertySetter; +class StyleEditor : public TLPEditor{ + Q_OBJECT + private: + int m_iconWidth, + m_iconHeight; +public: + StyleEditor(QWidget *parent=0, const char* name=0); + virtual void setButtonIcon(int width, int height); + +public slots: + void openCSSEditor(); + virtual void connectToPropertySetter(propertySetter* /*p*/){} + virtual void setInitialValue(const QString& /*s*/){} +}; + + +#endif //STYLEEDITOR_H diff --git a/quanta/components/csseditor/stylesheetparser.cpp b/quanta/components/csseditor/stylesheetparser.cpp new file mode 100644 index 00000000..b8cbf306 --- /dev/null +++ b/quanta/components/csseditor/stylesheetparser.cpp @@ -0,0 +1,245 @@ +/*************************************************************************** + stylesheetparser.cpp - description + ------------------- + begin : gio ago 19 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "stylesheetparser.h" +#include +#include + +static const QString msg1(i18n("has not been closed")), + msg2(i18n("needs an opening parenthesis ")); + +stylesheetParser::stylesheetParser(const QString& s){ + m_styleSheet = s; + m_styleSheet=m_styleSheet.right(m_styleSheet.length()-whiteSpaces(0)); + m_stopProcessing = false; + m_orderNumber = 0; +} + +int stylesheetParser::whiteSpaces(int d){ + int ws=0; + for( unsigned int i=d;i tmp(m_styleSheet.left(k+ws),++m_orderNumber); + m_stylesheetStructure["/*"+QString::number(m_orderNumber,10)]=tmp; + m_styleSheet=m_styleSheet.right(m_styleSheet.length()-k-ws); + parse(); + } + + else { + m_stopProcessing = true; + emit errorOccurred(i18n("The comment") + " :\n" +m_styleSheet.mid(0,20) + "...\n "+ msg1); + return; + } +} + +unsigned int stylesheetParser::numberOfParenthesisInAParenthesisBlock(parenthesisKind p, const QString& b){ + QChar searchFor = '{'; + if (p == closed) + searchFor = '}'; + int num = 0; + int len = b.length(); + bool ignore = false; + for (int i = 0; i < len; i++) + { + if (b[i] == '/' && (i + 1 < len) && b[i + 1] == '*') + ignore = true; + if (b[i] == '*' && (i + 1 < len) && b[i + 1] == '/') + ignore = false; + if (!ignore && b[i] == searchFor) + num++; + } + return num; +} + +int findParanthesis(const QString& string, const QChar &ch, int startPos = 0) +{ + int pos = -1; + int len = string.length(); + bool ignore = false; + for (int i = startPos; i < len; i++) + { + if (string[i] == '/' && (i + 1 < len) && string[i + 1] == '*') + ignore = true; + if (string[i] == '*' && (i + 1 < len) && string[i + 1] == '/') + ignore = false; + if (!ignore && string[i] == ch) + { + pos = i; + break; + } + } + return pos; +} + +void stylesheetParser::parseSelector(){ + int closingParenthesisPos = findParanthesis(m_styleSheet, '}'); + if(closingParenthesisPos==-1) { + m_stopProcessing = true; + emit errorOccurred(i18n("The selector") + " :\n" +m_styleSheet.mid(0,20) + "...\n "+ msg1); + return; + } + + QString temp(m_styleSheet.left(closingParenthesisPos+1)); + + if(numberOfParenthesisInAParenthesisBlock(closed,temp) < numberOfParenthesisInAParenthesisBlock(opened,temp)){ + m_stopProcessing = true; + emit errorOccurred(i18n("The selector") + " :\n" +m_styleSheet.mid(0,20) + "...\n "+ msg1); + return; + } + + if(numberOfParenthesisInAParenthesisBlock(closed,temp) > numberOfParenthesisInAParenthesisBlock(opened,temp)){ + m_stopProcessing = true; + emit errorOccurred(i18n("The selector") + " :\n" +m_styleSheet.mid(0,20) + "...\n "+ msg2); + return; + } + + int closingParentheses = 1, + openingParentheses = 0; + while(true){ + openingParentheses = numberOfParenthesisInAParenthesisBlock(closed,m_styleSheet.left(closingParenthesisPos+1)); //m_styleSheet.left(closingParenthesisPos+1).contains("{"); + + if(openingParentheses==closingParentheses){ + QString selectorName=m_styleSheet.left(findParanthesis(m_styleSheet, '{')/*m_styleSheet.find("{")*/).stripWhiteSpace(), + selectorValue=m_styleSheet.mid(findParanthesis(m_styleSheet, '{')/*m_styleSheet.find("{")*/+1, closingParenthesisPos - m_styleSheet.find("{") -1); + + selectorName.remove("\n").remove("\t"); + selectorValue.remove("\n").remove("\t"); + QPair tmp(selectorValue,++m_orderNumber); + + if (m_stylesheetStructure.contains(selectorName)) + { + uint i = 2; + QString s = selectorName + QString("-v%1").arg(i); + while (m_stylesheetStructure.contains(s)) + { + i++; + s = selectorName + QString("-v%1").arg(i); + } + selectorName = s; + } + m_stylesheetStructure[selectorName]=tmp; + break; + } + else { + closingParenthesisPos = findParanthesis(m_styleSheet, '{',closingParenthesisPos+1)/*m_styleSheet.find("}",closingParenthesisPos+1)*/; + closingParentheses++; + } + } + + int ws=whiteSpaces(closingParenthesisPos+1); + m_styleSheet=m_styleSheet.right(m_styleSheet.length()-closingParenthesisPos-1-ws); + parse(); +} + +void stylesheetParser::parseAtRules1(){ +//TODO this needs to be fixed : in case the at rule is not properly closed the parser hangs + if(m_styleSheet.find("{") == -1) { + m_stopProcessing = true; + emit errorOccurred(m_styleSheet.mid(0,20) + "...\n " + msg2); + return; + } + + int closingParenthesisPos = m_styleSheet.find("}"), + closingParentheses = 0; + + if(closingParenthesisPos==-1) return; + else closingParentheses = 1; + + int openingParentheses=0; + while(true){ + openingParentheses = m_styleSheet.left(closingParenthesisPos+1).contains("{"); + + if(openingParentheses==closingParentheses) + break; + else { + closingParenthesisPos = m_styleSheet.find("}",closingParenthesisPos+1); + if( closingParenthesisPos!= -1 ) + closingParentheses++; + else { + m_stopProcessing = true; + emit errorOccurred(m_styleSheet.mid(0,20) + "...\n " + msg1); + return; + } + } + } + + int ws=whiteSpaces(closingParenthesisPos+1); + QPair tmp(m_styleSheet.left(closingParenthesisPos+1+ws),++m_orderNumber); + m_stylesheetStructure["@rule"+QString::number(m_orderNumber,10)]=tmp; + m_styleSheet=m_styleSheet.right(m_styleSheet.length()-closingParenthesisPos-1-ws); + parse(); +} + +void stylesheetParser::parseAtRules2(){ +//TODO this needs to be fixed : in case the at rule is not properly closed the parser hangs + int semicolonPos = m_styleSheet.find(";"); + + if(semicolonPos==-1) { + m_stopProcessing = true; + emit errorOccurred(m_styleSheet.mid(0,20) + "...\n " + msg1); + return; + } + + int ws=whiteSpaces(semicolonPos+1); + QPair tmp(m_styleSheet.left(semicolonPos+1+ws),++m_orderNumber); + m_stylesheetStructure["@rule"+QString::number(m_orderNumber,10)]=tmp; + m_styleSheet=m_styleSheet.right(m_styleSheet.length()-semicolonPos-1-ws); + parse(); +} + +#include "stylesheetparser.moc" diff --git a/quanta/components/csseditor/stylesheetparser.h b/quanta/components/csseditor/stylesheetparser.h new file mode 100644 index 00000000..26d5fa3e --- /dev/null +++ b/quanta/components/csseditor/stylesheetparser.h @@ -0,0 +1,58 @@ +/*************************************************************************** + stylesheetparser.h - description + ------------------- + begin : gio ago 19 2004 + copyright : (C) 2004 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 STYLESHEETPARSER_H +#define STYLESHEETPARSER_H + +#include +#include +#include + +/** + *@author gulmini luciano + */ + +class stylesheetParser : public QObject{ + Q_OBJECT + private: + + enum parenthesisKind { opened, closed }; + QString m_styleSheet; + bool m_stopProcessing; + unsigned int m_orderNumber; + QMap > m_stylesheetStructure; + void parseComment(); + void parseSelector(); + void parseAtRules1(); + void parseAtRules2(); + int whiteSpaces(int); + unsigned int numberOfParenthesisInAParenthesisBlock(parenthesisKind p, const QString& b); + + public: + stylesheetParser(const QString& s); + ~stylesheetParser(){} + void parse(); + + QMap > stylesheetStructure() { return m_stylesheetStructure; } + unsigned int orderNumber() const {return m_orderNumber; } + + signals: + void errorOccurred(const QString&); +}; + +#endif + diff --git a/quanta/components/csseditor/tlpeditors.cpp b/quanta/components/csseditor/tlpeditors.cpp new file mode 100644 index 00000000..706ac518 --- /dev/null +++ b/quanta/components/csseditor/tlpeditors.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + tlpeditors.cpp - description + ------------------- + begin : gio apr 1 2004 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "qextfileinfo.h" +#include "tlpeditors.h" +#include "fontfamilychooser.h" +#include "project.h" + +TLPEditor::TLPEditor(QWidget *parent, const char* name) : miniEditor(parent,name){ + m_label = new QLabel(this); + m_le = new QLineEdit(this); + m_pb = new KPushButton(this); + setSpacing( KDialog::spacingHint() ); +} + +TLPEditor::~TLPEditor(){ + delete m_label; + delete m_le; + delete m_pb; +} + +void TLPEditor::setButtonIcon(QString s){ + QIconSet iconSet = SmallIconSet(QString::fromLatin1(s)); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + m_pb->setIconSet(iconSet); + m_pb->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); +} + +void TLPEditor::setLabelText(QString s){ + m_label->setText(s); +} + +void TLPEditor::setToolTip(QString s){ + QToolTip::add(m_pb, s); +} + +void TLPEditor::setWhatsThis(QString s){ + QWhatsThis::add(m_le,s); +} + +URIEditor::URIEditor(QWidget *parent, const char* name) : TLPEditor(parent,name){ + QString whatsthis =i18n("With this line edit you can insert the URI of the resource you want to reach"); + setWhatsThis(whatsthis); + setLabelText(" Uri :"); + setButtonIcon("fileopen"); + setToolTip(i18n("Open the URI selector")); + + connect(m_pb, SIGNAL(clicked()), this, SLOT(openFileDialog())); +} + +void URIEditor::connectToPropertySetter(propertySetter* p){ + connect(this,SIGNAL(valueChanged(const QString&)), p ,SIGNAL(valueChanged(const QString&))); +} + +void URIEditor::setMode(const mode& m) { + m_Mode = m ; + if( m_Mode == Single ) + connect(m_le, SIGNAL(textChanged ( const QString & )), this, SLOT(selectedURI(const QString&))); + else{ + connect(m_le, SIGNAL(textChanged ( const QString & )), this, SLOT(selectedURIs(const QStringList&))); + } +} + +void URIEditor::selectedURI(const QString & s){ + KURL u; + u.setPath(s); + emit valueChanged("url(\'" + QExtFileInfo::toRelative(u, Project::ref()->projectBaseURL()).path() + "\')"); +} + +void URIEditor::selectedURIs(const QStringList& s){ + KURL u; + QStringList selectedFiles = s, + selectedFilesWithURLFormat; + for ( QStringList::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ){ + u.setPath(*it); + selectedFilesWithURLFormat.append( "url(\'" + QExtFileInfo::toRelative(u, Project::ref()->projectBaseURL()).path() + "\')"); + } + emit valueChanged(selectedFilesWithURLFormat.join(",")); +} + +void URIEditor::openFileDialog(){ + + KFileDialog fd( Project::ref()->projectBaseURL().url(), "*.*", this, "file dialog", true ); + switch(m_resourceType) { + case image : { + fd.setFilter( "*.png *.gif *.jpg *.mng|" + i18n("Image Files") +" (*.png *.gif *.jpg *.mng)\n*.*|" + i18n("All Files")+(" (*.*)") ); + KImageFilePreview *ip = new KImageFilePreview( &fd ); + fd.setPreviewWidget( ip ); + } + break; + case audio : { + fd.setFilter( "*.au *.aiff *.wav|" + i18n("Audio Files")+" (*.au *.aiff *.wav)\n*.*|" + i18n("All Files")+(" (*.*)") ); + + + } + break; + //case mousePointer : fd.setFilter( "*.|" + i18n("Mouse Pointers (*.)")+"\n*.*|" + i18n("All Files (*.*)") );break; + case mousePointer : fd.setFilter( "*.*|" + i18n("All Files")+(" (*.*)") );break; + + default:; + } + + if( m_Mode == Single) + fd.setMode(KFile::File); + else + fd.setMode(KFile::Files); + + + if( fd.exec() ){ + if( fd.mode() == KFile::File ) + selectedURI( fd.selectedFile() ); + else { + selectedURIs( fd.selectedFiles() ); + /*QStringList selectedFiles = fd.selectedFiles(); + KURL u; + for ( QStringList::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ){ + u.setPath(*it); + m_sFiles.append( "url(\'" + QExtFileInfo::toRelative(u, Project::ref()->projectBaseURL()).path() + "\')"); + } + emit valueChanged(m_sFiles.join(","));*/ + } + } +} + +fontEditor::fontEditor(QWidget *parent, const char* name) : TLPEditor(parent,name), m_initialValue(QString::null){ + QString whatsthis =i18n("With this line edit you can insert the name of the font you want to use"); + setWhatsThis(whatsthis); + setLabelText(i18n("Font family:")); + setButtonIcon("fonts"); + setToolTip(i18n("Open font family chooser")); + connect(m_pb, SIGNAL(clicked()), this, SLOT(openFontChooser())); + connect(m_le, SIGNAL(textChanged ( const QString & )), this, SIGNAL( valueChanged( const QString& ) ) ); +} + +void fontEditor::connectToPropertySetter(propertySetter* p){ + connect(this, SIGNAL(valueChanged(const QString&)), p, SIGNAL(valueChanged(const QString&))); +} + +void fontEditor::openFontChooser(){ + fontFamilyChooser dlg( this ); + dlg.setInitialValue(m_initialValue); + if( dlg.exec() ) + emit valueChanged( dlg.fontList().join(", ")); +} + +#include "tlpeditors.moc" diff --git a/quanta/components/csseditor/tlpeditors.h b/quanta/components/csseditor/tlpeditors.h new file mode 100644 index 00000000..d0e52d37 --- /dev/null +++ b/quanta/components/csseditor/tlpeditors.h @@ -0,0 +1,94 @@ +/*************************************************************************** + tlpeditors.h - description + ------------------- + begin : gio apr 1 2004 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 TLPEDITORS_H +#define TLPEDITORS_H + +#include "minieditor.h" +#include "propertysetter.h" + +class KPushButton; +class QLineEdit; +class QLabel; +/** + *@author gulmini luciano + */ + + +class TLPEditor : public miniEditor { //editor with a line text and a button calling a dialog + Q_OBJECT + + protected: + QLineEdit *m_le; + QLabel *m_label; + KPushButton *m_pb; + + public: + TLPEditor(QWidget *parent, const char* name=0); + virtual ~TLPEditor(); + virtual void setButtonIcon(QString); + void setToolTip(QString); + void setLabelText(QString); + void setWhatsThis(QString); + QLineEdit* lineEdit() const { return m_le; } + KPushButton* button() const { return m_pb; } + virtual void setInitialValue(const QString& s)=0; + virtual void connectToPropertySetter(propertySetter* p)=0; + + signals: + void valueChanged(const QString&); +}; + +class fontEditor : public TLPEditor{ + Q_OBJECT + private: + QString m_initialValue; + + public: + fontEditor(QWidget *parent, const char* name=0); + virtual void setInitialValue(const QString& s) { m_initialValue = s; } + virtual void connectToPropertySetter(propertySetter* p); + + public slots: + void openFontChooser(); +}; + +class URIEditor : public TLPEditor { + Q_OBJECT + public: + enum mode{ Multi, Single }; + enum URIResourceType{ audio, image, mousePointer }; + + private: + mode m_Mode; + URIResourceType m_resourceType; + + public: + URIEditor(QWidget *parent, const char* name=0); + void setMode(const mode& m); + void setResourceType(const URIResourceType& r) { m_resourceType = r ; } + virtual void setInitialValue(const QString& /*s*/){} + virtual void connectToPropertySetter(propertySetter* p); + + public slots: + void selectedURI(const QString&); + void selectedURIs(const QStringList&); + void openFileDialog(); +}; + + +#endif diff --git a/quanta/components/cvsservice/Makefile.am b/quanta/components/cvsservice/Makefile.am new file mode 100644 index 00000000..79429348 --- /dev/null +++ b/quanta/components/cvsservice/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libcvsservice.la + +libcvsservice_la_SOURCES = cvsservice.cpp cvscommitdlgs.ui \ + cvsservicedcopif.skel cvsupdatetodlgs.ui +libcvsservice_la_METASOURCES = AUTO + +AM_CPPFLAGS = -I$(top_srcdir)/quanta/src \ + -I$(top_srcdir)/quanta/utility \ + -I$(top_srcdir)/quanta/parsers \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/lib \ + $(KMDI_INCLUDES) $(all_includes) +noinst_HEADERS = cvsservicedcopif.h diff --git a/quanta/components/cvsservice/cvscommitdlgs.ui b/quanta/components/cvsservice/cvscommitdlgs.ui new file mode 100644 index 00000000..ce2c9fd0 --- /dev/null +++ b/quanta/components/cvsservice/cvscommitdlgs.ui @@ -0,0 +1,150 @@ + +CVSCommitDlgS +/*************************************************************************** + * * + * 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; version 2 of the License. * + * * +***************************************************************************/ + +(C) 2004 Andras Mantia <amantia@kde.org> + + + CVSCommitDlgS + + + + 0 + 0 + 600 + 480 + + + + CVS Commit + + + + unnamed + + + + fileList + + + + + textLabel1 + + + Commit the following files: + + + + + messageCombo + + + false + + + + + textLabel2 + + + Older &messages: + + + messageCombo + + + + + textLabel3 + + + &Log message: + + + logEdit + + + + + logEdit + + + + + cancelButton + + + &Cancel + + + + + okButton + + + &OK + + + true + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 80 + 20 + + + + + + + + + + okButton + clicked() + CVSCommitDlgS + accept() + + + cancelButton + clicked() + CVSCommitDlgS + reject() + + + messageCombo + activated(const QString&) + logEdit + setText(const QString&) + + + + fileList + messageCombo + logEdit + okButton + cancelButton + + + + klistbox.h + + diff --git a/quanta/components/cvsservice/cvsservice.cpp b/quanta/components/cvsservice/cvsservice.cpp new file mode 100644 index 00000000..043af54e --- /dev/null +++ b/quanta/components/cvsservice/cvsservice.cpp @@ -0,0 +1,555 @@ +/*************************************************************************** + cvsservice.cpp - description + ------------------------------ + begin : Sun May 16 17:50:25 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; version 2 + * + ***************************************************************************/ + +//qt include +#include +#include +#include +#include +#include +#include + +//kde includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// CvsService +#include +#include +#include + +#include "cvsservice.h" +#include "cvscommitdlgs.h" +#include "cvsupdatetodlgs.h" + +#define CVSSERVICE_TIMEOUT 1000*60 + +CVSService::CVSService(KActionCollection *ac) +{ + m_menu = new KPopupMenu(); + KAction *action = new KAction(i18n("&Commit..."), "vcs_commit", 0, this, SLOT(slotCommit()), ac, "vcs_commit"); + action->plug(m_menu); + action = new KAction(i18n("&Update"), "vcs_update", 0, this, SLOT(slotUpdate()), ac, "vcs_update"); + action->plug(m_menu); + KPopupMenu *updateToMenu = new KPopupMenu(m_menu); + m_menu->insertItem(SmallIconSet("vcs_update"), i18n("Update &To"), updateToMenu); + action = new KAction(i18n("&Tag/Date..."), "vcs_update", 0, this, SLOT(slotUpdateToTag()), ac, "vcs_update_tag_date"); + action->plug(updateToMenu); + action = new KAction(i18n("&HEAD"), "vcs_update", 0, this, SLOT(slotUpdateToHead()), ac, "vcs_update_head"); + action->plug(updateToMenu); + action = new KAction(i18n("Re&vert"), "reload", 0, this, SLOT(slotRevert()), ac, "vcs_revert"); + action->plug(m_menu); + m_menu->insertSeparator(); + action = new KAction(i18n("&Add to Repository..."), "vcs_add", 0, this, SLOT(slotAdd()), ac, "vcs_add"); + action->plug(m_menu); + action = new KAction(i18n("&Remove From Repository..."), "vcs_remove", 0, this, SLOT(slotRemove()), ac, "vcs_remove"); + action->plug(m_menu); + action = new KAction(i18n("&Ignore in CVS Operations"), 0, this, SLOT(slotAddToCVSIgnore()), ac); + action->plug(m_menu); + action = new KAction(i18n("Do &Not Ignore in CVS Operations"), 0, this, SLOT(slotRemoveFromCVSIgnore()), ac); + action->plug(m_menu); + + m_menu->insertSeparator(); + action = new KAction(i18n("Show &Log Messages"), 0, this, SLOT(slotBrowseLog()), ac); + action->plug(m_menu); + + m_cvsJob = 0L; + m_repository = 0L; + m_cvsService =0L; + m_commitDlg = new CVSCommitDlgS(); + m_updateToDlg = new CVSUpdateToDlgS(); + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout())); +} + +CVSService::~CVSService() +{ + if (m_cvsService) + m_cvsService->quit(); + delete m_cvsService; + delete m_menu; + delete m_repository; + m_repository = 0L; + m_cvsService = 0L; + delete m_commitDlg; + delete m_updateToDlg; +} + +void CVSService::setAppId(const QCString &id) +{ + m_appId = id; + m_cvsService = new CvsService_stub(m_appId, "CvsService"); + m_timer->start(CVSSERVICE_TIMEOUT, true); +} + +void CVSService::setRepository(const QString &repository) +{ + startService(); + delete m_repository; + m_repository = new Repository_stub(m_appId, "CvsRepository"); + if (m_repository->setWorkingCopy(repository)) + { + m_repositoryPath = repository; + if (!m_repositoryPath.endsWith("/")) + m_repositoryPath += "/"; + } +} + +void CVSService::slotUpdate() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotUpdate(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotUpdate(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty()) + { + emit clearMessages(); + emit showMessage(i18n("Running CVS update...") + "\n", false); + m_files = files; + m_job = m_cvsService->update(files, true, true, true, ""); + m_cvsCommand = "update"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotUpdateToTag() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotUpdateToTag(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotUpdateToTag(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty() && m_updateToDlg->exec()) + { + QString extraOpts; + QString commandStr; + if (m_updateToDlg->tagRadioButton->isChecked()) + { + extraOpts = "-r " + m_updateToDlg->tagCombo->currentText(); + commandStr = i18n("Updating to revision %1 ...").arg(m_updateToDlg->tagCombo->currentText()); + } else + { + extraOpts = "-D " + m_updateToDlg->dateLineEdit->text(); + commandStr = i18n("Updating to the version from %1 ...").arg(+ m_updateToDlg->dateLineEdit->text()); + } + emit clearMessages(); + emit showMessage(commandStr + "\n", false); + m_files = files; + m_job = m_cvsService->update(files, true, true, true, extraOpts); + m_cvsCommand = "update"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotUpdateToHead() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotUpdateToHead(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotUpdateToHead(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty()) + { + emit clearMessages(); + emit showMessage(i18n("Updating to HEAD...") + "\n", false); + m_files = files; + m_job = m_cvsService->update(files, true, true, true, "-A"); + m_cvsCommand = "update"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotCommit() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotCommit(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotCommit(const QStringList &files) +{ + startService(); + m_commitDlg->fileList->clear(); + m_commitDlg->fileList->insertStringList(files); + m_commitDlg->logEdit->clear(); + m_commitDlg->messageCombo->insertItem(i18n("Current"), 0); + m_commitDlg->messageCombo->setCurrentItem(0); + + if (m_repository && !m_appId.isEmpty() && m_commitDlg->exec()) + { + m_commitDlg->messageCombo->removeItem(0); + QString message = m_commitDlg->logEdit->text(); + if (message != m_commitDlg->messageCombo->currentText()) + m_commitDlg->messageCombo->insertItem(message, 0); + emit clearMessages(); + emit showMessage(i18n("Running CVS commit...") + "\n", false); + m_files = files; + m_job = m_cvsService->commit(files, message, true); + m_cvsCommand = "commit"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotRevert() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotRevert(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotRevert(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty()) + { + emit clearMessages(); + emit showMessage(i18n("Reverting to the version from the repository...") + "\n", false); + m_files = files; + m_job = m_cvsService->update(files, true, true, true, "-C"); + m_cvsCommand = "update"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotAdd() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotAdd(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotAdd(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty() && (KMessageBox::questionYesNoList(0, i18n("Add the following files to repository?"), files, i18n("CVS Add"), KStdGuiItem::add(), i18n("Do Not Add")) == KMessageBox::Yes)) + { + emit clearMessages(); + emit showMessage(i18n("Adding file to the repository...") + "\n", false); + m_files = files; + m_job = m_cvsService->add(files, false); + m_cvsCommand = "add"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotRemove() +{ + QStringList files; + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + files += m_defaultFile.remove(m_repositoryPath); + slotRemove(files); + } else + { + notInRepository(); + } + } +} + +void CVSService::slotRemove(const QStringList &files) +{ + startService(); + if (m_repository && !m_appId.isEmpty() && (KMessageBox::warningContinueCancelList(0, i18n("Remove the following files from the repository?
This will remove your working copy as well.
"), files, i18n("CVS Remove")) == KMessageBox::Continue)) + { + emit clearMessages(); + emit showMessage(i18n("Removing files from the repository...") + "\n", false); + m_files = files; + m_job = m_cvsService->remove(files, true); + m_cvsCommand = "remove"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } +} + +void CVSService::slotBrowseLog() +{ + startService(); + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + QString file = m_defaultFile.remove(m_repositoryPath); + if (m_repository && !m_appId.isEmpty() ) + { + emit clearMessages(); + emit showMessage(i18n("Showing CVS log...") + "\n", false); + m_files += file; + m_job = m_cvsService->log(file); + m_cvsCommand = "log"; + m_cvsJob = new CvsJob_stub(m_job.app(), m_job.obj()); + + connectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)", true); + connectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)", true); + m_cvsJob->execute(); + } + } else + { + notInRepository(); + } + } +} + +void CVSService::slotAddToCVSIgnore() +{ + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + emit clearMessages(); + QFileInfo fInfo(m_defaultFile); + QFile f(fInfo.dirPath()+ "/.cvsignore"); + if (f.open(IO_ReadWrite)) + { + bool found = false; + QTextStream str(&f); + str.setEncoding(QTextStream::UnicodeUTF8); + QString line; + while (!str.atEnd()) + { + line = str.readLine().stripWhiteSpace(); + if (line == fInfo.fileName()) + { + emit showMessage(i18n("\"%1\" is already in the CVS ignore list.").arg(fInfo.fileName()) + "\n", false); + found = true; + break; + } + } + if (!found) + { + str << fInfo.fileName() << endl; + emit showMessage(i18n("\"%1\" added to the CVS ignore list.").arg(fInfo.fileName()) + "\n", false); + } + f.close(); + } + + } else + { + notInRepository(); + } + } +} + +void CVSService::slotRemoveFromCVSIgnore() +{ + if (!m_defaultFile.isEmpty()) + { + if (m_defaultFile.startsWith(m_repositoryPath)) + { + emit clearMessages(); + QString content; + QFileInfo fInfo(m_defaultFile); + QFile f(fInfo.dirPath()+ "/.cvsignore"); + bool found = false; + if (f.open(IO_ReadWrite)) + { + QTextStream str(&f); + str.setEncoding(QTextStream::UnicodeUTF8); + QString line; + while (!str.atEnd()) + { + line = str.readLine().stripWhiteSpace(); + if (line != fInfo.fileName()) + { + content += line + "\n"; + } else + found = true; + } + if (!found) + { + emit showMessage(i18n("\"%1\" is not in the CVS ignore list.").arg(fInfo.fileName()) + "\n", false); + } + f.close(); + } + if (found && f.open(IO_WriteOnly)) + { + QTextStream str(&f); + str.setEncoding(QTextStream::UnicodeUTF8); + str << content; + emit showMessage(i18n("\"%1\" removed from the CVS ignore list.").arg(fInfo.fileName()) + "\n", false); + f.close(); + } + + } else + { + notInRepository(); + } + } +} + +void CVSService::slotJobExited(bool normalExit, int exitStatus) +{ + if (!normalExit) + { + KMessageBox::sorry(0, i18n("The CVS command %1 has failed. The error code was %2.").arg(m_cvsCommand).arg(exitStatus), i18n("Command Failed")); + } + if (exitStatus == 0) + { + emit commandExecuted(m_cvsCommand, m_files); + } + disconnectDCOPSignal(m_job.app(), m_job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)"); + disconnectDCOPSignal(m_job.app(), m_job.obj(), "receivedStdout(QString)", "slotReceivedStdout(QString)"); + disconnectDCOPSignal(m_job.app(), m_job.obj(), "receivedStderr(QString)", "slotReceivedStderr(QString)"); + //delete m_cvsJob; + //m_cvsJob = 0L; + emit showMessage(i18n("CVS command finished."), false); + emit showMessage(" ", false); +} + +void CVSService::slotReceivedStdout(QString output) +{ + emit showMessage(output, true); +} + +void CVSService::slotReceivedStderr(QString output) +{ + emit showMessage(output, true); +} + +void CVSService::notInRepository() +{ + emit clearMessages(); + emit showMessage(i18n("Error: \"%1\" is not part of the\n\"%2\" repository.").arg(m_defaultFile).arg(m_repositoryPath) + "\n", false); +} + +void CVSService::startService() +{ + if (!m_cvsService) + { + QString error; + KApplication::startServiceByDesktopName("cvsservice", QStringList(), &error, + &m_appId); + m_cvsService = new CvsService_stub(m_appId, "CvsService"); + } + m_timer->start(CVSSERVICE_TIMEOUT, true); +} + +void CVSService::slotTimeout() +{ + if (m_cvsService) + m_cvsService->quit(); + delete m_cvsService; + m_cvsService = 0L; +} + +#include "cvsservice.moc" diff --git a/quanta/components/cvsservice/cvsservice.h b/quanta/components/cvsservice/cvsservice.h new file mode 100644 index 00000000..ebfcb402 --- /dev/null +++ b/quanta/components/cvsservice/cvsservice.h @@ -0,0 +1,118 @@ +/*************************************************************************** + cvsservice.h - description + ------------------------------ + begin : Sun May 16 17:50:25 2004 + copyright : (C) 2004, 2005 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; version 2 + * + ***************************************************************************/ + +#ifndef CVSSERVICE_H +#define CVSSERVICE_H + +//qt includes +#include + +//kde includes +#include + +//own includes +#include "cvsservicedcopif.h" + +class QTimer; +class KPopupMenu; +class KActionCollection; +class CvsJob_stub; +class CvsService_stub; +class Repository_stub; + +class CVSCommitDlgS; +class CVSUpdateToDlgS; + +/** @short This class manages the CVS repositories from withing Quanta with the help of "cvsservice" + * + */ +class CVSService : public QObject, public CVSServiceDCOPIf +{ + Q_OBJECT + +public: + + /** + * since this class is a singleton you must use this function to access it + * @return the class pointer + */ + static CVSService* ref(KActionCollection *ac = 0L) + { + static CVSService *m_ref; + if (!m_ref) m_ref = new CVSService(ac); + return m_ref; + } + + ~CVSService(); + + void setAppId(const QCString& id); + /** Returns true if the cvsservice was found */ + bool exists() {return !m_appId.isEmpty();} + void setRepository(const QString &repository); + void setCurrentFile(const QString &file) {m_defaultFile = file;} + KPopupMenu *menu() {return m_menu;} + +public slots: + void slotUpdate(); + void slotUpdate(const QStringList &files); + void slotUpdateToTag(); + void slotUpdateToTag(const QStringList &files); + void slotUpdateToHead(); + void slotUpdateToHead(const QStringList &files); + void slotCommit(); + void slotCommit(const QStringList &files); + void slotRevert(); + void slotRevert(const QStringList &files); + void slotAdd(); + void slotAdd(const QStringList &files); + void slotRemove(); + void slotRemove(const QStringList &files); + void slotBrowseLog(); + void slotAddToCVSIgnore(); + void slotRemoveFromCVSIgnore(); + + virtual void slotJobExited(bool normalExit, int exitStatus); + virtual void slotReceivedStdout(QString output); + virtual void slotReceivedStderr(QString output); + +signals: + void clearMessages(); + void showMessage(const QString &msg, bool append); + void commandExecuted(const QString& command, const QStringList& files); + +private slots: + void slotTimeout(); + +private: + CVSService(KActionCollection *ac); + void notInRepository(); + void startService(); + + QCString m_appId; + KPopupMenu *m_menu; + Repository_stub *m_repository; + CvsJob_stub *m_cvsJob; + CvsService_stub *m_cvsService; + QString m_defaultFile; + QString m_repositoryPath; + QString m_cvsCommand; + QStringList m_files; + CVSCommitDlgS *m_commitDlg; + CVSUpdateToDlgS *m_updateToDlg; + DCOPRef m_job; + QTimer *m_timer; +}; + +#endif diff --git a/quanta/components/cvsservice/cvsservicedcopif.h b/quanta/components/cvsservice/cvsservicedcopif.h new file mode 100644 index 00000000..75c0434a --- /dev/null +++ b/quanta/components/cvsservice/cvsservicedcopif.h @@ -0,0 +1,30 @@ +/*************************************************************************** + cvsservicedcopif.h - description + ------------------------------ + begin : Sun May 16 22:50:25 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; version 2 + * + ***************************************************************************/ + +#ifndef CVSSERVICEDCOPIF_H +#define CVSSERVICEDCOPIF_H + +#include +#include + +class CVSServiceDCOPIf : virtual public DCOPObject +{ + K_DCOP +k_dcop: + virtual void slotJobExited( bool normalExit, int exitStatus ) = 0; + virtual void slotReceivedStdout( QString someOutput ) = 0; +}; + +#endif diff --git a/quanta/components/cvsservice/cvsupdatetodlgs.ui b/quanta/components/cvsservice/cvsupdatetodlgs.ui new file mode 100644 index 00000000..ef646f92 --- /dev/null +++ b/quanta/components/cvsservice/cvsupdatetodlgs.ui @@ -0,0 +1,198 @@ + +CVSUpdateToDlgS +/*************************************************************************** + * * + * 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; version 2 of the License. * + * * +***************************************************************************/ + +(C) 2005 Andras Mantia <amantia@kde.org> + + + CVSUpdateToDlgS + + + + 0 + 0 + 499 + 213 + + + + CVS Update + + + + unnamed + + + + buttonGroup1 + + + NoFrame + + + Plain + + + + + + + unnamed + + + + dateRadioButton + + + Update to &date ('yyyy-mm-dd'): + + + + + tagRadioButton + + + Update to &tag/branch: + + + true + + + + + tagCombo + + + true + + + + + spacer2 + + + Horizontal + + + Fixed + + + + 40 + 20 + + + + + + dateLineEdit + + + + + spacer2_2 + + + Horizontal + + + Fixed + + + + 40 + 20 + + + + + + + + layout5 + + + + unnamed + + + + cancelButton + + + + 1 + 0 + 0 + 0 + + + + &Cancel + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 295 + 20 + + + + + + okButton + + + + 1 + 0 + 0 + 0 + + + + &OK + + + true + + + true + + + + + + + + + cancelButton + clicked() + CVSUpdateToDlgS + reject() + + + okButton + clicked() + CVSUpdateToDlgS + accept() + + + + diff --git a/quanta/components/debugger/Makefile.am b/quanta/components/debugger/Makefile.am new file mode 100644 index 00000000..f24e455d --- /dev/null +++ b/quanta/components/debugger/Makefile.am @@ -0,0 +1,25 @@ +SUBDIRS = interfaces gubed dbgp +METASOURCES = AUTO + + +noinst_LTLIBRARIES = libdebuggermanager.la + +libdebuggermanager_la_LDFLAGS = $(all_libraries) +libdebuggermanager_la_LIBADD = interfaces/libdebuggerinterface.la +libdebuggermanager_la_SOURCES = debuggermanager.cpp debuggerbreakpoint.cpp \ + quantadebuggerinterface.cpp debuggervariable.cpp debuggerui.cpp variableslistview.cpp \ + debuggerbreakpointlist.cpp debuggervariablesets.ui debuggerbreakpointview.cpp pathmapper.cpp \ + pathmapperdialogs.ui pathmapperdialog.cpp pathmapperdialog.h conditionalbreakpointdialogs.ui \ + conditionalbreakpointdialog.cpp conditionalbreakpointdialog.h backtracelistview.cpp + +AM_CPPFLAGS = -I$(top_srcdir)/quanta/components/debuggerquanta \ + -I$(top_srcdir)/quanta/components/debugger/interfaces \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/quanta/utility \ + -I$(top_srcdir)/quanta/src \ + -I$(top_srcdir)/quanta/parsers \ + -I$(top_srcdir)/quanta/parts/preview \ + -I$(top_srcdir)/quanta/messages \ + -I$(top_srcdir)/lib \ + $(KMDI_INCLUDES) $(all_includes) +noinst_HEADERS = pathmapper.h backtracelistview.h diff --git a/quanta/components/debugger/backtracelistview.cpp b/quanta/components/debugger/backtracelistview.cpp new file mode 100644 index 00000000..aa5c8c95 --- /dev/null +++ b/quanta/components/debugger/backtracelistview.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + backtracelistview.cpp + -------------------------- + begin : 2005-07-31 + copyright : (C) 2005 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// KDE Includes +#include +#include +#include +#include +#include + +// Quanta includes +#include "backtracelistview.h" +#include "debuggerclient.h" +#include "debuggermanager.h" +#include "resource.h" +#include "quanta.h" + +namespace BacktraceListviewColumns +{ + // The enums must correspond to the order of the columns + // If you change here, change the column adding + enum Columns + { + Level = 0, + Type, + File, + Line, + Function + }; +} + +BacktraceListviewItem::BacktraceListviewItem(BacktraceListview* view) + : KListViewItem(view) +{ +} + + +BacktraceListview::BacktraceListview(QWidget *parent, const char *name) + : KListView(parent, name) +{ + int charwidth = this->fontMetrics().width("0"); + // If you change the order here, change the BacktraceListviewColumns enums above + addColumn("#", charwidth * 3); + addColumn(i18n("Type"), charwidth * 10); + addColumn(i18n("File"), charwidth * 60); + addColumn(i18n("Line"), charwidth * 6); + addColumn(i18n("Function"), charwidth * 30); + + setSorting(BacktraceListviewColumns::Level); // Sort on the level column + setAllColumnsShowFocus(true); + + // Jump to bt + connect(this, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int) ), this, SLOT(slotBacktraceDoubleClick( QListViewItem *, const QPoint &, int))); +} + + +BacktraceListview::~BacktraceListview() +{} + +void BacktraceListview::backtraceShow(int level, BacktraceType type, const QString& filename, long line, const QString& func) +{ + BacktraceListviewItem* item = new BacktraceListviewItem(this); + item->setLevel(level); + item->setType(type); + item->setFilename(filename); + item->setLine(line); + item->setFunc(func); + + item->setText(BacktraceListviewColumns::File, filename); + item->setText(BacktraceListviewColumns::Function, func); + item->setText(BacktraceListviewColumns::Level, QString::number(level)); + item->setText(BacktraceListviewColumns::Line, QString::number(line + 1)); + item->setText(BacktraceListviewColumns::Type, type == File ? i18n("File") : i18n("Eval")); + + insertItem(item); +} + +void BacktraceListview::keyPressEvent(QKeyEvent *e) +{ + if(e->key() != Qt::Key_Enter) + { + e->ignore(); + return; + } + + if(selectedItem()) + jumpHistory(selectedItem()); +} + +void BacktraceListview::clear() +{ + KListView::clear(); +} + +void BacktraceListview::slotBacktraceDoubleClick(QListViewItem *item, const QPoint &, int ) +{ + if(!item) + return; + + jumpHistory(item); +} + +void BacktraceListview::jumpHistory(QListViewItem *item) +{ + BacktraceListviewItem* btitem = dynamic_cast(item); + + if(btitem->type() == File) + { + quantaApp->gotoFileAndLine(btitem->filename(), btitem->line(), 0); + } + +} + +#include "backtracelistview.moc" diff --git a/quanta/components/debugger/backtracelistview.h b/quanta/components/debugger/backtracelistview.h new file mode 100644 index 00000000..e00d0afc --- /dev/null +++ b/quanta/components/debugger/backtracelistview.h @@ -0,0 +1,93 @@ +/*************************************************************************** + Backtracelistview.h + ------------------------ + begin : 2005-07-31 + copyright : (C) 2005 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 BACKTRACELISTVIEW_H +#define BACKTRACELISTVIEW_H + +#include +#include +#include + +class BacktraceListview; + + +enum BacktraceType +{ + File = 0, + Eval +}; + + +class BacktraceListviewItem : public KListViewItem +{ + private: + BacktraceType m_type; + QString m_filename; + QString m_func; + long m_line; + long m_level; + + public: + BacktraceListviewItem(); + BacktraceListviewItem(BacktraceListview* view); + + // Type + BacktraceType type() const { return m_type; } + void setType(BacktraceType type) { m_type = type; } + + // Filename + QString filename() const { return m_filename; } + void setFilename(const QString &filename) { m_filename = filename; } + + // Function + QString func() const { return m_func; } + void setFunc(const QString &func) { m_func = func; } + + // Line + long line() const { return m_line; } + void setLine(long line) { m_line= line; } + + // Level + long level() const { return m_level; } + void setLevel(long level) { m_level = level; } + +}; + +class BacktraceListview : public KListView +{ + Q_OBJECT + + public: + + BacktraceListview(QWidget *parent = 0, const char *name = 0); + ~BacktraceListview(); + + void backtraceShow(int level, BacktraceType type, const QString& filename, long line, const QString& func); + + void clear(); + + public slots: + void slotBacktraceDoubleClick(QListViewItem *item, const QPoint &point, int column); + + private: + void keyPressEvent(QKeyEvent *e); + void jumpHistory(QListViewItem *item); + +}; + +#endif diff --git a/quanta/components/debugger/conditionalbreakpointdialog.cpp b/quanta/components/debugger/conditionalbreakpointdialog.cpp new file mode 100644 index 00000000..943c33d4 --- /dev/null +++ b/quanta/components/debugger/conditionalbreakpointdialog.cpp @@ -0,0 +1,100 @@ +/*************************************************************************** + conditionalbreakpointdialog.cpp + -------------------- + begin : 2005-01-08 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "conditionalbreakpointdialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debuggerbreakpoint.h" + +ConditionalBreakpointDialog::ConditionalBreakpointDialog(const QString& expression, const QString& inFile, const QString& inClass, const QString& inFunction) + : ConditionalBreakpointDialogS(0, "ConditionalBreakpointDialog", false, 0) +{ + comboExpression->setCurrentText(expression); + lineFile->setText(inFile); + lineClass->setText(inClass); + lineFunction->setText(inFunction); + + buttonClearFile->setPixmap(SmallIcon("clear_left")); + buttonClearClass->setPixmap(SmallIcon("clear_left")); + buttonClearFunction->setPixmap(SmallIcon("clear_left")); + + connect(comboExpression, SIGNAL(textChanged(const QString&)), this, SLOT(slotExpressionChanged())); + + connect(buttonClearFile, SIGNAL(pressed()), this, SLOT(slotClearFile())); + connect(buttonClearClass, SIGNAL(pressed()), this, SLOT(slotClearClass())); + connect(buttonClearFunction, SIGNAL(pressed()), this, SLOT(slotClearFunction())); + + slotExpressionChanged(); +} + +ConditionalBreakpointDialog::~ConditionalBreakpointDialog() +{ +} + +void ConditionalBreakpointDialog::slotExpressionChanged() +{ + + if(comboExpression->currentText().find( QRegExp("[^=!]=[^=]"), 0 ) >= 0) + ledWarning->on(); + else + ledWarning->off(); + +} + +void ConditionalBreakpointDialog::slotClearFile() +{ + lineFile->setText(""); +} + +void ConditionalBreakpointDialog::slotClearClass() +{ + lineClass->setText(""); +} + +void ConditionalBreakpointDialog::slotClearFunction() +{ + lineFunction->setText(""); +} + +/*DebuggerBreakpoint::Types type()*/ + +DebuggerBreakpoint *ConditionalBreakpointDialog::breakpoint() +{ + if(comboExpression->currentText().isEmpty()) + return NULL; + + DebuggerBreakpoint *bp = new DebuggerBreakpoint( + (radioOnChange->isChecked() ? DebuggerBreakpoint::ConditionalChange : DebuggerBreakpoint::ConditionalTrue), + comboExpression->currentText(), + lineFile->text(), + lineClass->text(), + lineFunction->text()); + + return bp; +} + + +#include "conditionalbreakpointdialog.moc" + diff --git a/quanta/components/debugger/conditionalbreakpointdialog.h b/quanta/components/debugger/conditionalbreakpointdialog.h new file mode 100644 index 00000000..fdae39a3 --- /dev/null +++ b/quanta/components/debugger/conditionalbreakpointdialog.h @@ -0,0 +1,56 @@ +/*************************************************************************** + conditionalbreakpointdialog.h + ------------------ + begin : 2004-04-05 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 CONDITIONALBREAKPOINTDIALOG_H +#define CONDITIONALBREAKPOINTDIALOG_H + +#include "conditionalbreakpointdialogs.h" +#include "debuggerbreakpoint.h" + +class ConditionalBreakpointDialog : public ConditionalBreakpointDialogS +{ + Q_OBJECT + + public: + enum Break + { + OnTrue = 0, + OnChange + }; + + ConditionalBreakpointDialog(const QString& expression, const QString& inFile, const QString& inClass, const QString& inFunction); + ~ConditionalBreakpointDialog(); + +// QString expression(); +// QString inFile(); +// QString inClass(); +// QString inFunction(); +// DebuggerBreakpoint::Types type(); + + DebuggerBreakpoint *breakpoint(); + + public slots: + void slotExpressionChanged(); + void slotClearFile(); + void slotClearClass(); + void slotClearFunction(); + + private: + +}; + +#endif // CONDITIONALBREAKPOINTDIALOG_H + diff --git a/quanta/components/debugger/conditionalbreakpointdialogs.ui b/quanta/components/debugger/conditionalbreakpointdialogs.ui new file mode 100644 index 00000000..8e4a1bf2 --- /dev/null +++ b/quanta/components/debugger/conditionalbreakpointdialogs.ui @@ -0,0 +1,329 @@ + +ConditionalBreakpointDialogS + + + ConditionalBreakpointDialogS + + + + 0 + 0 + 564 + 432 + + + + Add Conditional Breakpoint + + + true + + + + unnamed + + + + lblExpression + + + + 4 + 5 + 0 + 0 + + + + Expression: + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + + + + true + + + + + + + buttonGroup1 + + + Break When + + + + unnamed + + + + radioOnTrue + + + When expression is true + + + + + radioOnChange + + + When expression changes + + + true + + + + + + + spacer8 + + + Vertical + + + Expanding + + + + 30 + 20 + + + + + + comboExpression + + + true + + + + + ledWarning + + + + 22 + 22 + + + + + 22 + 22 + + + + Off + + + + 255 + 0 + 0 + + + + Lit when a finding a single equal sign in expression (common error) + + + + + groupBox10 + + + Only Break In + + + + unnamed + + + + lblValue + + + + 5 + 5 + 0 + 0 + + + + File: + + + AlignVCenter + + + + + lblValue_2 + + + + 5 + 5 + 0 + 0 + + + + Objects of class: + + + AlignVCenter + + + + + lblValue_3 + + + + 5 + 5 + 0 + 0 + + + + Function: + + + AlignVCenter + + + + + lineFile + + + + + lineFunction + + + + + buttonClearFile + + + x + + + + + buttonClearFunction + + + x + + + + + buttonClearClass + + + x + + + + + lineClass + + + + + + + + + + + buttonOk + clicked() + ConditionalBreakpointDialogS + accept() + + + buttonCancel + clicked() + ConditionalBreakpointDialogS + reject() + + + + buttonOk + buttonCancel + + + + kcombobox.h + klineedit.h + kled.h + + 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, + * + * 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 +#include +#include +#include + +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, + * + * 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 +#include + +#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 + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 + +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 + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 @@ + +DBGpSettingsS + + + DBGpSettingsS + + + + 0 + 0 + 569 + 467 + + + + DBGp Settings + + + true + + + + unnamed + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + Ca&ncel + + + true + + + + + + + tabWidget2 + + + true + + + + 5 + 5 + 1 + 1 + + + + + tab + + + &General + + + + unnamed + + + + groupBox2 + + + Connection Settings + + + + unnamed + + + + lblDebuggerServerListenPort + + + + 5 + 5 + 1 + 0 + + + + Listen port: + + + + + lineServerListenPort + + + + 7 + 0 + 4 + 0 + + + + + + lblRequest + + + + 5 + 5 + 1 + 0 + + + + Request URL: + + + + + lineStartSession + + + + 7 + 0 + 4 + 0 + + + + See "What's This?" for available variables + + + %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 + + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 21 + 40 + + + + + + groupBox1 + + + Directory Mapping + + + + unnamed + + + + lineServerBasedir + + + + 7 + 0 + 4 + 0 + + + + + + lblDebuggerServerBasedir + + + + 5 + 5 + 1 + 0 + + + + Server basedir: + + + + + lineLocalBasedir + + + + 7 + 0 + 4 + 0 + + + + + + + + + checkLocalProject + + + + 1 + 0 + 4 + 0 + + + + + + + + + + + + lblDebuggerLocalBasedir + + + + 5 + 5 + 1 + 0 + + + + Local basedir: + + + + + lblLocalProject + + + + 5 + 5 + 1 + 0 + + + + Local project: + + + + + + + groupBox3_2 + + + Profiling + + + + unnamed + + + + lineProfilerFilename + + + + 7 + 0 + 4 + 0 + + + + See "What's This?" for available variables + + + Path to the profiler output +%a - Appid as returned from the debugger +%c - CRC32 of the initial filepath + + + + + lblRequest_2 + + + + 5 + 5 + 1 + 0 + + + + Profiler output: + + + + + lblLocalProject_2 + + + + 5 + 5 + 1 + 0 + + + + Map profiler output: + + + + + checkProfilerMapFilename + + + + 1 + 0 + 4 + 0 + + + + + + + + + + If this checkbox is checked, the profiler output filename will be mapped using the basedirs just like the remote script files. + + + + + lblLocalProject_2_2 + + + + 5 + 5 + 1 + 0 + + + + Open automatically: + + + + + checkProfilerAutoOpen + + + + 1 + 0 + 4 + 0 + + + + + + + + + + If this checkbox is checked, the profiler output will be opened automatically once the session ends. + + + + + + + + + tab + + + Deb&ug Behavior + + + + unnamed + + + + groupBox4 + + + Error Handling + + + + unnamed + + + + checkBreakOnUserError + + + + 7 + 0 + 0 + 0 + + + + User errors + + + + + lblBreakOn + + + Break on: + + + AlignTop + + + + + checkBreakOnUserWarning + + + + 7 + 0 + 0 + 0 + + + + User warnings + + + + + checkBreakOnUserNotice + + + + 7 + 0 + 0 + 0 + + + + User notices + + + + + checkBreakOnNotice + + + + 7 + 0 + 0 + 0 + + + + Notices + + + + + checkBreakOnWarning + + + + 7 + 0 + 0 + 0 + + + + W&arnings + + + + + + + groupBox5 + + + Execution + + + + unnamed + + + + + Pause + + + image0 + + + + + Run + + + image1 + + + + comboDefaultExecutionState + + + + + lblDefaultExecutionMode + + + Default mode: + + + AlignVCenter + + + + + + + spacer4_3 + + + Vertical + + + Expanding + + + + 21 + 40 + + + + + + + + TabPage + + + &About + + + + unnamed + + + + textLabel1 + + + + 5 + 4 + 0 + 0 + + + + <h4>DBGp Plugin for Quanta +</h4> + + + + + textAbout + + + true + + + <html><head><meta name="qrichtext" content="1" /></head><body style="font-size:10pt;font-family:Bitstream Vera Sans"> +<p><span style="font-weight:600">About</span></p> +<p>DBGp is a debugger protocol defined by the developers of Xdebug. This plugin integrates debuggers that supports the DBGp protocol with Quanta. </p> +<p>In order to use this plugin for PHP debugging, you need to get a supporting debugger. Currently, only <a href="http://xdebug.org">Xdebug</a> is tested.</p> +<p>For more info about Xdebug, please visit the Xdebug website at <a href="http://xdebug.org">http://xdebug.org</a> </p> +<p><span style="font-weight:600">Technical Details</span></p> +<p>This version of the debugger supports version %PROTOCOLVERSION% of the DBGp protocol. </p> +</body></html> + + + + + + + + + + 89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff610000027f49444154388d7d93df4b53611cc69ff73de7ccb375dcdad46d2e3269036d21c4420a0b898484e82a08a2a02238a41741dd77e14dff4074d521efbae8a61b2f6a892062604e53117165e28f864dd73adb999e3cdb79cfe9c25a9c4dfa5e3e3ccfe7fdfee02538a412830b226075c3b662804d006b9567a5d4b4d2a7d77a494d5002c81370c20075797dc7fd157804139f77445846a14898fe9a67ead38f4aff661d2031b81006a1e3a16053c7ddcb3e5c3cc5c1ebe1000046c5c6a7af3a86c776b1b2bef3c3cdb2373ebcb83a5e052406e725103a9388473a1e5d13d1e8e60f9b0c1566e1655245727a3b2f19cb5d13c3b7bfff71da43a16073c7bd4b024667b56aa0b7cb0b009858fca75deff1622367357d59d58764597e481203332238317be74ad8d7798ca2ffacbf6a4eceaa00e0d0dea554ac6feb50deaabbc15f635d3c806e9728f9fc6e865cc172b49c2b9875633c1bf34033fca00db6a495a33d3c805840a2c8692638426a00953a40a9dc0000a0820842f9180f80941987cd3c0717ef04bc598ac02354f0b80642c8c1f6096cca03d66a51b791ce37d7bd06007a45a80b7304d8370db82c3d4379564a31a350a404a0f45086a3dc0283c83358fbea5e80a5e7e8b4d2a713a60f53238b36afe630c75b54c45b5487d6eed3408d2c04333712e437b608009c93937e2634a5cec79ba3019febbf1dfc2c9631b594cb448cd19b216e2d55ddda0579245a165adf9f89f94e76b649203517b16d1be9cd5dccafa8997065f241982c4f2a8aa2395cbdf75fb5eac289218fe7c8adf6904b3ada7870b242c9c07ab6bc67e8ea48c89c7a1ee2d6161545d1809adf0800b22cbbbe99a7231a17ed21948f11d894587a26c0d273417e630b405e5194f25fff6f6493fb9b9d8e82910000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000000ac49444154388ded94c10dc33008453f5637ea061ec24cd2293289976083ce440f6d2262b012da5b95277188133f7f4560e0e2039dfc4eb39e621f164097894455c30280debbdb539c0180881c25dcd15a73f2509c8588c0cc3b795a4c445b0170bf65e596158f821969f19af4e8b02bf1f7e2b3890bf09eb8f145660223b63eb6a267ad00e209b47d6cfb39143f824be42e825aab5b4f27b6f2993483db2c223a4aa3db6b0633ff14e80f79015c6574466adcb13f0000000049454e44ae426082 + + + + + buttonOk + clicked() + DBGpSettingsS + accept() + + + buttonCancel + clicked() + DBGpSettingsS + reject() + + + + tabWidget2 + lineLocalBasedir + lineServerBasedir + lineServerListenPort + checkBreakOnNotice + checkBreakOnWarning + checkBreakOnUserNotice + checkBreakOnUserWarning + checkBreakOnUserError + comboDefaultExecutionState + buttonOk + buttonCancel + + + slotLocalProjectToggled(bool) + checkLocalProject_toggled(bool) + slotLocalProjectToggle(bool) + + + + ktextbrowser.h + + 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, + * + * 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 +#include + +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, + * + * 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 +#include + +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 + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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")) + +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::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::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 ) +{ + /* + + + + + + + + + */ + +// // 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: + + + + + + + + + + + + + + */ + 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 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 + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include + +#include "debuggerclient.h" +#include "dbgpnetwork.h" + +typedef QValueList WatchList; +typedef QMap 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 diff --git a/quanta/components/debugger/debuggerbreakpoint.cpp b/quanta/components/debugger/debuggerbreakpoint.cpp new file mode 100644 index 00000000..ae8ed6cb --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpoint.cpp @@ -0,0 +1,181 @@ +/*************************************************************************** + debuggerbreakpoint.cpp + ---------------------- + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "debuggerbreakpoint.h" +#include + +DebuggerBreakpoint::DebuggerBreakpoint() + : m_line(1)//, m_state(0) +{} + +DebuggerBreakpoint::DebuggerBreakpoint( const DebuggerBreakpoint & bp ) +{ + m_conditionExpr = bp.condition(); + m_filePath = bp.filePath(); + m_class = bp.inClass(); + m_function = bp.inFunction(); + m_line = bp.line(); + m_state = bp.state(); + m_key = bp.key(); + m_type = bp.type(); +} + +DebuggerBreakpoint::DebuggerBreakpoint( const DebuggerBreakpoint * bp ) +{ + m_conditionExpr = bp->condition(); + m_filePath = bp->filePath(); + m_class = bp->inClass(); + m_function = bp->inFunction(); + m_line = bp->line(); + m_state = bp->state(); + m_key = bp->key(); + m_type = bp->type(); +} + + +DebuggerBreakpoint::DebuggerBreakpoint(const QString& filePath, int line) +{ + m_filePath = filePath; + m_line = line; + m_type = DebuggerBreakpoint::LineBreakpoint; + m_state = DebuggerBreakpoint::Undefined; +} + +DebuggerBreakpoint::DebuggerBreakpoint(const Types type, + const QString& conditionExpr, const QString& filePath, + const QString& inClass, const QString& inFunction) +{ + m_conditionExpr = conditionExpr; + m_filePath = filePath; + m_class = inClass; + m_function = inFunction; + m_line = 0; + m_type = type; + m_state = DebuggerBreakpoint::Undefined; +} + +DebuggerBreakpoint::~DebuggerBreakpoint() +{} + +void DebuggerBreakpoint::setFilePath(const QString& filePath) +{ + m_filePath = filePath; +} + +void DebuggerBreakpoint::setClass(const QString& newclass) +{ + m_class = newclass; +} + +void DebuggerBreakpoint::setFunction(const QString& function) +{ + m_function = function; +} + +void DebuggerBreakpoint::setLine(int line) +{ + m_line = line; +} + +void DebuggerBreakpoint::setCondition(const QString& expression) +{ + m_conditionExpr = expression; +} + +void DebuggerBreakpoint::setValue(const QString& value) +{ + m_value = value; +} + +void DebuggerBreakpoint::setState(int state) +{ + m_state = state; +} + +void DebuggerBreakpoint::setType(DebuggerBreakpoint::Types type ) +{ + m_type = type; +} + +void DebuggerBreakpoint::setKey(const QString& value) +{ + m_key = value; +} + +const QString& DebuggerBreakpoint::key() const +{ + return m_key; +} + +const QString& DebuggerBreakpoint::filePath() const +{ + return m_filePath; +} + +const QString& DebuggerBreakpoint::value() const +{ + return m_value; +} + +const QString& DebuggerBreakpoint::inClass() const +{ + return m_class; +} +const QString& DebuggerBreakpoint::inFunction() const +{ + return m_function; +} + +DebuggerBreakpoint::Types DebuggerBreakpoint::type() const +{ + return m_type; +} + +int DebuggerBreakpoint::line() const +{ + return m_line; +} + +const QString& DebuggerBreakpoint::condition() const +{ + return m_conditionExpr; +} + +int DebuggerBreakpoint::state() const +{ + return m_state; +} + +bool DebuggerBreakpoint::operator == (DebuggerBreakpoint bp) const +{ + // If they key matches + if(!m_key.isEmpty() && bp.key() == m_key) + return true; + + // Or everything else... + if(bp.filePath() == m_filePath + && (bp.line() == m_line || m_type != DebuggerBreakpoint::LineBreakpoint) + && bp.type() == m_type + && bp.inClass() == m_class + && bp.inFunction() == m_function + && bp.condition() == m_conditionExpr + ) + return true; + return false; + +} + diff --git a/quanta/components/debugger/debuggerbreakpoint.h b/quanta/components/debugger/debuggerbreakpoint.h new file mode 100644 index 00000000..46e0950d --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpoint.h @@ -0,0 +1,85 @@ +/*************************************************************************** + debuggerbreakpoint.h + -------------------- + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERBREAKPOINT_H +#define DEBUGGERBREAKPOINT_H +#include + + +class DebuggerBreakpoint +{ + public: + enum Types + { + LineBreakpoint = 0, + ConditionalTrue, + ConditionalChange + }; + + enum States + { + Undefined = 0, + Unfulfilled, + Fulfilled, + Error + }; + + DebuggerBreakpoint(); + DebuggerBreakpoint(const DebuggerBreakpoint& bp); + DebuggerBreakpoint(const DebuggerBreakpoint* bp); + DebuggerBreakpoint(const QString& filePath, int line); // Line BP + DebuggerBreakpoint(const DebuggerBreakpoint::Types type, // Any kind + const QString& conditionExpr, const QString& filePath = "", + const QString& inClass = "", const QString& inFunction = ""); + + virtual ~DebuggerBreakpoint(); + + virtual void setFunction(const QString& filePath); + virtual void setClass(const QString& filePath); + virtual void setFilePath(const QString& filePath); + virtual void setLine(int line); + virtual void setCondition(const QString& expression); + virtual void setState(int state); + virtual void setType(Types type); + virtual void setValue(const QString& value); + virtual void setKey(const QString& value); + + virtual const QString& filePath() const; + virtual const QString& inClass() const; + virtual const QString& inFunction() const; + virtual int line() const; + virtual const QString& condition() const; + virtual int state() const; + virtual DebuggerBreakpoint::Types type() const; + virtual const QString& value() const; + virtual const QString& key() const; + + bool operator == (DebuggerBreakpoint) const; + + protected: + QString m_filePath; + QString m_class; + QString m_function; + int m_line; + QString m_conditionExpr; + int m_state; + Types m_type; + QString m_value; + QString m_key; +}; + +#endif diff --git a/quanta/components/debugger/debuggerbreakpointlist.cpp b/quanta/components/debugger/debuggerbreakpointlist.cpp new file mode 100644 index 00000000..ba117965 --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpointlist.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + debuggerbreakpointlist.cpp + -------------------------- + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include + +#include "debuggerbreakpointlist.h" +#include "debuggerbreakpoint.h" +#include "debuggerclient.h" +#include "debuggermanager.h" +#include "debuggerui.h" +#include "resource.h" +#include "quanta.h" + +DebuggerBreakpointList::DebuggerBreakpointList() + : m_current(0) +{ + m_breakpointList = new BreakpointList_t(); +} + +DebuggerBreakpointList::~DebuggerBreakpointList() +{ + delete m_breakpointList; +} + +void DebuggerBreakpointList::add(DebuggerBreakpoint* bp) +{ + if(quantaApp->debugger()->UI()) + quantaApp->debugger()->UI()->showBreakpoint(*bp); + + m_breakpointList->push_front(bp); + if(bp->type() == DebuggerBreakpoint::LineBreakpoint) + quantaApp->debugger()->setMark(bp->filePath(), bp->line(), true, KTextEditor::MarkInterface::markType02); +} + +void DebuggerBreakpointList::remove(DebuggerBreakpoint* bp) +{ + BreakpointList_t::iterator it = find(*bp); + if(it == m_breakpointList->end()) + return; + +// DebuggerBreakpoint bp1(bp); + + if(*bp == (*bp)) + { + DebuggerBreakpoint* tmp; + + tmp = (*it); + // Remove it from the bp-list + if(quantaApp->debugger()->UI()) + quantaApp->debugger()->UI()->deleteBreakpoint(*bp); + + // Remove editor markpoint if there is one... + if(bp->type() == DebuggerBreakpoint::LineBreakpoint) + quantaApp->debugger()->setMark(bp->filePath(), bp->line(), false, KTextEditor::MarkInterface::markType02); + + it = m_breakpointList->remove(it); + delete tmp; + } +} + + + +DebuggerBreakpoint* DebuggerBreakpointList::retrieve(const QString& filePath, int line) +{ + BreakpointList_t::iterator it; + + for(it = m_breakpointList->begin(); it != m_breakpointList->end(); ++it) + { + if((filePath == (*it)->filePath()) && + line == (*it)->line()) + { + DebuggerBreakpoint* bp = new DebuggerBreakpoint(*it); + return bp; + } + } + return 0; +} + +void DebuggerBreakpointList::clear() +{ + BreakpointList_t::iterator it; + + for(it = m_breakpointList->begin(); it != m_breakpointList->end(); ++it) + { + + // Remove it from the bp-list + quantaApp->debugger()->UI()->deleteBreakpoint(*(*it)); + + // Remove editor markpoint if there is one... + quantaApp->debugger()->setMark((*it)->filePath(), (*it)->line(), false, KTextEditor::MarkInterface::markType02); + + if(quantaApp->debugger()->client()) + quantaApp->debugger()->client()->removeBreakpoint((*it)); + } + m_breakpointList->clear(); +} + +bool DebuggerBreakpointList::exists(DebuggerBreakpoint* bp) +{ + BreakpointList_t::iterator it = find(*bp); + if(it == m_breakpointList->end()) + return false; + + if(*bp == (*it)) + return true; + + return false; +} + + +BreakpointList_t::iterator DebuggerBreakpointList::find(const DebuggerBreakpoint &bp) +{ + BreakpointList_t::iterator it; + + for(it = m_breakpointList->begin(); it != m_breakpointList->end(); ++it) + { + if(bp == (*it)) + return it; + } + return m_breakpointList->end(); +} + +void DebuggerBreakpointList::rewind() +{ + m_current = 0; +} + +DebuggerBreakpoint* DebuggerBreakpointList::next() +{ + if(m_current == 0) + { + m_current = m_breakpointList->begin(); + } + else + { + ++m_current; + } + + if(m_current != m_breakpointList->end()) + { + return (*m_current); + } + else + { + return NULL; + } +} + +DebuggerBreakpoint * DebuggerBreakpointList::findDebuggerBreakpoint( const QString & key ) +{ + BreakpointList_t::iterator it; + for(it = m_breakpointList->begin(); it != m_breakpointList->end(); ++it) + { + if((*it)->key() == key) + { + DebuggerBreakpoint *bp = new DebuggerBreakpoint((*it)); + return bp; + } + } + return NULL; +} + +void DebuggerBreakpointList::updateBreakpointKey( const DebuggerBreakpoint & bp, const QString & newkey ) +{ + //DebuggerBreakpoint *bpp = new DebuggerBreakpoint(bp); + BreakpointList_t::iterator it; + it = find(bp); + if(it != m_breakpointList->end()) + { + (*it)->setKey(newkey); + } +} + +size_t DebuggerBreakpointList::count( ) +{ + return m_breakpointList->count(); +} diff --git a/quanta/components/debugger/debuggerbreakpointlist.h b/quanta/components/debugger/debuggerbreakpointlist.h new file mode 100644 index 00000000..4ca26a95 --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpointlist.h @@ -0,0 +1,58 @@ +/*************************************************************************** + debuggerbreakpointlist.h + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERBREAKPOINTLIST_H +#define DEBUGGERBREAKPOINTLIST_H + +#include +#include +#include + +class DebuggerBreakpoint; + typedef QValueList BreakpointList_t; + +class DebuggerBreakpointList +{ + + private: + BreakpointList_t* m_breakpointList; + BreakpointList_t::iterator m_current; + BreakpointList_t::iterator find(const DebuggerBreakpoint &bp); + + public: + DebuggerBreakpointList(); + ~DebuggerBreakpointList(); + + void add(DebuggerBreakpoint*); + void remove(DebuggerBreakpoint*); + //int remove(QString filePath, int line); + void clear(); + bool exists(DebuggerBreakpoint*); + //bool exists(QString filePath, int line); + + DebuggerBreakpoint* retrieve(const QString& filePath, int line); + + DebuggerBreakpoint * findDebuggerBreakpoint(const QString& key); + void updateBreakpointKey(const DebuggerBreakpoint &bp, const QString& newkey); + + size_t count(); + void rewind(); + DebuggerBreakpoint* next(); + +}; + +#endif diff --git a/quanta/components/debugger/debuggerbreakpointview.cpp b/quanta/components/debugger/debuggerbreakpointview.cpp new file mode 100644 index 00000000..2f7eea36 --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpointview.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + debuggerbreakpointview.cpp + -------------------------- + begin : 2004-06-27 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// KDE Includes +#include +#include +#include +#include +#include +#include + +// Quanta includes +#include "debuggerbreakpointview.h" +#include "debuggerbreakpoint.h" +#include "debuggerclient.h" +#include "debuggermanager.h" +#include "resource.h" +#include "quanta.h" + +namespace DebuggerBreakpointViewColumns +{ + // The enums must correspond to the order of the columns + // If you change here, change the column adding + enum Columns + { + Expression = 0, + File, + Class, + Function, + Line, + Value + }; +} + +DebuggerBreakpointViewItem::DebuggerBreakpointViewItem(DebuggerBreakpointView* view) + : KListViewItem(view) +{ +} + + +DebuggerBreakpointView::DebuggerBreakpointView(QWidget *parent, const char *name) + : KListView(parent, name) +{ + // If you change here, change the DebuggerBreakpointViewColumns enums above + addColumn(i18n("Expression")); + addColumn(i18n("File")); + addColumn(i18n("Class")); + addColumn(i18n("Function")); + addColumn(i18n("Line")); + addColumn(i18n("Value")); + + setResizeMode(QListView::AllColumns); + setAllColumnsShowFocus(true); + + m_breakpointPopup = new KPopupMenu(this); + m_breakpointPopup->insertItem(SmallIcon("editdelete"), i18n("&Remove"), this, SLOT(slotRemoveSelected())); + + connect(this, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & ) ), this, SLOT(slotBreakpointContextMenu(KListView *, QListViewItem *, const QPoint &))); + + // Jump to bp + connect(this, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int) ), this, SLOT(slotBreakpointDoubleClick( QListViewItem *, const QPoint &, int))); +} + + +DebuggerBreakpointView::~DebuggerBreakpointView() +{} + +void DebuggerBreakpointView::deleteBreakpoint(const DebuggerBreakpoint &bp) +{ + QListViewItem *item = findBreakpoint(bp, false); + if(item) + { + delete item; + } +} + + +void DebuggerBreakpointView::showBreakpoint(const DebuggerBreakpoint &bp) +{ + QListViewItem *item = findBreakpoint(bp); + if(!item) + return; + + if(bp.type() == DebuggerBreakpoint::LineBreakpoint) + { + item->setText(DebuggerBreakpointViewColumns::Value, ""); + item->setText(DebuggerBreakpointViewColumns::Line, QString::number(bp.line() + 1)); + } + else + { + item->setText(DebuggerBreakpointViewColumns::Value, bp.value()); + item->setText(DebuggerBreakpointViewColumns::Line, ""); + } + item->setText(DebuggerBreakpointViewColumns::File, bp.filePath()); + item->setText(DebuggerBreakpointViewColumns::Expression, bp.condition()); + item->setText(DebuggerBreakpointViewColumns::Class, bp.inClass()); + item->setText(DebuggerBreakpointViewColumns::Function, bp.inFunction()); +} + +QListViewItem* DebuggerBreakpointView::findBreakpoint(const DebuggerBreakpoint& bp, bool addIfNotExist) +{ + // Find the old item if its there + DebuggerBreakpointViewItem* item = dynamic_cast(firstChild()); + while(item) + { + if(item->breakpoint() == bp) + break; + + item = dynamic_cast(item->nextSibling()); + } + + // Insert a new item + if(!item && addIfNotExist) + { + item = new DebuggerBreakpointViewItem(this); + item->setBreakpoint(bp); + insertItem(item); + } + + return item; +} + + +DebuggerBreakpoint DebuggerBreakpointView::selected() +{ + DebuggerBreakpointViewItem* bpitem = dynamic_cast(selectedItem()); + + return bpitem->breakpoint(); +} + +void DebuggerBreakpointView::slotRemoveSelected() +{ + if(!selectedItem()) + return; + + DebuggerBreakpoint bp = selected(); + + emit removeBreakpoint(&bp); +} + +void DebuggerBreakpointView::keyPressEvent(QKeyEvent *e) +{ + if(e->key() != Qt::Key_Delete) + { + e->ignore(); + return; + } + + slotRemoveSelected(); +} + +void DebuggerBreakpointView::clear() +{ + KListView::clear(); +} + +void DebuggerBreakpointView::slotBreakpointDoubleClick(QListViewItem *item, const QPoint &, int ) +{ + if(!item) + return; + + DebuggerBreakpointViewItem* bpitem = dynamic_cast(item); + + if(!bpitem->breakpoint().filePath().isEmpty()) + { + quantaApp->gotoFileAndLine(bpitem->breakpoint().filePath(), bpitem->breakpoint().line(), 0); + } + +} + +void DebuggerBreakpointView::slotBreakpointContextMenu(KListView *, QListViewItem *, const QPoint& point) +{ + if(!selectedItem()) + return; + + m_breakpointPopup->exec(point); +} + +#include "debuggerbreakpointview.moc" diff --git a/quanta/components/debugger/debuggerbreakpointview.h b/quanta/components/debugger/debuggerbreakpointview.h new file mode 100644 index 00000000..1e3ca087 --- /dev/null +++ b/quanta/components/debugger/debuggerbreakpointview.h @@ -0,0 +1,74 @@ +/*************************************************************************** + Breakpoinlistview.h + ------------------------ + begin : 2004-06-27 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERBREAKPOINTVIEW_H +#define DEBUGGERBREAKPOINTVIEW_H + +#include +#include +#include +#include "debuggerbreakpoint.h" + +// class DebuggerBreakpoint; +class DebuggerBreakpointView; + +class DebuggerBreakpointViewItem : public KListViewItem +{ + private: + DebuggerBreakpoint m_breakpoint; + + public: + DebuggerBreakpointViewItem(); + DebuggerBreakpointViewItem(DebuggerBreakpointView* view); + + DebuggerBreakpoint breakpoint() const { return m_breakpoint; } + void setBreakpoint(const DebuggerBreakpoint &bp) { m_breakpoint = bp; } + +}; + +class DebuggerBreakpointView : public KListView +{ + Q_OBJECT + + public: + DebuggerBreakpointView(QWidget *parent = 0, const char *name = 0); + ~DebuggerBreakpointView(); + + void showBreakpoint(const DebuggerBreakpoint& bp); + void deleteBreakpoint(const DebuggerBreakpoint& bp); + + DebuggerBreakpoint selected(); + + void clear(); + + public slots: + void slotRemoveSelected(); + void slotBreakpointContextMenu(KListView *list, QListViewItem * item, const QPoint& point); + void slotBreakpointDoubleClick(QListViewItem *item, const QPoint &point, int column); + + signals: + void removeBreakpoint(DebuggerBreakpoint*); + + private: + void keyPressEvent(QKeyEvent *e); + QListViewItem* findBreakpoint(const DebuggerBreakpoint& bp, bool addIfNotExist = true); + + KPopupMenu *m_breakpointPopup; +}; + +#endif diff --git a/quanta/components/debugger/debuggermanager.cpp b/quanta/components/debugger/debuggermanager.cpp new file mode 100644 index 00000000..bbc6336c --- /dev/null +++ b/quanta/components/debugger/debuggermanager.cpp @@ -0,0 +1,850 @@ +/*************************************************************************** + phpdebuggerinterface.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + Based on work by Mathieu Kooiman + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "quanta.h" +#include "document.h" +#include "resource.h" +#include "project.h" +#include "quantadebuggerinterface.h" +#include "debuggerclient.h" +#include "debuggerbreakpoint.h" +#include "debuggerbreakpointlist.h" +#include "debuggermanager.h" +#include "messageoutput.h" +#include "viewmanager.h" +#include "quantaview.h" +#include "debuggerui.h" +#include "debuggervariable.h" +#include "pathmapper.h" +#include "variableslistview.h" +#include "conditionalbreakpointdialog.h" + +// dialogs +#include "debuggervariablesets.h" + +DebuggerManager::DebuggerManager(QObject *myparent) + : QObject(myparent) +{ + initActions(); + + // Create objects + m_breakpointList = new DebuggerBreakpointList(); + m_pathmapper = new PathMapper(this, "pathmapper"); + m_debuggerui = NULL; + m_interface = new QuantaDebuggerInterface(this, "interface"); + m_client = NULL; +} + +void DebuggerManager::slotNewProjectLoaded(const QString &projectname, const KURL &, const KURL &) +{ + if(m_client) + { + + disconnect(m_client, SIGNAL(updateStatus(DebuggerUI::DebuggerStatus)), m_debuggerui, SLOT(slotStatus(DebuggerUI::DebuggerStatus))); + + delete m_client; + m_client = NULL; + } + enableAction("*", false); + + // Remove all breakpoints + m_breakpointList->clear(); + + if(m_debuggerui) + { + delete m_debuggerui; + m_debuggerui = NULL; + } + //kdDebug(24002) << "DebuggerManager::slotNewProjectLoaded " << projectname << ", " << Project::ref()->debuggerClient << endl; + + // Load new client + if(!projectname.isEmpty()) + { + + KTrader::OfferList offers = KTrader::self()->query("Quanta/Debugger"); + KTrader::OfferList::ConstIterator iterDbg; + for(iterDbg = offers.begin(); iterDbg != offers.end(); ++iterDbg) + { + KService::Ptr service = *iterDbg; + if(Project::ref()->debuggerClient() == service->name()) + { + int errCode = 0; +//Workaround for dynamic_cast not working correctly on SUSE 10, gcc 4.0.2 +//The correct way should be a simple: +// m_client = KParts::ComponentFactory::createInstanceFromService(service, this, 0, QStringList(), &errCode); + QObject* obj = KParts::ComponentFactory::createInstanceFromService(service, this, 0, QStringList(), &errCode); + if (obj && obj->inherits("DebuggerClient")) + m_client = static_cast(obj); + + //kdDebug(24002) << service->name() << " (" << m_client << ")" << endl; + + if(!m_client) + { + emit hideSplash(); + KMessageBox::error(NULL, i18n("Unable to load the debugger plugin, error code %1 was returned: %2.").arg(errCode).arg(KLibLoader::self()->lastErrorMessage()), i18n("Debugger Error")); + } + break; + } + } + } + + // Tell client to load its settings + if (m_client) + { + QDomNode nodeThisDbg; + QDomDocument *dom = Project::ref()->sessionDom(); + QDomNode projectNode = dom->firstChild().firstChild(); + QDomNode nodeDbg = projectNode.namedItem("debuggers"); + if(nodeDbg.isNull()) + { + nodeDbg = dom->createElement("debuggers"); + projectNode.appendChild(nodeDbg); + } + + // Load this project's mapped paths + m_pathmapper->readConfig(); + + // Load this projects debugger's settings + nodeThisDbg = nodeDbg.namedItem(m_client->getName()); + if(nodeThisDbg.isNull()) + { + nodeThisDbg = dom->createElement(m_client->getName()); + nodeDbg.appendChild(nodeThisDbg); + } + + m_client->readConfig(nodeThisDbg); + + // recreate UI + m_debuggerui = new DebuggerUI(this, "debuggerui"); + connect(m_client, SIGNAL(updateStatus(DebuggerUI::DebuggerStatus)), m_debuggerui, SLOT(slotStatus(DebuggerUI::DebuggerStatus))); + + // Load saved breakpoints + if(Project::ref()->debuggerPersistentBreakpoints()) + { + QDomNode nodeBreakpoints = nodeDbg.namedItem("breakpoints"); + if(!nodeBreakpoints.isNull()) + { + QDomNode child = nodeBreakpoints.firstChild(); + while(!child.isNull()) + { + DebuggerBreakpoint* bp = new DebuggerBreakpoint(); + bp->setFilePath( child.attributes().namedItem("filepath").nodeValue()); + bp->setClass( child.attributes().namedItem("class").nodeValue()); + bp->setFunction( child.attributes().namedItem("function").nodeValue()); + bp->setCondition( child.attributes().namedItem("condition").nodeValue()); + bp->setLine( child.attributes().namedItem("line").nodeValue().toLong()); + if(child.attributes().namedItem("type").nodeValue() == "true") + bp->setType(DebuggerBreakpoint::ConditionalTrue); + else if(child.attributes().namedItem("type").nodeValue() == "change") + bp->setType(DebuggerBreakpoint::ConditionalChange); + else + bp->setType(DebuggerBreakpoint::LineBreakpoint); + + // Update client and ui + m_client->addBreakpoint(bp); + m_breakpointList->add(bp); + + // loop + child = child.nextSibling(); + } + } + } + + // Load saved Watches + if(Project::ref()->debuggerPersistentWatches()) + { + QDomNode nodeWatches = nodeDbg.namedItem("watches"); + if(!nodeWatches.isNull()) + { + QDomNode child = nodeWatches.firstChild(); + while(!child.isNull()) + { + QString watch = child.attributes().namedItem("name").nodeValue(); + DebuggerVariable *var = new DebuggerVariable(watch, "", DebuggerVariableTypes::Undefined); + m_debuggerui->addVariable(var); + m_client->addWatch(watch); + + child = child.nextSibling(); + } + } + } + + } + + initClientActions(); + + // Disable all debugactions that need a session (ie not breakpoints, etc) + slotDebugStartSession(); +} + +void DebuggerManager::initActions() +{ + KAction * newaction; + KActionCollection *ac = quantaApp->actionCollection(); + if(!ac) + return; + + //Debugger, breakpoint + newaction = new KAction(i18n("Toggle &Breakpoint"), SmallIcon("debug_breakpoint"), Qt::CTRL+Qt::SHIFT+Qt::Key_B, this, SLOT(toggleBreakpoint()), ac, "debug_breakpoints_toggle"); + newaction->setToolTip(i18n("Toggles a breakpoint at the current cursor location")); + + newaction = new KAction(i18n("&Clear Breakpoints"), 0, this, SLOT(clearBreakpoints()), ac, "debug_breakpoints_clear"); + newaction->setToolTip(i18n("Clears all breakpoints")); + + newaction = new KAction(i18n("Break When..."), SmallIcon("math_int"), 0, this, SLOT(slotConditionalBreakpoint()), ac, "debug_conditional_break"); + newaction->setToolTip(i18n("Adds a new conditional breakpoint")); + + newaction = new KAction(i18n("Break When..."), SmallIcon("math_int"), 0, this, SLOT(slotConditionalBreakpoint()), ac, "debug_conditional_breakdialog"); + newaction->setToolTip(i18n("Adds a new conditional breakpoint")); + + // Execution + newaction = new KAction(i18n("Send HTTP R&equest"), SmallIcon("debug_currentline"), 0, this, SLOT(slotDebugRequest()), ac, "debug_request"); + newaction->setToolTip(i18n("Initiate HTTP Request to the server with debugging activated")); + + newaction = new KAction(i18n("&Trace"), SmallIcon("debug_run"), 0, this, SLOT(slotDebugTrace()), ac, "debug_trace"); + newaction->setToolTip(i18n("Traces through the script. If a script is currently not being debugged, it will start in trace mode when started")); + + newaction = new KAction(i18n("&Run"), SmallIcon("debug_leap"), 0, this, SLOT(slotDebugRun()), ac, "debug_run"); + newaction->setToolTip(i18n("Runs the script. If a script is currently not being debugged, it will start in run mode when started")); + + newaction = new KAction(i18n("&Step"), SmallIcon("debug_stepover"), 0, this, SLOT(slotDebugStepOver()), ac, "debug_stepover"); + newaction->setToolTip(i18n("Executes the next line of execution, but does not step into functions or includes")); + + newaction = new KAction(i18n("Step &Into"), SmallIcon("debug_stepinto"), 0, this, SLOT(slotDebugStepInto()), ac, "debug_stepinto"); + newaction->setToolTip(i18n("Executes the next line of execution and steps into it if it is a function call or inclusion of a file")); + + newaction = new KAction(i18n("S&kip"), SmallIcon("debug_skip"), 0, this, SLOT(slotDebugSkip()), ac, "debug_skip"); + newaction->setToolTip(i18n("Skips the next command of execution and makes the next command the current one")); + + newaction = new KAction(i18n("Step &Out"), SmallIcon("debug_stepout"), 0, this, SLOT(slotDebugStepOut()), ac, "debug_stepout"); + newaction->setToolTip(i18n("Executes the rest of the commands in the current function/file and pauses when it is done (when it reaches a higher level in the backtrace)")); + + newaction = new KAction(i18n("&Pause"), SmallIcon("debug_pause"), 0, this, SLOT(slotDebugPause()), ac, "debug_pause"); + newaction->setToolTip(i18n("Pauses the scripts if it is running or tracing. If a script is currently not being debugged, it will start in paused mode when started")); + newaction = new KAction(i18n("Kill"), SmallIcon("debug_kill"), 0, this, SLOT(slotDebugKill()), ac, "debug_kill"); + newaction->setToolTip(i18n("Kills the currently running script")); + + newaction = new KAction(i18n("Start Session"), SmallIcon("debug_connect"), 0, this, SLOT(slotDebugStartSession()), ac, "debug_connect"); + newaction->setToolTip(i18n("Starts the debugger internally (Makes debugging possible)")); + + newaction = new KAction(i18n("End Session"), SmallIcon("debug_disconnect"), 0, this, SLOT(slotDebugEndSession()), ac, "debug_disconnect"); + newaction->setToolTip(i18n("Stops the debugger internally (debugging not longer possible)")); + + // Variables + newaction = new KAction(i18n("Watch Variable"), SmallIcon("math_brace"), 0, this, SLOT(slotAddWatch()), ac, "debug_addwatch"); + newaction->setToolTip(i18n("Adds a variable to the watch list")); + + newaction = new KAction(i18n("Watch Variable"), SmallIcon("math_brace"), 0, this, SLOT(slotAddWatch()), ac, "debug_addwatchdialog"); + newaction->setToolTip(i18n("Adds a variable to the watch list")); + + newaction = new KAction(i18n("Set Value of Variable"), SmallIcon("edit"), 0, this, SLOT(slotVariableSet()), ac, "debug_variable_set"); + newaction->setToolTip(i18n("Changes the value of a variable")); + + newaction = new KAction(i18n("Set Value of Variable"), SmallIcon("edit"), 0, this, SLOT(slotVariableSet()), ac, "debug_variable_setdialog"); + newaction->setToolTip(i18n("Changes the value of a variable")); + + newaction = new KAction(i18n("Open Profiler Output"), SmallIcon("launch"), 0, this, SLOT(slotProfilerOpen()), ac, "debug_profiler_open"); + newaction->setToolTip(i18n("Opens the profiler output file")); + + enableAction("*", false); + +} + +void DebuggerManager::initClientActions() +{ + enableAction("*", false); + + if(m_client) + { + // Get actioncollection and add appropriate actions depending on capabilities of the debugger + if(m_client->supports(DebuggerClientCapabilities::LineBreakpoints)) + enableAction("debug_breakpoints_toggle", true); + if(m_client->supports(DebuggerClientCapabilities::LineBreakpoints)) + enableAction("debug_breakpoints_clear", true); + } +} + +DebuggerManager::~DebuggerManager() +{ + delete m_breakpointList; + m_breakpointList = 0L; + + if(m_client) + { + + disconnect(m_client, SIGNAL(updateStatus(DebuggerUI::DebuggerStatus)), m_debuggerui, SLOT(slotStatus(DebuggerUI::DebuggerStatus))); + + delete m_client; + m_client = 0L; + } + + delete m_debuggerui; + m_debuggerui = 0L; + delete m_interface; + m_interface = 0L; + delete m_pathmapper; + m_pathmapper = 0L; +} + +void DebuggerManager::enableAction(const QString& action, bool enable) +{ + if(action == "*") + { + // Enable/Disable all session related actions + connect/disconnect + enableAction("debug_request", enable); + enableAction("debug_run", enable); + enableAction("debug_trace", enable); + enableAction("debug_pause", enable); + enableAction("debug_kill", enable); + enableAction("debug_stepover", enable); + enableAction("debug_stepinto", enable); + enableAction("debug_stepout", enable); + enableAction("debug_skip", enable); + + enableAction("debug_connect", enable); + enableAction("debug_disconnect", enable); + + enableAction("debug_breakpoints_toggle", enable); + enableAction("debug_breakpoints_clear", enable); + + enableAction("debug_profiler_open", enable); + + } + else + { + // The action may or may not exist, depending on capabilities of the debugger plugin + KActionCollection *ac = quantaApp->actionCollection(); + if(ac && ac->action(action)) + ac->action(action)->setEnabled(enable); + } +} + +void DebuggerManager::slotRemoveVariable(DebuggerVariable* var) +{ + if(!m_client) + return; + + m_client->removeWatch(var); + +} + +void DebuggerManager::slotRemoveBreakpoint(DebuggerBreakpoint* bp) +{ + if(!m_client) + return; + m_breakpointList->remove(bp); + m_client->removeBreakpoint(bp); + +} + + +void DebuggerManager::slotAddWatch() +{ + kdDebug(24002) << "DebuggerManager::slotAddWatch() " << endl; + if(!m_client) + return; + + + QString watch = KInputDialog::getText(i18n("Add Watch"), i18n("Specify variable to watch:"), quantaApp->popupWord); + quantaApp->popupWord = ""; + if(!watch.isEmpty()) + { + DebuggerVariable *var = new DebuggerVariable(watch, "", DebuggerVariableTypes::Undefined); + m_debuggerui->addVariable(var); + m_client->addWatch(watch); + } +} + +void DebuggerManager::slotVariableSet() +{ + kdDebug(24002) << "DebuggerManager::slotVariableSet(" << quantaApp->popupWord << ") " << endl; + if(!m_client) + return; + + + DebuggerVariableSetS dlg; + dlg.lineVariable->setText(quantaApp->popupWord); + quantaApp->popupWord = ""; + if(dlg.exec() == QDialog::Accepted) + { + DebuggerVariable var; + var.setName(dlg.lineVariable->text()); + var.setValue(dlg.lineValue->text()); + m_client->variableSetValue(var); + } +} + +void DebuggerManager::slotConditionalBreakpoint() +{ + QString file; + + kdDebug(24002) << "DebuggerManager::slotConditionalBreakpoint() " << quantaApp->popupWord << endl; + if(!m_client) + return; + + Document *w = ViewManager::ref()->activeDocument(); + if (w) + file = w->url().prettyURL(0, KURL::StripFileProtocol); + + ConditionalBreakpointDialog dlg(quantaApp->popupWord, file, "", ""); + quantaApp->popupWord = ""; + if(dlg.exec() == QDialog::Accepted) + { + DebuggerBreakpoint * bp = dlg.breakpoint(); + if(bp) + { + m_client->addBreakpoint(bp); + m_breakpointList->add(bp); + } + } +} + +void DebuggerManager::slotDebugStartSession() +{ + if(!m_client) + return; + + m_client->startSession(); +} + +void DebuggerManager::slotDebugEndSession() +{ + if(!m_client) + return; + + m_client->endSession(); +} + +void DebuggerManager::slotDebugRequest() +{ + if(!m_client) + return; + + m_client->request(); +} + +void DebuggerManager::slotDebugTrace() +{ + if(!m_client) + return; + + m_client->trace(); +} + +void DebuggerManager::slotDebugRun() +{ + if(!m_client) + return; + + m_client->run(); + +} +void DebuggerManager::slotDebugSkip() +{ + if(!m_client) + return; + + m_client->skip(); + +} +void DebuggerManager::slotDebugStepOver() +{ + if(!m_client) + return; + + m_client->stepOver(); + +} +void DebuggerManager::slotDebugStepInto() +{ + if(!m_client) + return; + + m_client->stepInto(); + +} +void DebuggerManager::slotDebugPause() +{ + if(!m_client) + return; + + m_client->pause(); + +} +void DebuggerManager::slotDebugKill() +{ + if(!m_client) + return; + + m_client->kill(); + +} +void DebuggerManager::slotDebugStepOut() +{ + if(!m_client) + return; + + m_client->stepOut(); + +} + +void DebuggerManager::slotProfilerOpen( ) +{ + if(!m_client) + return; + + m_client->profilerOpen(); +} + +// A new file was opened, tell the debugger so it can tell us about breakpoints etc +void DebuggerManager::fileOpened(const QString& file) +{ + + // Set breakpoint markers if we have a bp in the file + m_breakpointList->rewind(); + DebuggerBreakpoint* bp; + while((bp = m_breakpointList->next())) + { + if(bp->filePath() == file) + { + setMark(bp->filePath(), bp->line(), true, KTextEditor::MarkInterface::markType02); + } + } + + //lets keep the eye on toggling bp's through the editor margin + QuantaView *view = ViewManager::ref()->isOpened(KURL::fromPathOrURL(file)); + if (view) + { + ::Document* qdoc = view->document(); + if(qdoc) + { + connectBreakpointSignals(qdoc); + } + } + + // Also, if we have a debug-session, let the debugger know... + if(m_client) + m_client->fileOpened(file); +} + +// Check with editors if breakpoints changed and send all breakpoint (again) to client +void DebuggerManager::refreshBreakpoints() +{ + // Resend bps + m_breakpointList->rewind(); + DebuggerBreakpoint* bp; + while((bp = m_breakpointList->next())) + { + m_client->addBreakpoint(bp); + } + +} + + +// The debug server told us we have a breakpoint, mark it in the file +void DebuggerManager::haveBreakpoint (const QString& file, int line) +{ + setMark(file, line, true, KTextEditor::MarkInterface::markType02); +} + +// The debug server told us we DONT have a breakpoint, remove it +void DebuggerManager::havenoBreakpoint (const QString& file, int line) +{ + DebuggerBreakpoint* br = new DebuggerBreakpoint(file, line); + m_breakpointList->remove(br); + setMark(file, line, false, KTextEditor::MarkInterface::markType02); + m_breakpointList->remove(br); +} + +// New current line +bool DebuggerManager::setActiveLine (const QString& file, int line ) +{ + //Get local filename + QString filename = file; + + // Remove old active line mark + setMark(m_currentFile, m_currentLine, false, KTextEditor::MarkInterface::markType05); + + // Update vars with active line + m_currentFile = filename; + m_currentLine = line; + + // No new current position + if(filename.isEmpty() || quantaApp->previewVisible()) + return true; + + // Find new position in editor + if(ViewManager::ref()->isOpened(filename) || QExtFileInfo::exists(filename, true, 0L)) + quantaApp->gotoFileAndLine(filename, line, 0); + else + { + showStatus(i18n("Unable to open file %1, check your basedirs and mappings.").arg(filename), true); + } + + // Add new active line mark + setMark(filename, line, true, KTextEditor::MarkInterface::markType05); + return true; +} + +// Set/clear a mark in a document +void DebuggerManager::setMark(const QString& filename, long line, bool set, int mark) +{ + if((!filename.isEmpty()) && ViewManager::ref()->isOpened(filename)) + { + ::Document* qdoc = ViewManager::ref()->isOpened(filename)->document(); + if(qdoc) + { + disconnectBreakpointSignals(qdoc); + + KTextEditor::Document* doc = qdoc->doc(); + if(doc) + { + KTextEditor::MarkInterface *markIf = dynamic_cast(doc); + if(markIf) + { + if(set) + markIf->addMark(line, mark); + else + markIf->removeMark(line, mark); + } + } + connectBreakpointSignals(qdoc); + } + } +} + +void DebuggerManager::connectBreakpointSignals(Document* qdoc) +{ + connect(qdoc, SIGNAL(breakpointMarked(Document*, int)), + this, SLOT(slotBreakpointMarked(Document*, int))); + + connect(qdoc, SIGNAL(breakpointUnmarked(Document*, int)), + this, SLOT(slotBreakpointUnmarked(Document*, int))); +} + +void DebuggerManager::disconnectBreakpointSignals(Document* qdoc) +{ + disconnect(qdoc, SIGNAL(breakpointMarked(Document*, int)), + this, SLOT(slotBreakpointMarked(Document*, int))); + + disconnect(qdoc, SIGNAL(breakpointUnmarked(Document*, int)), + this, SLOT(slotBreakpointUnmarked(Document*, int))); +} + +// Show a status message and optionally put it on the log +bool DebuggerManager::showStatus(const QString& a_message, bool log) +{ + QString message = a_message; + quantaApp->slotStatusMsg(m_client->getName() + ": " + message); + + if(log) + { + if(!message.endsWith("\n")) + message.append("\n"); + quantaApp->messageOutput()->showMessage(m_client->getName() + ": " + message); + } + return true; +} + + +void DebuggerManager::toggleBreakpoint () +{ + Document *w = ViewManager::ref()->activeDocument(); + if (w) + { + uint line, col; + w->viewCursorIf->cursorPositionReal(&line, &col); + + DebuggerBreakpoint* br = m_breakpointList->retrieve(w->url().prettyURL(0, KURL::StripFileProtocol), line); + + if(!br) + { + DebuggerBreakpoint* br = new DebuggerBreakpoint(w->url().prettyURL(0, KURL::StripFileProtocol), line); + m_breakpointList->add(br); +// setMark(w->url().prettyURL(0, KURL::StripFileProtocol), br->line(), true, KTextEditor::MarkInterface::markType02); // FIXME Is this really needed? + if(m_client && m_client->isActive()) + { + DebuggerBreakpoint tmpbp = *br; + m_client->addBreakpoint(br); + + } + else + // Trigger pathmapper to make sure we have a valid translation... + m_pathmapper->mapLocalPathToServer(w->url().prettyURL(0, KURL::StripFileProtocol)); + } + else + { + m_breakpointList->remove(br); +// setMark(w->url().prettyURL(0, KURL::StripFileProtocol), br->line(), false, KTextEditor::MarkInterface::markType02); // FIXME Is this really needed? + + if(m_client && m_client->isActive()) + { + m_client->removeBreakpoint(br); + } + } + } +} +void DebuggerManager::clearBreakpoints () +{ + m_breakpointList->clear(); +} + +void DebuggerManager::slotBreakpointMarked(Document* qdoc, int line) +{ + DebuggerBreakpoint* br = new DebuggerBreakpoint(qdoc->url().prettyURL(0, KURL::StripFileProtocol), line); + + m_breakpointList->add(br); + if(m_client && m_client->isActive()) + { + m_client->addBreakpoint(br); + } +} + +void DebuggerManager::slotBreakpointUnmarked(Document* qdoc, int line) +{ + QString filePath = qdoc->url().prettyURL(0, KURL::StripFileProtocol); + + DebuggerBreakpoint* br = m_breakpointList->retrieve(filePath, line); + + if (br) + { + if(m_client && m_client->isActive()) + { + m_client->removeBreakpoint(br); + } + + m_breakpointList->remove(br); + } +} + +void DebuggerManager::updateBreakpointKey( const DebuggerBreakpoint & bp, const QString & newkey ) +{ + m_breakpointList->updateBreakpointKey(bp, newkey); + + // Update UI + m_debuggerui->deleteBreakpoint(bp); + DebuggerBreakpoint bpnew(bp); + bpnew.setKey(newkey); + m_debuggerui->showBreakpoint(bpnew); + +} + +DebuggerBreakpoint * DebuggerManager::findDebuggerBreakpoint( const QString & key ) +{ + return m_breakpointList->findDebuggerBreakpoint(key); +} + +void DebuggerManager::saveProperties( ) +{ + + if (m_client) + { + QDomDocument *dom = Project::ref()->sessionDom(); + QDomNode projectNode = dom->firstChild().firstChild(); + QDomNode nodeDbg = projectNode.namedItem("debuggers"); + if(nodeDbg.isNull()) + { + nodeDbg = dom->createElement("debuggers"); + projectNode.appendChild(nodeDbg); + } + + // Save breakpoints + if(Project::ref()->debuggerPersistentBreakpoints()) + { + // (Re)create breakpoints section + QDomNode nodeBreakpoints = nodeDbg.namedItem("breakpoints"); + if(!nodeBreakpoints.isNull()) + nodeBreakpoints.parentNode().removeChild(nodeBreakpoints); + + if(m_breakpointList->count() > 0) + { + nodeBreakpoints = dom->createElement("breakpoints"); + nodeDbg.appendChild(nodeBreakpoints); + + + // Loop breakpoints and save 'em + m_breakpointList->rewind(); + DebuggerBreakpoint* bp; + while((bp = m_breakpointList->next())) + { + QDomElement child = dom->createElement("breakpoint"); + child.setAttribute("filepath", bp->filePath()); + child.setAttribute("class", bp->inClass()); + child.setAttribute("function", bp->inFunction()); + child.setAttribute("condition", bp->condition()); + child.setAttribute("line", QString::number(bp->line())); + if(bp->type() == DebuggerBreakpoint::ConditionalTrue) + child.setAttribute("type", "true"); + else if(bp->type() == DebuggerBreakpoint::ConditionalChange) + child.setAttribute("type", "change"); + else + child.setAttribute("type", "line"); + + nodeBreakpoints.appendChild(child); + } + } + } + + // Save Watches + if(Project::ref()->debuggerPersistentWatches()) + { + // (Re)create watches section + QDomNode nodeWatches = nodeDbg.namedItem("watches"); + if(!nodeWatches.isNull()) + nodeWatches.parentNode().removeChild(nodeWatches); + + if(m_debuggerui->watches()->first()) + { + nodeWatches = dom->createElement("watches"); + nodeDbg.appendChild(nodeWatches); + + // Loop watches and save 'em + for( DebuggerVariable *v = m_debuggerui->watches()->first(); v; v = m_debuggerui->watches()->next()) + { + QDomElement child = dom->createElement("watch"); + child.setAttribute("name", v->name()); + + nodeWatches.appendChild(child); + } + } + } + } +} + +void DebuggerManager::slotHandleEvent( const QString & event, const QString &, const QString & ) +{ + if(event == "before_project_close") + saveProperties(); +} + + + + +#include "debuggermanager.moc" diff --git a/quanta/components/debugger/debuggermanager.h b/quanta/components/debugger/debuggermanager.h new file mode 100644 index 00000000..f7584bdf --- /dev/null +++ b/quanta/components/debugger/debuggermanager.h @@ -0,0 +1,128 @@ +/*************************************************************************** + phpdebuggerinterface.h + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + Based on work by Mathieu Kooiman + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 PHPDEBUGGERINTERFACE_H +#define PHPDEBUGGERINTERFACE_H + +#include +#include + +class DebuggerClient; +class QuantaDebuggerInterface; +class DebuggerBreakpointList; +class DebuggerUI; +class DebuggerVariable; +class DebuggerBreakpoint; +class PathMapper; +class Document; + +class DebuggerManager : public QObject +{ + Q_OBJECT + private: + // client + DebuggerClient *m_client; + QuantaDebuggerInterface * m_interface; + DebuggerBreakpointList *m_breakpointList; + DebuggerUI * m_debuggerui; + PathMapper * m_pathmapper; + + // Internal help functions + void initActions(); + void initClientActions(); + void saveProperties(); + + void connectBreakpointSignals(Document*); + void disconnectBreakpointSignals(Document*); + + QString m_currentFile; + long m_currentLine; + + public: + DebuggerManager(QObject *myparent); + ~DebuggerManager(); + + // Access to memebers + DebuggerUI * UI() { return m_debuggerui; }; + DebuggerClient * client() { return m_client; }; + PathMapper * Mapper() { return m_pathmapper; }; + + // Breakpoints + void haveBreakpoint (const QString& file, int line); + void havenoBreakpoint (const QString& file, int line); + void refreshBreakpoints(); +// DebuggerBreakpoint *newDebuggerBreakpoint(); + DebuggerBreakpoint * findDebuggerBreakpoint(const QString& key); + void updateBreakpointKey(const DebuggerBreakpoint &bp, const QString& newkey); + + // Public help functions + bool showStatus(const QString& message, bool log); + bool setActiveLine (const QString& file, int line); + void setMark(const QString& filename, long line, bool set, int mark); + + void enableAction(const QString& action, bool enable); + void fileOpened(const QString& file); + + bool hasClient() { return m_client != 0; }; + + public slots: + + // Execution control slots + void slotDebugRequest(); + void slotDebugRun(); + void slotDebugTrace(); + void slotDebugSkip(); + void slotDebugStepOver(); + void slotDebugStepInto(); + void slotDebugStepOut(); + void slotDebugPause(); + void slotDebugKill(); + + // Breakpoint + void toggleBreakpoint(); + void clearBreakpoints(); + void slotConditionalBreakpoint(); + void slotRemoveBreakpoint(DebuggerBreakpoint* bp); + + // Watches + void slotAddWatch(); + void slotRemoveVariable(DebuggerVariable* var); + void slotVariableSet(); + + // Connection related slots + void slotDebugStartSession(); + void slotDebugEndSession(); + + // Profiler + void slotProfilerOpen(); + + // Initiation + void slotNewProjectLoaded(const QString &, const KURL &, const KURL &); + + // Event handling + void slotHandleEvent(const QString &, const QString &, const QString &); + + private slots: + void slotBreakpointMarked(Document*, int); + void slotBreakpointUnmarked(Document*, int); + + signals: + void hideSplash(); +}; + +#endif + diff --git a/quanta/components/debugger/debuggerui.cpp b/quanta/components/debugger/debuggerui.cpp new file mode 100644 index 00000000..c290bd8a --- /dev/null +++ b/quanta/components/debugger/debuggerui.cpp @@ -0,0 +1,205 @@ +/*************************************************************************** + debuggerui.cpp + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "debuggerui.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "variableslistview.h" +#include "debuggerbreakpointview.h" +#include "backtracelistview.h" +#include "debuggervariable.h" + +#include "quantacommon.h" +#include "quanta.h" +#include "resource.h" +#include "whtmlpart.h" + +DebuggerUI::DebuggerUI(QObject *parent, const char *name) + : QObject(parent, name), m_variablesListView(0) +{ + + // Variable watch tree + m_variablesListView = new VariablesListView(quantaApp->getMainDockWidget(), "debuggerVariables"); + m_variablesListView->setIcon(SmallIcon("math_brace")); + m_variablesListView->setCaption(i18n("Variables")); + m_variableListViewTVA = quantaApp->addToolWindow(m_variablesListView, quantaApp->prevDockPosition(m_variablesListView, KDockWidget::DockLeft), quantaApp->getMainDockWidget()); + + // Breakpointlist + m_debuggerBreakpointView = new DebuggerBreakpointView(quantaApp->getMainDockWidget(), "debuggerBreakpoints"); + m_debuggerBreakpointView->setIcon(SmallIcon("debug_breakpoint")); + m_debuggerBreakpointView->setCaption(i18n("Breakpoints")); + m_debuggerBreakpointViewTVA = quantaApp->addToolWindow(m_debuggerBreakpointView, quantaApp->prevDockPosition(m_debuggerBreakpointView, KDockWidget::DockBottom), quantaApp->getMainDockWidget()); + + // Backtrace + m_backtraceListview = new BacktraceListview(quantaApp->getMainDockWidget(), "debuggerBacktrace"); + m_backtraceListview->setIcon(SmallIcon("player_playlist")); + m_backtraceListview->setCaption(i18n("Backtrace")); + m_backtraceListviewTVA = quantaApp->addToolWindow(m_backtraceListview, quantaApp->prevDockPosition(m_backtraceListview, KDockWidget::DockBottom), quantaApp->getMainDockWidget()); + + // Debug HTML preview + m_preview = new WHTMLPart(quantaApp, "debug_output", true); + //m_preview->view()->resize(0, 0); + m_preview->view()->setIcon(UserIcon("debug_run")); + m_preview->view()->setCaption(i18n("Debug Output")); + m_previewTVA = quantaApp->addToolWindow(m_preview->view(), quantaApp->prevDockPosition(m_preview->view(), KDockWidget::DockBottom), quantaApp->getMainDockWidget()); + connect(m_preview, SIGNAL(openFile(const KURL&, const QString&, bool)), quantaApp, SLOT(slotFileOpen(const KURL&, const QString&, bool))); + + // Show debugger toolbar + quantaApp->toolBar("debugger_toolbar")->show(); + + connect(m_variablesListView, SIGNAL(removeVariable(DebuggerVariable* )), parent, SLOT(slotRemoveVariable(DebuggerVariable* ))); + + connect(m_debuggerBreakpointView, SIGNAL(removeBreakpoint(DebuggerBreakpoint* )), parent, SLOT(slotRemoveBreakpoint(DebuggerBreakpoint* ))); + showMenu(); +} + +DebuggerUI::~DebuggerUI() +{ + hideMenu(); + quantaApp->toolBar("debugger_toolbar")->hide(); + + // Remove Variable tree + quantaApp->deleteToolWindow(m_variableListViewTVA); + m_variableListViewTVA = 0L; + + // Remove breakpointlist + quantaApp->deleteToolWindow(m_debuggerBreakpointViewTVA); + m_debuggerBreakpointViewTVA = 0L; + + // Remove backtrace + quantaApp->deleteToolWindow(m_backtraceListviewTVA); + m_backtraceListviewTVA = 0L; + + // Remove output + quantaApp->deleteToolWindow(m_previewTVA); + m_previewTVA = 0L; +} + +void DebuggerUI::showMenu() +{ + QPopupMenu* debuggerMenu = (QPopupMenu*)(quantaApp->guiFactory())->container("debugger_menu", quantaApp); + if(debuggerMenu) + { + KMenuBar *mb = quantaApp->menuBar(); + mb->activateItemAt(-1); //needed as insertItem might crash if a menu is activated + m_debuggerMenuID = mb->insertItem(i18n("Deb&ug"), debuggerMenu, -1, 5); + } + else + m_debuggerMenuID = 0; + + // Status indicator + quantaApp->statusBar()->insertFixedItem(i18n("Debugger Inactive"), IDS_STATUS_DEBUGGER); + +} + +void DebuggerUI::hideMenu() +{ + if(m_debuggerMenuID != 0) + { + KMenuBar *mb = quantaApp->menuBar(); + mb->activateItemAt(-1); //needed as removeItem might crash if a menu is activated + mb->removeItem(m_debuggerMenuID); + } + m_debuggerMenuID = 0; + + // Status indicator + quantaApp->statusBar()->removeItem(IDS_STATUS_DEBUGGER); + +} + +void DebuggerUI::addVariable(DebuggerVariable* var) +{ + m_variablesListView->addVariable(var); +} + +void DebuggerUI::showBreakpoint(const DebuggerBreakpoint &bp) +{ + m_debuggerBreakpointView->showBreakpoint(bp); +} +void DebuggerUI::deleteBreakpoint(const DebuggerBreakpoint &bp) +{ + m_debuggerBreakpointView->deleteBreakpoint(bp); +} + +void DebuggerUI::sendRequest(const KURL &url) +{ + m_preview->openURL(url); +} + +void DebuggerUI::slotStatus( DebuggerStatus status ) +{ + switch(status) + { + case NoSession: + quantaApp->statusBar()->changeItem(i18n("No session"), IDS_STATUS_DEBUGGER); + break; + + case AwaitingConnection: + quantaApp->statusBar()->changeItem(i18n("Waiting"), IDS_STATUS_DEBUGGER); + break; + + case Connected: + quantaApp->statusBar()->changeItem(i18n("Connected"), IDS_STATUS_DEBUGGER); + break; + + case Paused: + quantaApp->statusBar()->changeItem(i18n("Paused"), IDS_STATUS_DEBUGGER); + break; + + case Running: + quantaApp->statusBar()->changeItem(i18n("Running"), IDS_STATUS_DEBUGGER); + break; + + case Tracing: + quantaApp->statusBar()->changeItem(i18n("Tracing"), IDS_STATUS_DEBUGGER); + break; + + case HaltedOnError: + quantaApp->statusBar()->changeItem(i18n("On error"), IDS_STATUS_DEBUGGER); + break; + + case HaltedOnBreakpoint: + quantaApp->statusBar()->changeItem(i18n("On breakpoint"), IDS_STATUS_DEBUGGER); + break; + + default: + quantaApp->statusBar()->changeItem("", IDS_STATUS_DEBUGGER); + } +} + +void DebuggerUI::backtraceClear( ) +{ + if(m_backtraceListview) + m_backtraceListview->clear(); +} + +void DebuggerUI::backtraceShow( long level, BacktraceType type, const QString & filename, long line, const QString & func ) +{ + if(m_backtraceListview) + m_backtraceListview->backtraceShow(level, type, filename, line, func); +} + + +#include "debuggerui.moc" diff --git a/quanta/components/debugger/debuggerui.h b/quanta/components/debugger/debuggerui.h new file mode 100644 index 00000000..a86e4706 --- /dev/null +++ b/quanta/components/debugger/debuggerui.h @@ -0,0 +1,90 @@ +/*************************************************************************** + debuggerui.h + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERUI_H +#define DEBUGGERUI_H + +#include +#include +#include +#include "backtracelistview.h" + +class VariablesListView; +class DebuggerBreakpointView; +class BacktraceListview; +class DebuggerBreakpoint; +class DebuggerVariable; +class WHTMLPart; +class KURL; + +class DebuggerUI : public QObject +{ + Q_OBJECT + + public: + enum DebuggerStatus + { + NoSession = 0, + AwaitingConnection, + Connected, + Paused, + Running, + Tracing, + HaltedOnError, + HaltedOnBreakpoint + }; + + DebuggerUI(QObject *parent = 0, const char *name = 0); + ~DebuggerUI(); + + // Watches + void addVariable(DebuggerVariable* var); + void showBreakpoint(const DebuggerBreakpoint& bp); + void deleteBreakpoint(const DebuggerBreakpoint& bp); + void parsePHPVariables(const QString &); + void sendRequest(const KURL &url); + VariablesListView* watches() { return m_variablesListView; }; + + void showMenu(); + void hideMenu(); + + void backtraceClear(); + void backtraceShow(long level, BacktraceType type, const QString &filename, long line, const QString& func); + + private: + VariablesListView* m_variablesListView; + KMdiToolViewAccessor* m_variableListViewTVA; + KMdiToolViewAccessor* m_previewTVA; + + DebuggerBreakpointView* m_debuggerBreakpointView; + KMdiToolViewAccessor* m_debuggerBreakpointViewTVA; + + BacktraceListview* m_backtraceListview; + KMdiToolViewAccessor* m_backtraceListviewTVA; + + int m_debuggerMenuID; + + WHTMLPart *m_preview; + + public slots: + // Status indication + void slotStatus(DebuggerUI::DebuggerStatus status); + +}; + +#endif diff --git a/quanta/components/debugger/debuggervariable.cpp b/quanta/components/debugger/debuggervariable.cpp new file mode 100644 index 00000000..b6a4f76a --- /dev/null +++ b/quanta/components/debugger/debuggervariable.cpp @@ -0,0 +1,283 @@ +/*************************************************************************** + debuggervariable.cpp + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "debuggervariable.h" +#include +#include + +DebuggerVariable::DebuggerVariable() + : m_isReference(false) + , m_size(0) + , m_type(DebuggerVariableTypes::Undefined) + , m_item(NULL) +{} + +DebuggerVariable::DebuggerVariable(const QString& name) + : m_isReference(false) + , m_size(0) + , m_type(DebuggerVariableTypes::Undefined) + , m_item(NULL) +{ + m_name = name; +} + +DebuggerVariable::DebuggerVariable(const QString& name, const QString& value, int type) + : m_isReference(false) + , m_size(0) + , m_item(NULL) +{ + m_name = name; + m_value = value; + m_type = type; + if(type == DebuggerVariableTypes::String) + m_size = value.length(); +} + +DebuggerVariable::DebuggerVariable(const QString& name, const QString& value, int type, int size) + : m_isReference(false) + , m_item(NULL) +{ + m_name = name; + m_value = value; + m_type = type; + m_size = size; +} + +DebuggerVariable::DebuggerVariable(const QString& name, const ValueList_t& values, int type) + : m_isReference(false) + , m_item(NULL) +{ + m_name = name; + m_valueList = values; + m_type = type; + m_size = values.count(); +} + +DebuggerVariable::DebuggerVariable(DebuggerVariable* v, bool copyitem ) +{ + m_name = v->name(); + m_size = v->size(); + m_value = v->value(); + m_type = v->type(); + m_isReference = v->isReference(); + if(copyitem) + { + m_item = v->item(); + v->setItem(NULL); + } + else + m_item = NULL; + + // We cant just assign m_valuelist to v->values(), it would make a shallow copy... + for(DebuggerVariable * v2 = v->values().first(); v2; v2 = v->values().next()) + m_valueList.append(new DebuggerVariable(v2, copyitem)); +} + + +void DebuggerVariable::setName(const QString& name) +{ + m_name = name; +} +QString DebuggerVariable::name() const +{ + return m_name; +} +void DebuggerVariable::setValue(const QString& value) +{ + m_value = value; +} + +QString DebuggerVariable::value() const +{ + if(isScalar()) + return m_value; + else + return i18n("Non scalar value"); +} + +bool DebuggerVariable::isScalar() const +{ + switch(m_type) + { + case DebuggerVariableTypes::Reference: + case DebuggerVariableTypes::Resource: + case DebuggerVariableTypes::String: + case DebuggerVariableTypes::Integer: + case DebuggerVariableTypes::Float: + case DebuggerVariableTypes::Boolean: + case DebuggerVariableTypes::Undefined: + case DebuggerVariableTypes::Error: + return true; + } + return false; +} + +void DebuggerVariable::setValues(const ValueList_t& valueList) +{ + m_valueList = valueList; +} + +ValueList_t DebuggerVariable::values() const +{ + return m_valueList; +} + +void DebuggerVariable::setType(int type) +{ + m_type = type; +} + +int DebuggerVariable::type() const +{ + return m_type; +} + +const QString DebuggerVariable::typeName() const +{ + switch(m_type) + { + case DebuggerVariableTypes::Array: + return i18n("Array"); + case DebuggerVariableTypes::Object: + return i18n("Object"); + case DebuggerVariableTypes::Reference: + return i18n("Reference"); + case DebuggerVariableTypes::Resource: + return i18n("Resource"); + case DebuggerVariableTypes::String: + return i18n("String"); + case DebuggerVariableTypes::Integer: + return i18n("Integer"); + case DebuggerVariableTypes::Float: + return i18n("Float"); + case DebuggerVariableTypes::Boolean: + return i18n("Boolean"); + case DebuggerVariableTypes::Undefined: + return i18n("Undefined"); + case DebuggerVariableTypes::Error: + return i18n("Error"); + default: + return i18n("Unknown"); + } +} + + +void DebuggerVariable::setSize(long size) +{ + m_size = size; +} + +long DebuggerVariable::size() const +{ + return m_size; +} + +QString DebuggerVariable::sizeName() const +{ + switch(m_type) + { + case DebuggerVariableTypes::Reference: + case DebuggerVariableTypes::Resource: + case DebuggerVariableTypes::Integer: + case DebuggerVariableTypes::Float: + case DebuggerVariableTypes::Boolean: + case DebuggerVariableTypes::Undefined: + case DebuggerVariableTypes::Error: + return ""; + } + return QString::number(m_size); +} + +void DebuggerVariable::setReference(bool ref) +{ + m_isReference = ref; +} +bool DebuggerVariable::isReference() const +{ + return m_isReference; +} + + +DebuggerVariable::~DebuggerVariable() +{ + DebuggerVariable * v; + while((v = m_valueList.first())) + { + m_valueList.remove(v); + delete v; + } + // If this variable is shown in the treeview, remove it + if(m_item) + delete m_item; + +} + + +void DebuggerVariable::deleteChild( DebuggerVariable * child ) +{ + + for(DebuggerVariable *v = m_valueList.first(); v; v = m_valueList.next()) + { + if(v->name() == child->name()) + { + m_valueList.remove(v); + delete v; + return; + } + } +} + +DebuggerVariable* DebuggerVariable::findItem( QListViewItem * item, bool traverse ) +{ + if(item == m_item) + return this; + + if(!traverse) + return NULL; + + for(DebuggerVariable * v = m_valueList.first(); v; v = m_valueList.next()) + { + DebuggerVariable * v2 = v->findItem(item, true); + if(v2) + return v2; + } + return NULL; +} + +void DebuggerVariable::copy( DebuggerVariable * v, bool copychildren ) +{ + m_name = v->name(); + m_size = (v->isScalar() || copychildren ? v->size() : m_valueList.count()); + m_value = v->value(); + m_type = v->type(); + m_isReference = v->isReference(); + + // We cant just assign m_valuelist to v->values(), it would make a shallow copy... +// + if(copychildren) + { + m_valueList.clear(); + for(DebuggerVariable * v2 = v->values().first(); v2; v2 = v->values().next()) + m_valueList.append(new DebuggerVariable(v2, true)); + } +} + +void DebuggerVariable::append( DebuggerVariable * v ) +{ + m_valueList.append(v); +} + diff --git a/quanta/components/debugger/debuggervariable.h b/quanta/components/debugger/debuggervariable.h new file mode 100644 index 00000000..3c83de4b --- /dev/null +++ b/quanta/components/debugger/debuggervariable.h @@ -0,0 +1,103 @@ +/*************************************************************************** + debuggervariable.h + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERVARIABLE_H +#define DEBUGGERVARIABLE_H + +#include +#include +#include + +namespace DebuggerVariableTypes +{ + + enum VarType { + Object, + Resource, + Reference, + Array, + String, + Integer, + Float, + Boolean, + Error, + Undefined + }; +} + +class DebuggerVariable; +typedef QPtrList ValueList_t; + +class DebuggerVariable +{ + public: + DebuggerVariable(); + DebuggerVariable(DebuggerVariable* var, bool copyitem = false); + DebuggerVariable(const QString& name); + DebuggerVariable(const QString& name, const QString& value, int type); + DebuggerVariable(const QString& name, const QString& value, int type, int size); + DebuggerVariable(const QString& name, const ValueList_t& values, int type); + virtual ~DebuggerVariable(); + + DebuggerVariable* findItem(QListViewItem *item, bool traverse = false); + + virtual void setName(const QString& name); + virtual QString name() const; + + virtual void setValue(const QString& value); + virtual QString value() const; + + virtual void setValues(const ValueList_t& valueList); + virtual ValueList_t values() const; + + virtual void setType(int type); + virtual int type() const; + virtual const QString typeName() const ; + virtual bool isScalar() const; + + virtual void setSize(long size); + virtual long size() const; + virtual QString sizeName() const; + + virtual void setReference(bool ref); + virtual bool isReference() const; + + virtual void touch() { m_touched = true;}; + virtual bool touched() const { return m_touched;}; + + virtual void setItem(KListViewItem* item) { m_item = item;}; + virtual KListViewItem* item() const{ return m_item;}; + + virtual void copy(DebuggerVariable* v, bool copychldren = true); + virtual void append(DebuggerVariable* v); + virtual void deleteChild(DebuggerVariable *child); + + + private: + ValueList_t m_valueList; + + QString m_name; + QString m_value; + bool m_isReference; + long m_size; + int m_type; + long m_touched; + + KListViewItem* m_item; +}; +#endif diff --git a/quanta/components/debugger/debuggervariablesets.ui b/quanta/components/debugger/debuggervariablesets.ui new file mode 100644 index 00000000..70440ff4 --- /dev/null +++ b/quanta/components/debugger/debuggervariablesets.ui @@ -0,0 +1,185 @@ + +DebuggerVariableSetS + + + DebuggerVariableSetS + + + + 0 + 0 + 414 + 129 + + + + Set Value of Variable + + + true + + + + unnamed + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + + + + true + + + + + + + lineVariable + + + + + + + + lblVariable + + + + 5 + 5 + 0 + 0 + + + + Variable: + + + + + lblValue + + + + 5 + 5 + 0 + 0 + + + + New value: + + + AlignTop + + + + + spacer8 + + + Vertical + + + Expanding + + + + 30 + 20 + + + + + + lineValue + + + + 7 + 7 + 0 + 0 + + + + + + + + buttonOk + clicked() + DebuggerVariableSetS + accept() + + + buttonCancel + clicked() + DebuggerVariableSetS + reject() + + + + lineVariable + lineValue + buttonOk + buttonCancel + + + diff --git a/quanta/components/debugger/gubed/Makefile.am b/quanta/components/debugger/gubed/Makefile.am new file mode 100644 index 00000000..755a7409 --- /dev/null +++ b/quanta/components/debugger/gubed/Makefile.am @@ -0,0 +1,18 @@ +METASOURCES = AUTO + +kde_module_LTLIBRARIES = quantadebuggergubed.la + +quantadebuggergubed_la_SOURCES = gubedsettingss.ui quantadebuggergubed.cpp gubedsettings.cpp +quantadebuggergubed_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +quantadebuggergubed_la_LIBADD = ../interfaces/libdebuggerinterface.la $(LIB_KPARTS) +kde_services_DATA = quantadebuggergubed.desktop + +INCLUDES = -I$(top_srcdir)/quanta/components/debugger \ + -I$(top_srcdir)/quanta/components/debugger/interfaces \ + -I$(top_srcdir)/quanta/components/debugger/gubed \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/quanta/utility \ + $(all_includes) + + +noinst_HEADERS = gubedsettings.h diff --git a/quanta/components/debugger/gubed/gubedsettings.cpp b/quanta/components/debugger/gubed/gubedsettings.cpp new file mode 100644 index 00000000..f728d884 --- /dev/null +++ b/quanta/components/debugger/gubed/gubedsettings.cpp @@ -0,0 +1,41 @@ +/*************************************************************************** + gubedsettings.cpp + ------------------- + begin : 2004-04-05 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "gubedsettings.h" +#include + +GubedSettings::GubedSettings(const QString &protocolversion) + : GubedSettingsS(0, "GubedSettings", false, 0) +{ + textAbout->setText(textAbout->text().replace("%PROTOCOLVERSION%", protocolversion)); +} + +GubedSettings::~GubedSettings() +{ +} + +void GubedSettings::slotUseProxyToggle( bool useproxy) +{ + lineServerHost->setEnabled(useproxy); + lineServerPort->setEnabled(useproxy); + lineServerListenPort->setEnabled(!useproxy); +} + + +#include "gubedsettings.moc" + diff --git a/quanta/components/debugger/gubed/gubedsettings.h b/quanta/components/debugger/gubed/gubedsettings.h new file mode 100644 index 00000000..dc070f32 --- /dev/null +++ b/quanta/components/debugger/gubed/gubedsettings.h @@ -0,0 +1,36 @@ +/*************************************************************************** + gubedsettings.h + ------------------- + begin : 2004-04-05 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 GUBEDSETTINGS_H +#define GUBEDSETTINGS_H + +#include "gubedsettingss.h" + +class GubedSettings : public GubedSettingsS +{ + Q_OBJECT + + public slots: + virtual void slotUseProxyToggle( bool useproxy); + + public: + GubedSettings(const QString &protocolversion); + ~GubedSettings(); + +}; + +#endif + diff --git a/quanta/components/debugger/gubed/gubedsettingss.ui b/quanta/components/debugger/gubed/gubedsettingss.ui new file mode 100644 index 00000000..12125c93 --- /dev/null +++ b/quanta/components/debugger/gubed/gubedsettingss.ui @@ -0,0 +1,762 @@ + +GubedSettingsS + + + GubedSettingsS + + + + 0 + 0 + 659 + 527 + + + + Gubed Settings + + + true + + + + unnamed + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + Ca&ncel + + + true + + + + + + + tabWidget2 + + + + 5 + 5 + 1 + 1 + + + + + tab + + + &General + + + + unnamed + + + + spacer4 + + + Vertical + + + Expanding + + + + 21 + 40 + + + + + + groupBox1 + + + Directory Mapping + + + + unnamed + + + + lblDebuggerServerBasedir + + + + 5 + 5 + 0 + 0 + + + + Server basedir: + + + + + lblDebuggerLocalBasedir + + + + 5 + 5 + 0 + 0 + + + + Local basedir: + + + + + lineServerBasedir + + + + + lineLocalBasedir + + + + + + + + + + groupBox2 + + + Connection Settings + + + + unnamed + + + + lineServerListenPort + + + + 5 + 0 + 0 + 0 + + + + + + lineServerPort + + + false + + + + 5 + 0 + 0 + 0 + + + + + + lineServerHost + + + false + + + + + checkUseProxy + + + + + + + + lblDebuggerUseProxe + + + + 5 + 5 + 0 + 0 + + + + Use proxy + + + + + lblDebuggerServerHost + + + + 5 + 5 + 0 + 0 + + + + Proxy host: + + + + + lblDebuggerServerPort + + + + 5 + 5 + 0 + 0 + + + + Proxy port: + + + + + lblDebuggerServerListenPort + + + + 5 + 5 + 0 + 0 + + + + Listen port: + + + + + + + groupBox3 + + + Mode + + + + unnamed + + + + lineStartSession + + + See "What's This?" for available variables + + + %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 + + + + + optAddInclude + + + false + + + &Add include + + + + + optStartSession + + + Start session: + + + true + + + + + + + + + tab + + + Deb&ug Behavior + + + + unnamed + + + + groupBox4 + + + Error Handling + + + + unnamed + + + + checkBreakOnUserError + + + + 7 + 0 + 0 + 0 + + + + User errors + + + + + lblBreakOn + + + Break on: + + + AlignTop + + + + + checkBreakOnUserWarning + + + + 7 + 0 + 0 + 0 + + + + User warnings + + + + + checkBreakOnUserNotice + + + + 7 + 0 + 0 + 0 + + + + User notices + + + + + checkBreakOnNotice + + + + 7 + 0 + 0 + 0 + + + + Notices + + + + + checkBreakOnWarning + + + + 7 + 0 + 0 + 0 + + + + W&arnings + + + + + + + spacer4_3 + + + Vertical + + + Expanding + + + + 21 + 50 + + + + + + groupBox5 + + + Execution + + + + unnamed + + + + lblDelayFast + + + + 4 + 5 + 0 + 0 + + + + + 9 + + + + Fast + + + + + sliderDisplayDelay + + + + 0 + 27 + + + + 200 + + + Horizontal + + + Below + + + + + lblDelaySlow + + + + 4 + 5 + 0 + 0 + + + + + 9 + + + + Slow + + + AlignVCenter|AlignRight + + + + + + Pause + + + image0 + + + + + Trace + + + image1 + + + + + Run + + + image2 + + + + comboDefaultExecutionState + + + + + lblDefaultExecutionMode + + + Default mode: + + + AlignVCenter + + + + + lblDisplayDelay + + + Run speed: + + + AlignVCenter + + + + + + + + + TabPage + + + A&bout + + + + unnamed + + + + textLabel1 + + + + 5 + 4 + 0 + 0 + + + + <h4>Gubed PHP Debugger Plugin for Quanta +</h4> + + + + + pixmapLabel1 + + + + 0 + 0 + 0 + 0 + + + + image3 + + + false + + + AlignCenter + + + + + textAbout + + + true + + + <html><head><meta name="qrichtext" content="1" /></head><body style="font-size:10pt;font-family:Bitstream Vera Sans"> +<p><span style="font-weight:600">About</span></p> +<p>Gubed is a PHP debugger available for free through GPL. This plugin integrates Gubed with Quanta. </p> +<p>In order to use this plugin for PHP debugging, you need to get the Quanta package from the Gubed project page, <a href="http://sourceforge.net/projects/gubed">http://sourceforge.net/projects/gubed</a>, at SourceForge </p> +<p>For more info about Gubed, please visit the Gubed website at <a href="http://gubed.sf.net">http://gubed.sf.net</a> </p> +<p><span style="font-weight:600">Technical Details</span></p> +<p>This version of the debugger supports the %PROTOCOLVERSION% version of the Gubed protocol. </p> +</body></html> + + + + + + + + + + 89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff610000027f49444154388d7d93df4b53611cc69ff73de7ccb375dcdad46d2e3269036d21c4420a0b898484e82a08a2a02238a41741dd77e14dff4074d521efbae8a61b2f6a892062604e53117165e28f864dd73adb999e3cdb79cfe9c25a9c4dfa5e3e3ccfe7fdfee02538a412830b226075c3b662804d006b9567a5d4b4d2a7d77a494d5002c81370c20075797dc7fd157804139f77445846a14898fe9a67ead38f4aff661d2031b81006a1e3a16053c7ddcb3e5c3cc5c1ebe1000046c5c6a7af3a86c776b1b2bef3c3cdb2373ebcb83a5e052406e725103a9388473a1e5d13d1e8e60f9b0c1566e1655245727a3b2f19cb5d13c3b7bfff71da43a16073c7bd4b024667b56aa0b7cb0b009858fca75deff1622367357d59d58764597e481203332238317be74ad8d7798ca2ffacbf6a4eceaa00e0d0dea554ac6feb50deaabbc15f635d3c806e9728f9fc6e865cc172b49c2b9875633c1bf34033fca00db6a495a33d3c805840a2c8692638426a00953a40a9dc0000a0820842f9180f80941987cd3c0717ef04bc598ac02354f0b80642c8c1f6096cca03d66a51b791ce37d7bd06007a45a80b7304d8370db82c3d4379564a31a350a404a0f45086a3dc0283c83358fbea5e80a5e7e8b4d2a713a60f53238b36afe630c75b54c45b5487d6eed3408d2c04333712e437b608009c93937e2634a5cec79ba3019febbf1dfc2c9631b594cb448cd19b216e2d55ddda0579245a165adf9f89f94e76b649203517b16d1be9cd5dccafa8997065f241982c4f2a8aa2395cbdf75fb5eac289218fe7c8adf6904b3ada7870b242c9c07ab6bc67e8ea48c89c7a1ee2d6161545d1809adf0800b22cbbbe99a7231a17ed21948f11d894587a26c0d273417e630b405e5194f25fff6f6493fb9b9d8e82910000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000000c949444154388ded93db0d83300c45af5137ea06190226610a260943d8137426f707a33c0c49a4f6a7ea91f261149f5c2207f873409dfb74d43301c006e8d66856557701408cb1ea9d3c0933b71266ccf35cc95df1284484655932f9b09888ce05a0ba965bf12b045cddf995a824139becc99cd5656211c9928b48fd67a5d4634df631b38610e848af2202ab5df19d7ced9ff736c56c6b3a82aa7a5bf74aadd79acf65b5e13d9416da432a7e8c9e60f35b9c5a7d1b16b7e6d7f8c893f6e84a1c63c4beefdfcaf0ebbc010507b65c1e0ebcf80000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000000ac49444154388ded94c10dc33008453f5637ea061ec24cd2293289976083ce440f6d2262b012da5b95277188133f7f4560e0e2039dfc4eb39e621f164097894455c30280debbdb539c0180881c25dcd15a73f2509c8588c0cc3b795a4c445b0170bf65e596158f821969f19af4e8b02bf1f7e2b3890bf09eb8f145660223b63eb6a267ad00e209b47d6cfb39143f824be42e825aab5b4f27b6f2993483db2c223a4aa3db6b0633ff14e80f79015c6574466adcb13f0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af400000779494441545885b5566b6c54c715fe66ee6beededd8df7858dedc5181b87c501b2b20954e0d44a698df3a022a8addaa424229512f58168d52a951a5a4ad2a2d21f55da8aa6ed8f0ab595528ad434a452aa483c6a6a648bc486605b1830c602d65e83d7f6ee7dedde7ba73f1c6ffc0253851ce9fc9973bef9be3973667408e71cf7c39e6f6808d7aa6af2c1254bb6088a12bb383939f4565fdfdb1d0303dd77c389f783bca2a222f06a4dcdcf1f59ba744b2c1cae56348dfa54d53c75e5ca04804f57c02bab567dfe8fcb96fdf4b1d2d2cf4014411c07c8e711571435ca5862313cfd24e46b2391ea164d3bb891b1f5300cc0b2a6dcb6e127040151acf9d404fc301edffc7a34fab746e061d53044aeeb80ae835b16609a7800404010d6eddfbf9fdc7701d5d5d5be0d94ee7b08781886011806609a806d03f93ce03850008464397ce8d0a192fb2ae05b3535f17d9ef7c61724e9739a61487c62023c9b856b1828982690cf83e7f3a08e8387a251616c6c6ccdddf6fbbf9b30e179df7854559f22ba0e18060cd745976de3a4aea32049485a163657566289e761453008d7756b00fce7130b7876dd3aadceb6bffa4224b2376c9ac4721c9cb52cfcc034718173b8d389a914b49e1ebc9048e0f1ba3a445475755d5d9ddcdfdf9fff44021ee47ccbd668f4fb61cf23b02c9c721cbc66db38b7c047a63b0edee8e9c1bbd7afc3f5bcd2542aa50158500099fe09abaaaa986d5981e19191d19909cf3535b1e58ef3d88e48e4cd959406dc4c061de9349ebe7c19939e772fda6f88a2f862a150f8d742c162139aba1e7864d5aaaf555454046626c481af3cb17cf9c195a150804812061c07bf4ca7e7913f110a61776525d6068310c9ac9717f03cafec4eea8a15282b2bf3fd7af7ee5f8418db98ba79f3a8373969fa3cefd1e668f4e912d7257c7c1c855c0e3b4f9dc2dbc3c370a7719284ef9497e3bb555520aa0a5bd3d036398903bdbd18989c0493e561c375bf39323efe8f8504147ba0a5a5c5ba363232fcd4934f3664cbcaeadd4cc6f3150a3e55d70972394092f07e368b77d3e92239003c575e8ee7e371109f0f600c4c55b1251c46653c8ecba689db9c6b6f767545ef5481e2151c3e7cd83bd5dddd233246c2e1b01a0b87359fdf4f88a200aa8aebae8b83bdbd30dda97e9708c1b6a54bf1e3356b100e8741fc7e104d03340dc4e7c3ea8a0a6c5bbb161b57aef42f2929a9bd938059afe06c5fdf602e9f475014c1651928140045015c171f6432e81afdb83fab0301bc944840f0f9004a0159062409600c843178b28cace741515512d4b4ea7b121089c52e5e1a1e2e34545549b06d10d705cfe701cef1a70f3f442a972be67e3b9944d38a150021532e4920b20c5d149d6bba7ee92f1d1dbffd7b4f4f7b694949f5f0f8f81717bd02003872e48895b5ac61c8f2d4891405600c19cfc3e9c1c1625e5855b17df56ac88140b1f444d3005545c7c848fb5bfdfd7bcecbf2efaf8d8e76e735ed9d1b636357366cd8a02c5a81fafa7a7eb9aded82ab2871c1e7030070d7c5b18b1791b5ac2900a5f87a4303969495019cc32c1470cb30703d93c1c9c1c1ecabc78fbf03a01e40a320083200ce394f7677776f6c6a6a3addd6d6e6de51c0d48a3868791e3445013c0fa6aee3fc8d1bc57089cf87c6152bc05515574647f1873367d03b328281b131a47339e6baee5e00f2477b172b5c28148c73e7cef50348dd5580e1ba972c4a2d8d31064a713b9d465fea634c65248235757538d8de8ed7df7b0fb7757d265cfac8e719e7bcd1b6ed658b0ac864b3a39e24198431c601e89e875b1313c5786928047f2884df9d3c3997fcae4608494992746beefa3c01bae35cd33d6f027e7f988822263c0f59db2ec663b118fcb118a8380b5a007013408a103200a0c039df0960fa4fe684902ec7716cccb1790389c3792697cf67c118c0180a82006fc6cf2733063918c48bdbb7a32410e000fa28a5bf92657917636c672814da2d08c23f679003c030a5b40780b6a880f6f6f68c6e59d789aa82f8fd100301104128c65d4a612b0ad624127fddd6dc5cd3d9d959efbaeecbb66d1f374df3523e9f0fb9aefbd2ccea504aff0c20c5390fcde59b7705dddddd7a369b4d83524092e00f87a130568ca7c7c7f1dfdede2bff3e73e66713845c5bbf7efdac81c0308c6739e71b672cdd1404e1382124cf39f7cfe503e77c96b7b6b60a070e1cf89e61189ee7797c6868886fddba9503e000b8200819bfa6eddeb46993388d696969115455ada794be06c09bce05c029a53f8946a31a632c298ae297e6f2cd13c039c78e1d3b969d3871e2835c2ee7e57239be67cf1e3e63538710d24b29dd4b297d4610846728a53f22849c063039939c1072d5eff72febeaea0263ac5610845d73b9161cc98e1e3d3ad4dadadadadcdcfce5cd9b377f361e8fe7013c0ee0010002e73cc139dfbf1076da08211db22cbf9ccd66870080523ace399f3fa22f5481696f6c6c9492c96469229188504a7f03c09879c23b392164485194e6dada5a797aaff2f27246297da5b3b3932c7a050b793c1ef70b82b08b10d20720b700b10ee012a5745f2010a89a8bb76d1bc160b0f2c2850bb3041447b27bb14422215fbd7ab5d1719c759cf346ce790c534f7994527a561084f3b158ecfd63c78e19c964f29ef6fc1f4f14b29abe15e4b80000000049454e44ae426082 + + + + + buttonOk + clicked() + GubedSettingsS + accept() + + + buttonCancel + clicked() + GubedSettingsS + reject() + + + checkUseProxy + toggled(bool) + GubedSettingsS + slotUseProxyToggle(bool) + + + + tabWidget2 + lineLocalBasedir + lineServerBasedir + checkUseProxy + lineServerHost + lineServerPort + lineServerListenPort + optStartSession + lineStartSession + optAddInclude + checkBreakOnNotice + checkBreakOnWarning + checkBreakOnUserNotice + checkBreakOnUserWarning + checkBreakOnUserError + comboDefaultExecutionState + sliderDisplayDelay + buttonOk + buttonCancel + + + slotUseProxyToggle( bool ) + + + + ktextbrowser.h + + diff --git a/quanta/components/debugger/gubed/quantadebuggergubed.cpp b/quanta/components/debugger/gubed/quantadebuggergubed.cpp new file mode 100644 index 00000000..be703e73 --- /dev/null +++ b/quanta/components/debugger/gubed/quantadebuggergubed.cpp @@ -0,0 +1,1247 @@ +/*************************************************************************** + quantadebuggergubed.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "debuggerclient.h" +#include "quantadebuggergubed.h" +#include "debuggerinterface.h" +#include "debuggerbreakpoint.h" +#include "gubedsettings.h" +#include "debuggervariable.h" +#include "variableslistview.h" +#include "pathmapper.h" + +#include "debuggerui.h" + + +K_EXPORT_COMPONENT_FACTORY( quantadebuggergubed, + KGenericFactory("quantadebuggergubed")) + +const char QuantaDebuggerGubed::protocolversion[] = "0.0.12"; + +QuantaDebuggerGubed::QuantaDebuggerGubed (QObject *parent, const char* name, const QStringList&) + : DebuggerClient (parent, name) +{ + // Create a socket object and set up its signals + m_socket = NULL; + m_server = NULL; + m_errormask = 1794; + m_defaultExecutionState = Pause; + setExecutionState(m_defaultExecutionState); + + emit updateStatus(DebuggerUI::NoSession); + m_datalen = -1; +} + +QuantaDebuggerGubed::~QuantaDebuggerGubed () +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + + if(m_socket) + { + sendCommand("die", (char*)0L); + m_socket->flush(); + m_socket->close(); + delete m_socket; + m_socket = NULL; + } + if(m_server) + { + m_server->close(); + delete m_server; + m_server = NULL; + } + emit updateStatus(DebuggerUI::NoSession); +} + +// Try to make a connection to the gubed server +void QuantaDebuggerGubed::startSession() +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + + // Set default execution state + setExecutionState(m_defaultExecutionState); + + if(m_useproxy) + { + if(!m_socket) + { + m_socket = new KNetwork::KStreamSocket(m_serverHost, m_serverPort); + + 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())); + + m_socket->connect(); + debuggerInterface()->enableAction("debug_connect", true); + debuggerInterface()->enableAction("debug_disconnect", false); + debuggerInterface()->enableAction("debug_request", false); + kdDebug(24002) << k_funcinfo << ", proxy:" << m_serverHost << ", " << m_serverPort.toUInt() << endl; + + emit updateStatus(DebuggerUI::AwaitingConnection); + } + } + else + { + if(!m_server) + { + m_server = new KNetwork::KServerSocket(m_listenPort); + + m_server->setAddressReuseable(true); + connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept())); + + if(m_server->listen()) + { + emit updateStatus(DebuggerUI::AwaitingConnection); + debuggerInterface()->enableAction("debug_connect", false); + debuggerInterface()->enableAction("debug_disconnect", true); + debuggerInterface()->enableAction("debug_request", true); + } + else + { + emit updateStatus(DebuggerUI::NoSession); + delete m_server; + m_server = NULL; + debuggerInterface()->enableAction("debug_connect", true); + debuggerInterface()->enableAction("debug_disconnect", false); + debuggerInterface()->enableAction("debug_request", false); + } + } + } + +} + + +void QuantaDebuggerGubed::endSession() +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + + // Close the socket + if(m_socket) + { + sendCommand("die", (char*)0L); + m_socket->flush(); + m_socket->close(); + + m_socket->deleteLater(); + m_socket = NULL; + } + + // Close the server + if(m_server) + { + m_server->close(); + delete m_server; + m_server = NULL; + } + + // Fake a connection closed signal + slotConnectionClosed(); + debuggerInterface()->enableAction("debug_request", false); + debuggerInterface()->enableAction("debug_run", false); + debuggerInterface()->enableAction("debug_leap", false); + debuggerInterface()->enableAction("debug_pause", false); + + emit updateStatus(DebuggerUI::NoSession); +} + +// Change executionstate of the script +void QuantaDebuggerGubed::setExecutionState(State newstate) +{ + if(newstate == Pause) + { + sendCommand("pause", (char*)0L); + sendCommand("sendactiveline", (char*)0L); + if(isActive()) + emit updateStatus(DebuggerUI::Paused); + } + else if(newstate == Run) + { + if(m_executionState == Pause) + sendCommand("next", (char*)0L); + + sendCommand("run", (char*)0L); + if(isActive()) + emit updateStatus(DebuggerUI::Running); + } + else if(newstate == Trace) + { + if(m_executionState == Pause) + sendCommand("next", (char*)0L); + + sendCommand("trace", (char*)0L); + if(isActive()) + emit updateStatus(DebuggerUI::Tracing); + } + + m_executionState = newstate; + + if(debuggerInterface()) { + debuggerInterface()->enableAction("debug_trace", m_executionState != Trace); + debuggerInterface()->enableAction("debug_run", m_executionState != Run); + debuggerInterface()->enableAction("debug_pause", m_executionState != Pause); + } + + kdDebug(24002) << k_funcinfo << ", " << m_executionState << endl; + +} + +// Return capabilities of gubed +const uint QuantaDebuggerGubed::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::Trace: + case DebuggerClientCapabilities::Skip: + case DebuggerClientCapabilities::StepOut: + case DebuggerClientCapabilities::StepInto: + case DebuggerClientCapabilities::StepOver: + case DebuggerClientCapabilities::Watches: + case DebuggerClientCapabilities::VariableSetValue: + return true; + + default: + return false; + } +} + +// Socket errors +void QuantaDebuggerGubed::slotError(int) +{ + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + if(m_socket) + { + if(m_socket->error() == KNetwork::KSocketBase::RemotelyDisconnected) + { + slotConnectionClosed(); + return; + } + + if(m_socket->error()) + { + kdDebug(24002) << k_funcinfo << ", " << m_socket->errorString() << endl; + debuggerInterface()->showStatus(m_socket->errorString(), false); + } + } + + if(m_server && m_server->error()) + { + kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl; + debuggerInterface()->showStatus(m_server->errorString(), false); + } + +} + +// slotReadyAccept +void QuantaDebuggerGubed::slotReadyAccept() +{ + + kdDebug(24002) << k_funcinfo << ", m_server: " << m_server << ", m_socket" << m_socket << endl; + if(!m_socket) + { + + // Perhaps this shouldnt be disconnected - instead check if connections are available at disconnect? + 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" << endl; + m_socket->enableRead(true); + + 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(); + + emit updateStatus(DebuggerUI::Connected); + } + else + { + kdDebug(24002) << k_funcinfo << ", " << m_server->errorString() << endl; + } + } + +} + +// Connection established +void QuantaDebuggerGubed::slotConnected(const KNetwork::KResolverEntry &) +{ + emit updateStatus(DebuggerUI::Connected); + connected(); +} + +void QuantaDebuggerGubed::connected() +{ + kdDebug(24002) << k_funcinfo << endl; + + sendCommand("wait", (char*)0L); + debuggerInterface()->enableAction("debug_connect", false); + debuggerInterface()->enableAction("debug_disconnect", true); + debuggerInterface()->enableAction("debug_request", false); + + m_active = true; +} + +// Connectio closed +void QuantaDebuggerGubed::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->deleteLater(); + m_socket = NULL; + } + + if(m_server) + connect(m_server, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept())); + + // Disable all session related actions and enable connection action + debuggerInterface()->enableAction("*", false); + debuggerInterface()->enableAction("debug_connect", m_useproxy == 1 || m_server == NULL); + debuggerInterface()->enableAction("debug_disconnect", m_useproxy == 0 && m_server != NULL); + setExecutionState(m_defaultExecutionState); + + debuggerInterface()->enableAction("debug_request", true); + debuggerInterface()->enableAction("debug_breakpoints_toggle", true); + debuggerInterface()->enableAction("debug_breakpoints_clear", true); + + debuggerInterface()->setActiveLine("", 0); + + emit updateStatus(DebuggerUI::AwaitingConnection); + m_active = false; +} + +// Data from socket +void QuantaDebuggerGubed::slotReadyRead() +{ + + // Data from gubed + while(m_socket && (m_socket->bytesAvailable() > 0 || m_buffer.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 + 1]; + m_socket->readBlock(buffer, bytes); + buffer[bytes] = 0; + m_buffer += buffer; + delete[] buffer; + } + + while(1) + { + // If datalen == -1, we didnt read the command yet, otherwise were reading data. + if(m_datalen == -1) + { + bytes = m_buffer.find(";"); + if(bytes < 0) + break; + + data = m_buffer.left(bytes); + m_buffer.remove(0, bytes + 1); + bytes = data.find(":"); + m_command = data.left(bytes); + data.remove(0, bytes + 1); + m_datalen = data.toLong(); + } + if(m_datalen != -1 && (long)m_buffer.length() >= m_datalen) + { + data = m_buffer.left(m_datalen); + m_buffer.remove(0, m_datalen); + m_datalen = -1; + processCommand(data); + } + else + break; + } + } +} + +// Process a gubed command +void QuantaDebuggerGubed::processCommand(const QString& datas) +{ + kdDebug(24002) << k_funcinfo << ", " << m_command << " : " << datas.left(50) << endl; + StringMap args = parseArgs(datas); + + // See what command we got and act accordingly.. + if(m_command == "commandme") + { + //sendCommand("sendactiveline", (char*)0L); + debuggerInterface()->setActiveLine(mapServerPathToLocal(args["filename"]), args["line"].toLong()); + sendWatches(); + if(m_executionState == Trace) + sendCommand("wait", (char*)0L); + + if(m_executionState != Pause) + sendCommand("next", (char*)0L); + } + // Send run mode to script + else if(m_command == "getrunmode") + { + debuggingState(true); + sendCommand("setdisplaydelay", "newdelay", QString::number(m_displaydelay).ascii(), (char*)0L); + if(m_executionState == Pause) + sendCommand("pause", (char*)0L); + else if(m_executionState == Run) + sendCommand("run", (char*)0L); + else if(m_executionState == Trace) + sendCommand("trace", (char*)0L); + + sendCommand("seterrormask", "errormask", QString::number(m_errormask).ascii(), (char*)0L); + } + // Just some status info, display on status line + else if(m_command == "status") + { + long argcnt = args["args"].toLong(); + QString msg = i18n(args["message"]); // How will we get these messages throught to the translators? + for(int cnt = 1; cnt <= argcnt; cnt++) + msg.replace("%" + QString("%1").arg(cnt) + "%", args[QString("arg%1").arg(cnt)]); + + debuggerInterface()->showStatus(msg, false); + } + // New current line + else if(m_command == "setactiveline") + { + debuggerInterface()->setActiveLine(mapServerPathToLocal(args["filename"]), args["line"].toLong()); + } + // Script requests breakpointlist + else if(m_command == "sendbreakpoints") + { + sendBreakpoints(); + } + // Parsing failed + else if(m_command == "parsefailed") + { + debuggerInterface()->showStatus(i18n("Syntax or parse error in %1)").arg(args["filenme"]), true); + return; + } + // A debugging session is running + else if(m_command == "debuggingon") + { + debuggingState(true); + } + // No session is running + else if(m_command == "debuggingoff") + { + debuggingState(false); + } + // We stumbled upon an error + else if(m_command == "error") + { + // Put the line number first so double clicking will jump to the corrrect line + debuggerInterface()->showStatus(i18n("Error occurred: Line %1, Code %2 (%3) in %4").arg(args["line"]).arg(args["errnum"]).arg(args["errmsg"]).arg(args["filename"]), true); + + // Filter to get error code only and match it with out mask + long error = args["errnum"].toLong(); + if(m_errormask & error) + setExecutionState(Pause); + else if(m_executionState == Trace) + setExecutionState(Trace); + else if(m_executionState == Run) + setExecutionState(Run); + else + setExecutionState(Pause); + + emit updateStatus(DebuggerUI::HaltedOnError); + } + // We came across a hard coded breakpoint + else if(m_command == "forcebreak") + { + setExecutionState(Pause); + emit updateStatus(DebuggerUI::HaltedOnBreakpoint); + debuggerInterface()->showStatus(i18n("Breakpoint reached"), true); + } + // A conditional breakpoint was fulfilled + else if(m_command == "conditionalbreak") + { + setExecutionState(Pause); + emit updateStatus(DebuggerUI::HaltedOnBreakpoint); + debuggerInterface()->showStatus(i18n("Conditional breakpoint fulfilled"), true); + } + // There is a breakpoint set in this file/line + else if(m_command == "removebreakpoint") + { + debuggerInterface()->havenoBreakpoint(mapServerPathToLocal(args["filename"]), args["line"].toLong()); + } + // We're about to debug a file.. + else if(m_command == "initialize") + { + debuggerInterface()->showStatus(i18n("Established connection to %1").arg(args["filename"]), false); + sendCommand("sendprotocolversion", (char*)0L); + + debuggerInterface()->setActiveLine(mapServerPathToLocal(args["filename"]), 0); + sendCommand("havesource", (char*)0L); + debuggingState(true); + } + else if(m_command == "sendingwatches") + { + //debuggerInterface()->preWatchUpdate(); + } + // Show the contents of a watched variable + else if(m_command == "watch") + { + showWatch(args["variable"]); + } + // Show the contents of a variable + else if(m_command == "variable") + { + showWatch(args["variable"]); + } + // Show the contents of a variable + else if(m_command == "showcondition") + { + showCondition(args); + } + else if(m_command == "sentwatches") + { + //debuggerInterface()->postWatchUpdate(); + } + // Reached en of an include + else if(m_command == "end") + { + //debuggerInterface()->showStatus(i18n("At end of include %1").arg(data), true); + return; + } + // Check protocol version + else if(m_command == "protocolversion") + { + if(args["version"] != protocolversion) + { + debuggerInterface()->showStatus(i18n("The script being debugged does not communicate with the correct protocol version"), true); + sendCommand("die", (char*)0L); + } + return; + } + // Instructions we currently ignore + else if(m_command == "sourcesent" + || m_command == "addsourceline" + ) + {} + else + // Unimplemented command - log to debug output + kdDebug(24002) << "QuantaDebuggerGubed::slotReadyRead Unknown: " << m_command << ":" << datas << endl; +} + +// Turn on/off actions related to a debugging session +void QuantaDebuggerGubed::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 QuantaDebuggerGubed::sendBreakpoints() +{ + debuggerInterface()->refreshBreakpoints(); +} +void QuantaDebuggerGubed::sendWatches() +{ + for(QValueList::iterator it = m_watchlist.begin(); it != m_watchlist.end(); ++it) + sendCommand("getwatch", "variable", (*it).ascii(), (char*)0L); + sendCommand("sentwatches", "key", (char*)0L, (char*)0L); +} + +// Send a command to gubed +bool QuantaDebuggerGubed::sendCommand(const QString& command, StringMap args) +{ + + kdDebug(24002) << k_lineinfo << ", command " << command << " with data: " << phpSerialize(args) << endl; + if(!m_socket || m_socket->state() != KNetwork::KClientSocketBase::Connected) + return false; + + QString buffer = phpSerialize(args); + + buffer = QString(command + ":%1;" + buffer).arg(buffer.length()); + m_socket->writeBlock(buffer, buffer.length()); + return true; +} + +// Send a command to gubed +bool QuantaDebuggerGubed::sendCommand(const QString& command, char * firstarg, ...) +{ + StringMap ca; + char *next; + + va_list l_Arg; + va_start(l_Arg, firstarg); + + next = firstarg; + while(next) + { + ca[(QString)next] = (QString)va_arg(l_Arg, char*); +// kdDebug(24002) << k_lineinfo << " Added arg/valuepair " << next << ", " << ca[next].left(30) << endl; + next = va_arg(l_Arg, char*); + } + + va_end(l_Arg); + sendCommand(command, ca); + return true; +} + +// Return name of debugger +QString QuantaDebuggerGubed::getName() +{ + return "Gubed"; // no i18n on the name +} + +void QuantaDebuggerGubed::showWatch(const QString& data) +{ + debuggerInterface()->showVariable(parsePHPVariables(data)); +} + +// Send HTTP Request +void QuantaDebuggerGubed::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); +} + + +// Run boy, run (and show whats happening) +void QuantaDebuggerGubed::trace() +{ + setExecutionState(Trace); +} + +// Go as fast as possible and dont update current line or watches +void QuantaDebuggerGubed::run() +{ + setExecutionState(Run); +} + +// Step into function +void QuantaDebuggerGubed::stepInto() +{ + setExecutionState(Pause); + sendCommand("next", (char*)0L); +} + +// Step over function +void QuantaDebuggerGubed::stepOver() +{ + setExecutionState(Pause); + sendCommand("stepover", (char*)0L); +} + +// Step out of function +void QuantaDebuggerGubed::stepOut() +{ + setExecutionState(Pause); + sendCommand("stepout", (char*)0L); +} + +// Skip next function +void QuantaDebuggerGubed::skip() +{ + sendCommand("skip", (char*)0L); +} + +// Kill the running script +void QuantaDebuggerGubed::kill() +{ + sendCommand("die", (char*)0L); +} + +// Pause execution +void QuantaDebuggerGubed::pause() +{ + setExecutionState(Pause); +} + + +// Add a breakpoint +void QuantaDebuggerGubed::addBreakpoint (DebuggerBreakpoint* breakpoint) +{ + QString type; + if(breakpoint->type() == DebuggerBreakpoint::LineBreakpoint) + type = "line"; + else if(breakpoint->type() == DebuggerBreakpoint::ConditionalTrue) + type = "true"; + else + type = "change"; + + sendCommand("breakpoint", + "type", type.ascii(), + "filename", mapLocalPathToServer(breakpoint->filePath()).ascii(), + "class", breakpoint->inClass().ascii(), + "function", breakpoint->inFunction().ascii(), + "expression", breakpoint->condition().ascii(), + "line", QString::number(breakpoint->line()).ascii(), + (char *)0L); +} + +// QString QuantaDebuggerGubed::bpToGubed(DebuggerBreakpoint* breakpoint) +// { +// return QString("^" + mapLocalPathToServer(breakpoint->filePath()) + +// "^" + breakpoint->inClass() + +// "^" + breakpoint->inFunction() + +// "^" + (breakpoint->type() == DebuggerBreakpoint::ConditionalTrue ? "true" : "change") + +// "^" + breakpoint->condition()); +// } + +// Clear a breakpoint +void QuantaDebuggerGubed::removeBreakpoint(DebuggerBreakpoint* breakpoint) +{ + QString type; + if(breakpoint->type() == DebuggerBreakpoint::LineBreakpoint) + type = "line"; + else if(breakpoint->type() == DebuggerBreakpoint::ConditionalTrue) + type = "true"; + else + type = "change"; + + sendCommand("removebreakpoint", + "type", type.ascii(), + "filename", mapLocalPathToServer(breakpoint->filePath()).ascii(), + "class", breakpoint->inClass().ascii(), + "function", breakpoint->inFunction().ascii(), + "expression", breakpoint->condition().ascii(), + "line", QString::number(breakpoint->line()).ascii(), + (char*)0L); +} + +// A file was opened... +void QuantaDebuggerGubed::fileOpened(const QString&) +{ + sendCommand("reinitialize", (char*)0L); +} + +// Watch a variable +void QuantaDebuggerGubed::addWatch(const QString &variable) +{ + if(m_watchlist.find(variable) == m_watchlist.end()) + m_watchlist.append(variable); + sendCommand("getwatch", "variable", variable.ascii(), (char*)0L); +} +// Remove watch +void QuantaDebuggerGubed::removeWatch(DebuggerVariable *variable) +{ + if(m_watchlist.find(variable->name()) != m_watchlist.end()) + m_watchlist.remove(m_watchlist.find(variable->name())); + //sendCommand("unwatchvariable", var->name()); +} + +// Show conditional breakpoint state +void QuantaDebuggerGubed::showCondition(const StringMap &args) +{ + + 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 QuantaDebuggerGubed::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 = "8026"; + + 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 = "8016"; + + valuenode = node.namedItem("startsession"); + m_startsession = valuenode.firstChild().nodeValue(); + if(m_startsession.isEmpty()) + m_startsession = "http://localhost/Gubed/StartSession.php?gbdScript=/%rfpp"; + + valuenode = node.namedItem("defaultexecutionstate"); + if(valuenode.firstChild().nodeValue().isEmpty()) + m_defaultExecutionState = Pause; + else + m_defaultExecutionState = (State)valuenode.firstChild().nodeValue().toUInt(); + + valuenode = node.namedItem("useproxy"); + m_useproxy = valuenode.firstChild().nodeValue() == "1"; + + valuenode = node.namedItem("displaydelay"); + m_displaydelay = valuenode.firstChild().nodeValue().toLong(); + + valuenode = node.namedItem("errormask"); + m_errormask = valuenode.firstChild().nodeValue().toLong(); + kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl; +} + + +// Show configuration +void QuantaDebuggerGubed::showConfig(QDomNode node) +{ + GubedSettings set(protocolversion); + + readConfig(node); + + set.lineServerHost->setText(m_serverHost); + set.lineServerPort->setText(m_serverPort); + set.lineLocalBasedir->setText(m_localBasedir); + set.lineServerBasedir->setText(m_serverBasedir); + set.lineServerListenPort->setText(m_listenPort); + set.checkUseProxy->setChecked(m_useproxy); + set.sliderDisplayDelay->setValue(m_displaydelay); + set.lineStartSession->setText(m_startsession); + set.comboDefaultExecutionState->setCurrentItem((int)m_defaultExecutionState); + + set.checkBreakOnNotice->setChecked(QuantaDebuggerGubed::Notice & m_errormask); + set.checkBreakOnWarning->setChecked(QuantaDebuggerGubed::Warning & m_errormask); + set.checkBreakOnUserNotice->setChecked(QuantaDebuggerGubed::User_Notice & m_errormask); + set.checkBreakOnUserWarning->setChecked(QuantaDebuggerGubed::User_Warning & m_errormask); + set.checkBreakOnUserError->setChecked(QuantaDebuggerGubed::User_Error & m_errormask); + + if(set.exec() == QDialog::Accepted ) + { + QDomElement el; + + el = node.namedItem("serverhost").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("serverhost"); + node.appendChild( el ); + m_serverHost = set.lineServerHost->text(); + el.appendChild(node.ownerDocument().createTextNode(m_serverHost)); + + el = node.namedItem("serverport").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("serverport"); + node.appendChild( el ); + m_serverPort = set.lineServerPort->text(); + el.appendChild( node.ownerDocument().createTextNode(m_serverPort) ); + + el = node.namedItem("localbasedir").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("localbasedir"); + node.appendChild( el ); + m_localBasedir = set.lineLocalBasedir->text(); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setLocalBasedir(m_localBasedir); + el.appendChild( node.ownerDocument().createTextNode(m_localBasedir) ); + + el = node.namedItem("serverbasedir").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("serverbasedir"); + node.appendChild( el ); + m_serverBasedir = set.lineServerBasedir->text(); + if(debuggerInterface()) + debuggerInterface()->Mapper()->setServerBasedir(m_serverBasedir); + el.appendChild( node.ownerDocument().createTextNode(m_serverBasedir) ); + + el = node.namedItem("useproxy").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("useproxy"); + node.appendChild( el ); + m_useproxy = set.checkUseProxy->isChecked(); + el.appendChild( node.ownerDocument().createTextNode(m_useproxy ? "1" : "0") ); + + 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 ); + m_defaultExecutionState = (State)set.comboDefaultExecutionState->currentItem(); + el.appendChild(node.ownerDocument().createTextNode(QString::number(m_defaultExecutionState))); + + + el = node.namedItem("displaydelay").toElement(); + if (!el.isNull()) + el.parentNode().removeChild(el); + el = node.ownerDocument().createElement("displaydelay"); + node.appendChild( el ); + m_displaydelay = set.sliderDisplayDelay->value(); + el.appendChild( node.ownerDocument().createTextNode(QString::number(m_displaydelay))); + + 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() ? QuantaDebuggerGubed::Notice : 0) + + (set.checkBreakOnWarning->isChecked() ? QuantaDebuggerGubed::Warning : 0) + + (set.checkBreakOnUserNotice->isChecked() ? QuantaDebuggerGubed::User_Notice : 0) + + (set.checkBreakOnUserWarning->isChecked() ? QuantaDebuggerGubed::User_Warning : 0) + + (set.checkBreakOnUserError->isChecked() ? QuantaDebuggerGubed::User_Error : 0); + kdDebug(24002) << k_funcinfo << ", m_errormask = " << m_errormask << endl; + el.appendChild( node.ownerDocument().createTextNode(QString::number(m_errormask))); + + } +} + +// Map a server filepath to a local one using project settings +QString QuantaDebuggerGubed::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 QuantaDebuggerGubed::mapLocalPathToServer(const QString& localpath) +{ + // Translate filename from local to server + return debuggerInterface()->Mapper()->mapLocalPathToServer(localpath); +} + +void QuantaDebuggerGubed::variableSetValue(const DebuggerVariable &variable) +{ + sendCommand("setvariable", + "variable", variable.name().ascii(), + "value", variable.value().ascii(), + (char*)0L); +} + +QString QuantaDebuggerGubed::phpSerialize(StringMap args) +{ + StringMap::Iterator it; + // a:2:{s:4:"name";s:7:"Jessica";s:3:"age";s:2:"26";s:4:"test";i:1;} + QString ret = QString("a:%1:{").arg(args.size()); + for( it = args.begin(); it != args.end(); ++it ) + { + bool isNumber; + + it.data().toInt(&isNumber); + if(isNumber && !it.data().isEmpty()) + ret += QString("s:%1:\"%2\";i:%3;") + .arg(it.key().length()) + .arg(it.key()) + .arg(it.data()); + else + ret += QString("s:%1:\"%2\";s:%3:\"%4\";") + .arg(it.key().length()) + .arg(it.key()) + .arg(it.data().length()) + .arg(it.data()); + + } + + ret += "}"; + return ret; +} + + +StringMap QuantaDebuggerGubed::parseArgs(const QString &args) +{ + StringMap ca; + long cnt, length; + + // a:2:{s:4:"name";s:7:"Jessica";s:3:"age";s:2:"26";s:4:"test";i:1;} + + // No args + if(args.isEmpty() || args == "a:0:{}") + return ca; + + // Make sure we have a good string + if(!args.startsWith("a:")) + { + kdDebug(24002) << k_funcinfo << "An error occurred in the communication link, data received was:" << args << endl; + return ca; + } + + cnt = args.mid(2, args.find("{") - 3).toLong(); + QString data = args.mid(args.find("{") + 1); + + QString tmp, func; + while(cnt > 0) + { + tmp = data.left(data.find("\"")); + length = tmp.mid(2, tmp.length() - 3).toLong(); + + func = data.mid(tmp.length() + 1, length); + data = data.mid( tmp.length() + length + 3); + + if(data.left(1) == "i") + { + // Integer data + tmp = data.mid(data.find(":") + 1); + tmp = tmp.left(tmp.find(";")); + ca[func] = tmp; + data = data.mid(tmp.length() + 3); +// kdDebug(24002) << k_funcinfo << "**i " << func << ": " << ca[func] << endl; + } + else + { + // String data + tmp = data.left(data.find("\"")); + length = tmp.mid(2, tmp.length() - 3).toLong(); + + ca[func] = data.mid(tmp.length() + 1, length); + data = data.mid( tmp.length() + length + 3); +// kdDebug(24002) << k_funcinfo << "**s " << func << ": " << ca[func] << endl; + } + + cnt--; + } + + return ca; +} + +DebuggerVariable* QuantaDebuggerGubed::parsePHPVariables(const QString &varstring) +{ + QString str = varstring; + DebuggerVariable* var = parsePHPVariables(str); + return var; +} + +DebuggerVariable* QuantaDebuggerGubed::parsePHPVariables(QString &str) +{ + QString key, data; + QString tempstring; + int length; + DebuggerVariable* debuggervar = NULL; + + // get type of key + QString type = str.left(1); + str.remove(0, 2); + + // Strings + if(type == "s") + { + // Get length of key + tempstring = str.left(str.find(':')); + str.remove(0, str.find(':') + 1); + length = tempstring.toUInt(); + + key = str.left(length + 1); + key.remove(0, 1); // remove starting quote + str.remove(0, length + 3); + } + else if(type == "i") + { + key = str.left(str.find(';')); + str.remove(0, str.find(';') + 1); + + } + + // Get type of data + type = str.left(1); + str.remove(0, 2); + + if(type == "i") + { + /* Example: + s:4:"$row";i:6; + */ + data = str.left(str.find(';')); + str.remove(0, str.find(';') + 1); + debuggervar = debuggerInterface()->newDebuggerVariable(key, data, DebuggerVariableTypes::Integer); + + } + else if(type == "b") + { + /* Example: + s:8:"$boolvar";b:1; + */ + data = str.left(str.find(';')); + data = (data == "0" ? i18n("False"): i18n("True")); + str.remove(0, str.find(';') + 1); + debuggervar = debuggerInterface()->newDebuggerVariable(key, data, DebuggerVariableTypes::Boolean); + } + else if(type == "N") + { + /* Example: + s:6:"return";N; + */ + debuggervar = debuggerInterface()->newDebuggerVariable(key, i18n(""), DebuggerVariableTypes::Undefined); + } + else if(type == "s") + { + /* Example: + s:7:"$strvar";s:16:"This is a string"; + */ + + // Get length of string + tempstring = str.left(str.find(':')); + str.remove(0, str.find(':') + 1); + length = tempstring.toUInt(); + + data = str.left(length + 1); + data.remove(0, 1); // remove starting quote + str.remove(0, length + 3); + debuggervar = debuggerInterface()->newDebuggerVariable(key, data, DebuggerVariableTypes::String); + debuggervar->setSize(length); + } + else if(type == "a") + { + /* Example: + s:6:"$array";a:5:{s:11:"Ingredients";a:3:{i:0;s:8:"potatoes";i:1;s:4:"salt";i:2;s:6:"pepper";}s:6:"Guests";a:4:{i:0;s:5:"Fiona";i:1;s:4:"Tori";i:2;s:4:"Neil";i:3;s:4:"Nick";}s:4:"Dogs";a:4:{i:0;s:5:"Kitty";i:1;s:5:"Tessy";i:2;s:5:"Fanny";i:3;s:5:"Cosmo";}s:7:"Numbers";a:6:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:9;i:4;i:8;i:5;i:7;}s:6:"Letter";s:1:"L";} + */ + + // Get length of array + tempstring = str.left(str.find(':')); + str.remove(0, str.find(':') + 2); + length = tempstring.toUInt(); + + QPtrList vars ; + while(length > 0) + { + //kdDebug(24002) << "VariablesListView::parsePHPVariables: length " << length << ", \"" << str << "\"" << endl; + + length --; + DebuggerVariable* var = parsePHPVariables(str); + if(var) + vars.append(var); + + } + str.remove(0, 1); + debuggervar = debuggerInterface()->newDebuggerVariable(key, vars, DebuggerVariableTypes::Array); + } + else if(type == "O") + { + /* Example: + + */ + + // Get length of array + tempstring = str.left(str.find(':')); + str.remove(0, str.find(':') + 2); + tempstring = str.mid(str.find(':') + 1); + tempstring = tempstring.left(tempstring.find(':')); + length = tempstring.toUInt(); + + str.remove(0, str.find('{') + 1); + + QPtrList vars ; + while(length > 0) + { + //kdDebug(24002) << "VariablesListView::parsePHPVariables: length " << length << ", \"" << str << "\"" << endl; + + length --; + DebuggerVariable* var = parsePHPVariables(str); + if(var) + vars.append(var); + + } + str.remove(0, 1); + debuggervar = debuggerInterface()->newDebuggerVariable(key, vars, DebuggerVariableTypes::Object); + } + else if(type == "d") + { + /* Example: + s:9:"$floatvar";d:12.5600000000000004973799150320701301097869873046875;" + */ + data = str.left(str.find(';')); + str.remove(0, str.find(';') + 1); + debuggervar = debuggerInterface()->newDebuggerVariable(key, data, DebuggerVariableTypes::Float); + + } + else if(type == "-") + { + debuggervar = debuggerInterface()->newDebuggerVariable(key, i18n(""), DebuggerVariableTypes::Undefined); + } + else if(type == "!") + { + debuggervar = debuggerInterface()->newDebuggerVariable(key, i18n(""), DebuggerVariableTypes::Error); + } + else + { + kdDebug(24002) << "VariablesListView::parsePHPVariables: Unknown variable type " << type << ", " << str << endl; + debuggervar = debuggerInterface()->newDebuggerVariable(key, i18n(""), DebuggerVariableTypes::Error); + } + + return debuggervar; + +} + + +#include "quantadebuggergubed.moc" diff --git a/quanta/components/debugger/gubed/quantadebuggergubed.desktop b/quanta/components/debugger/gubed/quantadebuggergubed.desktop new file mode 100644 index 00000000..d2020cb7 --- /dev/null +++ b/quanta/components/debugger/gubed/quantadebuggergubed.desktop @@ -0,0 +1,48 @@ +[Desktop Entry] +Type=Service +Name=Gubed +Name[ne]=ग्युब्ड +Name[ta]=குபெட் +Comment=Quanta debugger plugin to interact with the Gubed PHP debugger, see http://gubed.sf.net +Comment[bg]=Приставка на Quanta за връзка с дебъгера Gubed PHP, http://gubed.sf.net +Comment[ca]=Connector de depuració pel Quanta que interactua amb el depurador Gubed PHP, consulteu http://gubed.sf.net +Comment[cs]=Ladicí modul Quanty s Gubed PHP debuggerem, viz http://gubed.sf.net +Comment[da]=Quanta fejlretter-plugin til at virke sammen med Gubed PHP fejlretter, se http://gubed.sf.net +Comment[de]=Debug-Komponente von Quanta für die Unterstützung des Gubed PHP-Debuggers. Näheres siehe http://gubed.sf.net +Comment[el]=Αποσφαλματωτής Quanta σε συνεργασία με το αποσφαλματωτή Gubed PHP, δείτε http://gubed.sf.net +Comment[es]=Accesorio de depuración de Quanta, para interactuar con el depurador de PHP Gubed. Vea http://gubed.sf.net +Comment[et]=Quanta siluriplugin koostööks PHP siluriga Gubed (vaata http://gubed.sf.net) +Comment[eu]=Gubed PHP araztailearekin lan egiteko Quanta araztailearen plugina, ikusi http://gubed.sf.net +Comment[fa]=وصلۀ اشکال‌زدای Quanta برای تعامل با اشکال‌زدای Gubed PHP، http://gubed.sf.net را ببینید +Comment[fi]=Gubed PHP debuggerin plugin Quantan debuggeriin (katso http://gubed.sf.net) +Comment[fr]=Module de débogage de Quanta pour interagir avec le débogueur PHP Gubed ; consulter http://gubed.sf.net. +Comment[gl]=Plugin de depuración de Quanta para interactuar co depurador de PHP Gubed, vexa tamén http://gubed.sf.net +Comment[hu]=Quanta-nyomkövető (bővítőmodulként) a Gubed PHP-nyomkövetőhöz, lásd: http://gubed.sf.net +Comment[is]=Quanta aflúsunaríforrit til samskipta við Gubed PHP aflúsarann. Sjá http://gubed.sf.net +Comment[it]=Plugin debugger di Quanta per interagire con il debugger PHP Gubed, vedi http://gubed.sf.net +Comment[ja]=Gubed PHP デバッガと対話する Quanta デバッガ。詳細は http://gubed.sf.net +Comment[ka]=Quanta-ს განბზიკვის მოდული Gubed PHP განბზიკავთან დასაკავშირებლად, იხილეთ http://gubed.sf.net +Comment[lt]=Quanta derintuvės priedas skirtas dirbti su Gubed PHP derintuve, žr.http://gubed.sf.net +Comment[ms]=Plug masuk penyah-ralat Quanta untuk berinteraksi dengan penyah-ralat Gubed PHP, lihat http://gubed.sf.net +Comment[nds]=Fehlersöök-Moduul för Quanta för't Tosamenwarken mit den PHP-Fehlersöker "Gubed", kiek op http://gubed.sf.net +Comment[ne]=ग्युब्ड पीएचपी त्रुटिमोचकसँग अन्तर्क्रिया गर्नका लागि क्वान्टा त्रुटिमोचक प्लगइन, http://gubed.sf.net हेर्नुहोस् +Comment[nl]=Quanta debugger plugin om te communiceren met de Gubed PHP debugger, zie http://gubed.sf.net +Comment[pl]=Wtyczka debuggera Quanty współpracująca z debuggerem PHP Gubed , patrz http://gubed.sf.net +Comment[pt]='Plugin' de Depuração do Quanta para interagir com o depurador de PHP Gubed, veja http://gubed.sf.net +Comment[pt_BR]=Plugin do debugger do Quanta para interagir com o debugger PHP Gubed, olhe http://gubed.sf.net +Comment[ru]=Модуль отладчика Quanta для связи с Gubed, отладчиком PHP, см. http://gubed.sf.net +Comment[sk]=Quanta debuger modul pre interakciu s Gubed PHP debugerom, pozrihttp://gubed.sf.net +Comment[sl]=Vstavek razhroščevanja v Quanti, ki sodeluje z razhroščevalnikom Gubed PHP, glejte http://gubed.sf.net +Comment[sr]=Исправљачки прикључак Quanta-е за интеракцију са исправљачем PHP-а Gubed, погледајте http://gubed.sf.net +Comment[sr@Latn]=Ispravljački priključak Quanta-e za interakciju sa ispravljačem PHP-a Gubed, pogledajte http://gubed.sf.net +Comment[sv]=Quanta-insticksprogram för felsökning som fungerar med PHP-felsökaren Gubed, se http://gubed.sf.net +Comment[ta]=குவாண்டா வழுநீக்கி உள்ளீடு குபெட்PHP வழுநீக்கியோடு தொடர்புக் கொண்டிருக்கிறது, பார்க்கவும் http://gubed.sf.net +Comment[tg]=Модули ғалатёби Quanta барои алоқаи аз Gubed, ғалатёби PHP, нишон кунед http://gubed.sf.net +Comment[tr]=Gubed PHP hata ayıklayıcısıyla iletişim kurmayı sağlayan Quanta hata ayıklama eklentisi, http://gubed.sf.net adresini ziyaret edin +Comment[uk]=Втулок зневадження Quanta для зв'язку зі зневаджувачем PHP -- Gubed, див. http://gubed.sf.net +Comment[zh_CN]=与 Gubed PHP 调试器交互 Quanta 调试器插件,见 http://gubed.sf.net +Comment[zh_HK]=Quanta 對於 Gubed PHP 除錯器的通訊外掛程式, 請參閱 http://gubed.sf.net +Comment[zh_TW]=Quanta 對於 Gubed PHP 除錯器的通訊外掛程式, 請參閱 http://gubed.sf.net +Icon=kdbg +ServiceTypes=Quanta/Debugger +X-KDE-Library=quantadebuggergubed diff --git a/quanta/components/debugger/gubed/quantadebuggergubed.h b/quanta/components/debugger/gubed/quantadebuggergubed.h new file mode 100644 index 00000000..62acac0b --- /dev/null +++ b/quanta/components/debugger/gubed/quantadebuggergubed.h @@ -0,0 +1,153 @@ +/*************************************************************************** + phpdebuggubed.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include + +#include "debuggerclient.h" + +typedef QValueList WatchList; +typedef QMap StringMap; + +class QuantaDebuggerGubed : public DebuggerClient +{ + Q_OBJECT + + public: + QuantaDebuggerGubed(QObject *parent, const char* name, const QStringList&); + ~QuantaDebuggerGubed(); + + // Execution states + enum State + { + Pause = 0, + Trace, + Run + }; + // 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 trace(); + void run(); + void skip(); + void stepInto(); + void stepOver(); + void stepOut(); + void pause(); + void kill(); + void setExecutionState(State newstate); + + // Connection + void startSession(); + void endSession(); + + // Return name of debugger + QString getName(); + + // 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); + + private: + KNetwork::KStreamSocket *m_socket; + KNetwork::KServerSocket *m_server; + QString m_command, m_buffer; + long m_datalen; + + QString m_serverBasedir; + QString m_localBasedir; + QString m_serverPort; + QString m_serverHost; + QString m_startsession; + QString m_listenPort; + bool m_useproxy; + State m_executionState, m_defaultExecutionState; + long m_errormask; + long m_displaydelay; + + WatchList m_watchlist; + +// bool sendCommand(const QString&, const QString&); + bool sendCommand(const QString& command, StringMap args); + bool sendCommand(const QString& command, char * firstarg, ...); + + void processCommand(const QString&); + void sendWatches(); + void sendBreakpoints(); + void debuggingState(bool enable); + void connected(); + + QString mapServerPathToLocal(const QString& serverpath); + QString mapLocalPathToServer(const QString& localpath); + QString bpToGubed(DebuggerBreakpoint* breakpoint); + + // Communication helpers + QString phpSerialize(StringMap args); + StringMap parseArgs(const QString &args); + + // Variables + DebuggerVariable* parsePHPVariables(const QString &varstring); + DebuggerVariable* parsePHPVariables(QString &str); + void showWatch(const QString& data); + + + public slots: + // Socket slots + void slotConnected(const KNetwork::KResolverEntry &); + void slotConnectionClosed(); + void slotError(int error); + void slotReadyRead(); + void slotReadyAccept(); + + signals: + void updateStatus(DebuggerUI::DebuggerStatus); +}; + +#endif diff --git a/quanta/components/debugger/interfaces/Makefile.am b/quanta/components/debugger/interfaces/Makefile.am new file mode 100644 index 00000000..dba1986b --- /dev/null +++ b/quanta/components/debugger/interfaces/Makefile.am @@ -0,0 +1,17 @@ + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libdebuggerinterface.la +libdebuggerinterface_la_LDFLAGS = $(all_libraries) +libdebuggerinterface_la_SOURCES = debuggerinterface.cpp debuggerclient.cpp + + +# Definition of the service type +kde_servicetypes_DATA = quantadebugger.desktop + + +INCLUDES = -I$(top_srcdir)/quanta/components/debugger \ + -I$(top_srcdir)/quanta/components/debugger/interfaces \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/utility \ + $(all_includes) diff --git a/quanta/components/debugger/interfaces/debuggerclient.cpp b/quanta/components/debugger/interfaces/debuggerclient.cpp new file mode 100644 index 00000000..8c3196d9 --- /dev/null +++ b/quanta/components/debugger/interfaces/debuggerclient.cpp @@ -0,0 +1,160 @@ +/*************************************************************************** + debuggerclient.cpp + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + Based on work by Mathieu Kooiman + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "debuggerclient.h" +#include "debuggerinterface.h" +#include +#include +#include + + +// CTor +DebuggerClient::DebuggerClient(QObject *parent, const char* name) + : QObject(parent, name) +{ + m_active = false; +} + + +DebuggerInterface* DebuggerClient::debuggerInterface() +{ + return static_cast( parent()->child( 0, "DebuggerInterface" ) ); +} + +// Active state of session +bool DebuggerClient::isActive() +{ + return m_active; +} + +void DebuggerClient::unSupportedAction(const QString &action) +{ + KMessageBox::error(NULL, i18n("The current debugger, %1, does not support the \"%2\" instruction.").arg(this->getName()).arg(action), i18n("Unsupported Debugger Function")); + +} + +// Unimplemented defaults - Pause execution +void DebuggerClient::pause() +{ + unSupportedAction(i18n("Pause")); +} + +// Unimplemented defaults - Send Request +void DebuggerClient::request() +{ + unSupportedAction(i18n("Send HTTP Request")); +} + +// Unimplemented defaults - step over +void DebuggerClient::stepOver() +{ + unSupportedAction(i18n("Step Over")); + +} + +// Unimplemented defaults - step out +void DebuggerClient::stepOut() +{ + unSupportedAction(i18n("Step Out")); + +} + +// Unimplemented defaults - trace +void DebuggerClient::trace() +{ + unSupportedAction(i18n("Trace")); +} +// Unimplemented defaults - Run +void DebuggerClient::run() +{ + unSupportedAction(i18n("Run")); +} +// Unimplemented defaults - skip +void DebuggerClient::skip() +{ + unSupportedAction(i18n("Skip")); +} +// Unimplemented defaults - stepInto +void DebuggerClient::stepInto() +{ + unSupportedAction(i18n("Step Into")); +} +// Unimplemented defaults - kill +void DebuggerClient::kill() +{ + unSupportedAction(i18n("Kill")); + +} + +// Unimplemented defaults +void DebuggerClient::profilerOpen( ) +{ + unSupportedAction(i18n("Open Profiler Output")); +} + +// Unimplemented defaults +void DebuggerClient::fileOpened(const QString&) +{ + return; +} + +// Unimplemented defaults +void DebuggerClient::addBreakpoint(DebuggerBreakpoint*) +{ + unSupportedAction(i18n("Set Breakpoint")); + +} + +// Unimplemented defaults +void DebuggerClient::removeBreakpoint(DebuggerBreakpoint*) +{ + unSupportedAction(i18n("Remove Breakpoint")); +} + + +// Unimplemented defaults +void DebuggerClient::showConfig(QDomNode) +{ + KMessageBox::error(NULL, i18n("%1 does not have any specific settings.").arg(this->getName()), i18n("Settings")); +} + +// Unimplemented defaults +void DebuggerClient::readConfig(QDomNode) +{ + +} + +// Unimplemented defaults: add watch +void DebuggerClient::addWatch(const QString &) +{ + KMessageBox::error(NULL, i18n("%1 does not support watches.").arg(this->getName()), i18n("Unsupported Debugger Function")); +} + +// Unimplemented defaults: Remove watch +void DebuggerClient::removeWatch(DebuggerVariable *) +{ + // Giving an error seems pointless, since you shouldnt be able to add a watch in the first place... + KMessageBox::error(NULL, i18n("%1 does not support watches.").arg(this->getName()), i18n("Unsupported Debugger Function")); +} + +// Unimplemented defaults: set value of varialbe +void DebuggerClient::variableSetValue(const DebuggerVariable &) +{ + KMessageBox::error(NULL, i18n("%1 does not support setting the value of variables.").arg(this->getName()), i18n("Unsupported Debugger Function")); +} + +#include "debuggerclient.moc" diff --git a/quanta/components/debugger/interfaces/debuggerclient.h b/quanta/components/debugger/interfaces/debuggerclient.h new file mode 100644 index 00000000..d50526cc --- /dev/null +++ b/quanta/components/debugger/interfaces/debuggerclient.h @@ -0,0 +1,115 @@ +/*************************************************************************** + phpdebugsocket.h + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + Based on work by Mathieu Kooiman + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 _DEBUGGERCLIENT_H +#define _DEBUGGERCLIENT_H + +#include +#include +#include +#include + +#include "debuggerui.h" + +class DebuggerInterface; +class DebuggerBreakpoint; +class DebuggerVariable; + +namespace DebuggerClientCapabilities +{ + enum Capabilities + { + // Session related + StartSession = 1000, + EndSession, + + // Breakpoint related + LineBreakpoints = 2000, + ConditionalBreakpoints, + + // Variable related + Watches = 4000, + VariableSetValue, + + // Execution related + Run = 5000, + Trace, + Pause, + Kill, + StepInto, + StepOver, + StepOut, + Skip, + + // Profiler related + ProfilerOpen = 6000 + }; +} + +class DebuggerClient : public QObject +{ + Q_OBJECT + + private: + protected: + DebuggerClient(QObject *parent, const char* name); + + bool m_active; + + public: + virtual const uint supports(DebuggerClientCapabilities::Capabilities) = 0; + virtual void startSession() = 0; + virtual void endSession() = 0; + virtual QString getName() = 0; + + // Execution control + virtual void request(); + virtual void run(); + virtual void trace(); + virtual void skip(); + virtual void stepOver(); + virtual void stepInto(); + virtual void stepOut(); + virtual void kill(); + virtual void pause(); + + // Settings + virtual void readConfig(QDomNode node); + virtual void showConfig(QDomNode node); + + // Profiler + virtual void profilerOpen(); + + // Misc + virtual void fileOpened(const QString& file); + virtual void addBreakpoint(DebuggerBreakpoint* breakpoint); + virtual void removeBreakpoint(DebuggerBreakpoint* breakpoint); + virtual void addWatch(const QString &); + virtual void removeWatch(DebuggerVariable*); + virtual void variableSetValue(const DebuggerVariable &variable); + + void unSupportedAction(const QString &action); + + bool isActive(); + DebuggerInterface *debuggerInterface(); + + signals: + void updateStatus(DebuggerUI::DebuggerStatus); + +}; + +#endif diff --git a/quanta/components/debugger/interfaces/debuggerinterface.cpp b/quanta/components/debugger/interfaces/debuggerinterface.cpp new file mode 100644 index 00000000..5481180c --- /dev/null +++ b/quanta/components/debugger/interfaces/debuggerinterface.cpp @@ -0,0 +1,26 @@ +/*************************************************************************** + debuggerinterface.cpp + --------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "debuggerinterface.h" + +DebuggerInterface::DebuggerInterface (QObject *parent, const char* name) + : QObject(parent, name) +{ +} + + +#include "debuggerinterface.moc" diff --git a/quanta/components/debugger/interfaces/debuggerinterface.h b/quanta/components/debugger/interfaces/debuggerinterface.h new file mode 100644 index 00000000..8c527979 --- /dev/null +++ b/quanta/components/debugger/interfaces/debuggerinterface.h @@ -0,0 +1,80 @@ +/*************************************************************************** + debuggerinterface.h + ------------------- + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 DEBUGGERINTERFACE_H +#define DEBUGGERINTERFACE_H + +#include +#include +#include + +#include "debuggervariable.h" +#include "debuggerbreakpoint.h" +#include "backtracelistview.h" + +class PathMapper; + +class DebuggerInterface : public QObject +{ + Q_OBJECT + + private: + + + public: + DebuggerInterface(QObject *parent, const char* name); + + // Breakpoints + virtual void haveBreakpoint (const QString& file, int line) = 0; + virtual void havenoBreakpoint (const QString& file, int line) = 0; + + // Public help functions + virtual bool showStatus(const QString& message, bool log) = 0; + virtual bool setActiveLine (const QString& file, int line) = 0; + + virtual void enableAction(const QString& action, bool enable) = 0; + virtual void fileOpened(const QString& file) = 0; + virtual void sendRequest(const KURL &url) = 0; + virtual const QString activeFileParts(const QString & str) = 0; + + // Watch handling + //virtual void preWatchUpdate() = 0; + //virtual void postWatchUpdate() = 0; + + virtual DebuggerVariable* newDebuggerVariable(const QString& name, const QString& value, int type) = 0; + virtual DebuggerVariable* newDebuggerVariable(const QString& name, const ValueList_t& values, int type) = 0; + virtual void showVariable(DebuggerVariable*) = 0; + + // Backtrace + virtual void backtraceClear() = 0; + virtual void backtraceShow(long level, BacktraceType type, const QString &filename, long line, const QString& func) = 0; + + + // Breakpoints + virtual void showBreakpoint(const DebuggerBreakpoint &bp) = 0; + virtual void refreshBreakpoints() = 0; + virtual DebuggerBreakpoint * newDebuggerBreakpoint() = 0; + virtual DebuggerBreakpoint * findDebuggerBreakpoint(const QString& key) = 0; + virtual void updateBreakpointKey(const DebuggerBreakpoint &bp, const QString& newkey) = 0; + + // Path mapping + virtual PathMapper* Mapper() = 0; +}; + +#endif + + diff --git a/quanta/components/debugger/interfaces/quantadebugger.desktop b/quanta/components/debugger/interfaces/quantadebugger.desktop new file mode 100644 index 00000000..56d05e04 --- /dev/null +++ b/quanta/components/debugger/interfaces/quantadebugger.desktop @@ -0,0 +1,45 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=Quanta/Debugger +Comment=A Quanta Debugger plugin +Comment[bg]=Приставка на Quanta за дебъгване +Comment[br]=Ul lugent dizraener Quanta +Comment[ca]=Un connector de depuració pel Quanta +Comment[cs]=Ladicí modul Quanty +Comment[da]=Et Quanta fejlretter-plugin +Comment[de]=Eine Quanta Debugger-Komponente +Comment[el]=Πρόσθετο αποσφαλματωτή Quanta +Comment[es]=Un accesorio para un depurador de Quanta +Comment[et]=Quanta siluriplugin +Comment[eu]=Quanta araztailearen plugina +Comment[fa]=وصلۀ اشکال‌زدای Quanta +Comment[fi]=Quantan debuggerin plugin +Comment[fr]=Un module de débogage pour Quanta +Comment[ga]=Breiseán dífhabhtóra Quanta +Comment[gl]=Un plugin para o depurador de Quanta +Comment[hu]=Quanta nyomkövető-modul +Comment[is]=Quanta aflúsunaríforrit +Comment[it]=Un plugin debugger di Quanta +Comment[ja]=Quanta デバッガプラグイン +Comment[ka]=Quanta-ს განბზიკვის მოდული +Comment[lt]=Quanta derintuvės priedas +Comment[ms]=Plug masuk penyah-ralat Quanta +Comment[nds]=En Fehlersöök-Komponent för Quanta +Comment[ne]=एउटा क्वान्टा त्रुटिमोचक प्लगइन +Comment[nl]=Een Quanta debugger-plugin +Comment[pl]=Wtyczka debuggera Quanty +Comment[pt]=Um 'plugin' de depuração para o Quanta +Comment[pt_BR]=Um plugin do Debugger do Quanta +Comment[ru]=Модуль отладки Quanta +Comment[sk]=Quanta debuger modul +Comment[sl]=Vstavek razhroščevanja v Quanti +Comment[sr]=Исправљачки прикључак Quanta-е +Comment[sr@Latn]=Ispravljački priključak Quanta-e +Comment[sv]=Ett Quanta-insticksprogram för felsökning +Comment[ta]=குவாண்டா வழுநீக்கி சொருகு +Comment[tg]=Модули ғалатёби Quanta +Comment[tr]=Bir Quanta Hata Ayıklayıcı eklentisi +Comment[uk]=Втулок зневадження Quanta +Comment[zh_CN]=Quanta 调试器插件 +Comment[zh_HK]=一個 Quanta 除錯器的外掛程式 +Comment[zh_TW]=一個 Quanta 除錯器的外掛程式 diff --git a/quanta/components/debugger/pathmapper.cpp b/quanta/components/debugger/pathmapper.cpp new file mode 100644 index 00000000..194355d7 --- /dev/null +++ b/quanta/components/debugger/pathmapper.cpp @@ -0,0 +1,228 @@ +/*************************************************************************** + pathmapper.h + ------------------------ + begin : 2004-10-10 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "pathmapper.h" +#include "pathmapperdialog.h" + +#include "quantacommon.h" +#include "project.h" + +#include +#include +#include +#include +#include + +PathMapper::PathMapper(QObject *parent, const char *name) + : QObject(parent, name) +{ + +} + +PathMapper::PathMapper() +{ + +} + +QString PathMapper::translate(const QString & path, const QString & from, const QString &to) +{ + QString translated = path; + + // Check if this dir is matched by the maps + if(path.startsWith(from, false)) + { + translated.remove(0, from.length()); + translated = to + translated; + } + + return translated; +} + +QString PathMapper::mapLocalPathToServer(const QString &localpath) +{ + if(localpath.isEmpty()) + return localpath; + + if(m_localBasedir == "/" && m_serverBasedir == "/") + return localpath; + + QString newpath = translate(localpath, m_localBasedir, m_serverBasedir); + + // If no translation occurred, check and see if some of the other translations does + if(newpath == localpath) + { + for (unsigned int cnt = 0; cnt < m_serverlist.count(); cnt++ ) + { + // If the entire filename matches, count it as a match even if there is no difference + if(m_locallist[cnt] == localpath) + return localpath; + + // If both are slashes, count it as a local project + if(m_locallist[cnt] == "/" && m_serverlist[cnt] == "/") + return localpath; + + // Check if it translates into something + newpath = translate(localpath, m_locallist[cnt], m_serverlist[cnt]); + if(newpath != localpath) + { + addHistory(localpath, newpath, true); + return newpath; + } + } + + // No translation found -> show dialog + PathMapperDialog pmdlg(localpath, PathMapperDialog::LocalToServer); + for (unsigned int cnt = 0; cnt < m_serverlist.count(); cnt++ ) + pmdlg.addHistory(m_serverlist[cnt], m_locallist[cnt]); + + if(pmdlg.exec() == QDialog::Accepted ) + { + newpath = translate(localpath, pmdlg.localPath(), pmdlg.serverPath()); + addHistory(pmdlg.localPath(), pmdlg.serverPath(), newpath != localpath); + + return newpath; + } + return localpath; + } + return newpath; +} + +QString PathMapper::mapServerPathToLocal(const QString &serverpath) +{ + QString newpath; + if(serverpath.isEmpty()) + return serverpath; + + newpath = translate(serverpath, m_serverBasedir, m_localBasedir); + + // Check if this dir is matched by the basedirs + if(QExtFileInfo::exists(newpath, true, 0L)) + return newpath; + + // Check if any previous mappings fit... + for (unsigned int cnt = 0; cnt < m_serverlist.count(); cnt++ ) + { + newpath = translate(serverpath, m_serverlist[cnt], m_locallist[cnt]); + if(QExtFileInfo::exists(newpath, true, 0L)) + return newpath; + } + + // If the basedirs didnt match, check if the file exists, + // otherwise scan through the mapping history or show the + // mapping dialog + if(!QExtFileInfo::exists(serverpath, true, 0L)) + { + PathMapperDialog pmdlg(serverpath, PathMapperDialog::ServerToLocal); + for (unsigned int cnt = 0; cnt < m_serverlist.count(); cnt++ ) + pmdlg.addHistory(m_serverlist[cnt], m_locallist[cnt]); + + if(pmdlg.exec() == QDialog::Accepted ) + { + addHistory(pmdlg.localPath(), pmdlg.serverPath(), true); + newpath = translate(serverpath, pmdlg.localPath(), pmdlg.serverPath()); + return newpath; + } + } + + return serverpath; +} + +void PathMapper::setLocalBasedir(const QString &localpath) +{ + m_localBasedir = localpath; +} +void PathMapper::setServerBasedir(const QString &serverpath) +{ + m_serverBasedir = serverpath; +} + +QDomNode PathMapper::pathMapperNode() +{ + QDomNode nodeThisDbg; + QDomDocument *dom = Project::ref()->sessionDom(); + QDomNode projectNode = dom->firstChild().firstChild(); + QDomNode nodeDbg = projectNode.namedItem("debuggers"); + if(nodeDbg.isNull()) + { + nodeDbg = dom->createElement("debuggers"); + projectNode.appendChild(nodeDbg); + } + + // Find the pathmapper section + nodeThisDbg = nodeDbg.namedItem("pathmapper"); + if(nodeThisDbg.isNull()) + { + nodeThisDbg = dom->createElement("pathmapper"); + nodeDbg.appendChild(nodeThisDbg); + } + + return nodeThisDbg; +} + +void PathMapper::addHistory(const QString &localpath, const QString &serverpath, bool saveinproject) +{ + bool exists = false; + for (unsigned int cnt = 0; cnt < m_serverlist.count() && !exists; cnt++ ) + if(m_serverlist[cnt] == serverpath && m_locallist[cnt] == localpath) + exists = true; + + if(!exists) + { + if(saveinproject) + { + QDomNode node = pathMapperNode(); + QDomNode newnode = Project::ref()->dom()->createElement("mapping"); + + QDomAttr serverattr = Project::ref()->dom()->createAttribute("serverpath"); + serverattr.setValue(serverpath); + QDomAttr localattr = Project::ref()->dom()->createAttribute("localpath"); + localattr.setValue(localpath); + + newnode.attributes().setNamedItem(serverattr); + newnode.attributes().setNamedItem(localattr); + + node = node.namedItem("mappings"); + node.insertAfter(newnode, node.lastChild()); + } + + m_serverlist.append(serverpath); + m_locallist.append(localpath); + } + +} + +void PathMapper::readConfig() +{ + QDomNode node = pathMapperNode(); + + // Server + QDomNode valuenode = node.namedItem("mappings"); + QDomNode child = valuenode.firstChild(); + QString serverpath, localpath; + while(!child.isNull()) + { + serverpath = child.attributes().namedItem("serverpath").nodeValue(); + localpath = child.attributes().namedItem("localpath").nodeValue(); + kdDebug(24002) << "PathMapper::readConfig " << serverpath << ", " << localpath << endl; + + m_serverlist.append(serverpath); + m_locallist.append(localpath); + child = child.nextSibling(); + } +} + +#include "pathmapper.moc" diff --git a/quanta/components/debugger/pathmapper.h b/quanta/components/debugger/pathmapper.h new file mode 100644 index 00000000..b93b48cb --- /dev/null +++ b/quanta/components/debugger/pathmapper.h @@ -0,0 +1,55 @@ +/*************************************************************************** + pathmapper.h + ------------------------ + begin : 2004-10-10 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 PATHMAPPER_H +#define PATHMAPPER_H + +#include +#include +#include + +class KURL; + +class PathMapper : public QObject +{ + Q_OBJECT + + public: + PathMapper(QObject *parent = 0, const char *name = 0); + PathMapper(); + virtual QString mapLocalPathToServer(const QString &localpath); + virtual QString mapServerPathToLocal(const QString &serverpath); + + virtual void setLocalBasedir(const QString &localpath); + virtual void setServerBasedir(const QString &serverpath); + + void readConfig(); + + private: + QDomNode pathMapperNode(); + QString translate(const QString & path, const QString & from, const QString &to); + void addHistory(const QString &localpath, const QString &serverpath, bool saveinproject); + + QString m_localBasedir; + QString m_serverBasedir; + + QStringList m_serverlist; + QStringList m_locallist; +}; + +#endif diff --git a/quanta/components/debugger/pathmapperdialog.cpp b/quanta/components/debugger/pathmapperdialog.cpp new file mode 100644 index 00000000..8cfb949e --- /dev/null +++ b/quanta/components/debugger/pathmapperdialog.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + pathmapperdialog.cpp + -------------------- + begin : 2005-01-08 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 "pathmapperdialog.h" +#include +#include +#include +#include +#include + +PathMapperDialog::PathMapperDialog(const QString& path, const PathMapperDialog::Direction direction) + : PathMapperDialogS(0, "PathMapperDialog", false, 0) +{ + m_direction = direction; + m_path = path; + linePath->setText(path); + + if(m_direction == LocalToServer) + ledTranslationExists->hide(); + + connect(listHistory, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); + connect(lineLocalPath, SIGNAL(textChanged(const QString&)), this, SLOT(slotPathsChanged())); + connect(lineServerPath, SIGNAL(textChanged(const QString&)), this, SLOT(slotPathsChanged())); +} + +PathMapperDialog::~PathMapperDialog() +{ +} + +void PathMapperDialog::addHistory(const QString &serverdir, const QString &localdir) +{ + new QListViewItem(listHistory, localdir, serverdir); +} + +void PathMapperDialog::slotSelectionChanged() +{ + lineLocalPath->setText(listHistory->currentItem()->text(0)); + lineServerPath->setText(listHistory->currentItem()->text(1)); +} + +void PathMapperDialog::slotPathsChanged() +{ + QString translated, from, to; + if(m_direction == ServerToLocal) + { + from = lineServerPath->text(); + to = lineLocalPath->text(); + } + else + { + to = lineServerPath->text(); + from = lineLocalPath->text(); + } + + translated = m_path; + + // Check if this dir is matched by the maps + if(m_path.startsWith(from, false)) + { + translated.remove(0, from.length()); + translated = to + translated; + } + + // Indicate wether local file exists + if(m_direction == ServerToLocal) + { + if(QExtFileInfo::exists(translated, true, this)) + ledTranslationExists->setColor(Qt::green); + else + ledTranslationExists->setColor(Qt::red); + ledTranslationExists->on(); + } + + lineTranslated->setText(translated); +} + +QString PathMapperDialog::serverPath() +{ + return lineServerPath->text(); +} + +QString PathMapperDialog::localPath() +{ + return lineLocalPath->text(); +} + +#include "pathmapperdialog.moc" + diff --git a/quanta/components/debugger/pathmapperdialog.h b/quanta/components/debugger/pathmapperdialog.h new file mode 100644 index 00000000..786de8ea --- /dev/null +++ b/quanta/components/debugger/pathmapperdialog.h @@ -0,0 +1,52 @@ +/*************************************************************************** + pathmapperdialog.h + ------------------ + begin : 2004-04-05 + copyright : (C) 2004 Linus McCabe + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 PATHMAPPERDIALOG_H +#define PATHMAPPERDIALOG_H + +#include "pathmapperdialogs.h" + +class PathMapperDialog : public PathMapperDialogS +{ + Q_OBJECT + + public: + enum Direction + { + ServerToLocal = 0, + LocalToServer + }; + + PathMapperDialog(const QString& path, const PathMapperDialog::Direction direction); + ~PathMapperDialog(); + + void addHistory(const QString &serverdir, const QString &localdir); + + QString serverPath(); + QString localPath(); + + public slots: + void slotSelectionChanged(); + void slotPathsChanged(); + + private: + QString m_path; + Direction m_direction; + +}; + +#endif // PATHMAPPERDIALOG_H + diff --git a/quanta/components/debugger/pathmapperdialogs.ui b/quanta/components/debugger/pathmapperdialogs.ui new file mode 100644 index 00000000..fc7486d4 --- /dev/null +++ b/quanta/components/debugger/pathmapperdialogs.ui @@ -0,0 +1,345 @@ + +PathMapperDialogS + + + PathMapperDialogS + + + + 0 + 0 + 590 + 519 + + + + Directory Mapping + + + true + + + + unnamed + + + + groupBox6 + + + Directory Mapping + + + + unnamed + + + + lblDebuggerLocalBasedir + + + + 5 + 5 + 0 + 0 + + + + Local basedir: + + + + + lblDebuggerServerBasedir + + + + 5 + 5 + 0 + 0 + + + + Server basedir: + + + + + lineLocalPath + + + This is where the local part of path is specified. If a file is located on the computer running Quanta at "/home/user/htdocs/project/file.php" and that file is located on the server as "/var/www/project/file.php", local basedir should be "/home/user/htdocs/" and server basedir should be "/var/www/". +The quanta will know that files starting with "/home/user/project/" on the local computer, will start with "/var/www/" on the remote computer. + + + + + lineServerPath + + + This is where the server part of path is specified. If a file is located on the computer running Quanta at "/home/user/htdocs/project/file.php" and that file is located on the server as "/var/www/project/file.php", local basedir should be "/home/user/htdocs/" and server basedir should be "/var/www/". +The quanta will know that files starting with "/home/user/project/" on the local computer, will start with "/var/www/" on the remote computer. + + + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + + + + true + + + + + + + groupBox7 + + + Previous Mappings + + + + unnamed + + + + + Local Directory + + + true + + + true + + + + + Server Directory + + + true + + + true + + + + listHistory + + + StyledPanel + + + Manual + + + true + + + AllColumns + + + This is a list of previously used mappings. Click on one to use it + + + + + + + groupBox8 + + + Sample + + + + unnamed + + + + lblTranslates + + + + 5 + 5 + 0 + 0 + + + + Translates to: + + + + + lblOriginal + + + + 5 + 5 + 0 + 0 + + + + Original path: + + + + + ledTranslationExists + + + + 22 + 22 + + + + + 22 + 22 + + + + On + + + Circular + + + Raised + + + Indicates whether the translated path exists on disk or not + + + This indicator tells you whether the translated path exists on local disk or not. + + + + + lineTranslated + + + false + + + + 0 + 0 + 0 + + + + This field shows what the "original path" above will look like after translation. + + + + + linePath + + + false + + + + 0 + 0 + 0 + + + + This field shows the path currently needing to be translated. + + + + + + + + + + + buttonOk + clicked() + PathMapperDialogS + accept() + + + buttonCancel + clicked() + PathMapperDialogS + reject() + + + + slotHistoryclicked() + + + + kled.h + + diff --git a/quanta/components/debugger/quantadebuggerinterface.cpp b/quanta/components/debugger/quantadebuggerinterface.cpp new file mode 100644 index 00000000..bd9ba2e1 --- /dev/null +++ b/quanta/components/debugger/quantadebuggerinterface.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + debugmanager.cpp + ------------------ + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 +#include +#include +#include +#include + +#include "debuggerinterface.h" +#include "quantadebuggerinterface.h" +#include "debuggermanager.h" +#include "debuggerui.h" +#include "pathmapper.h" +#include "project.h" +#include "viewmanager.h" +#include "document.h" + +class DebuggerBreakpoint; + +QuantaDebuggerInterface::QuantaDebuggerInterface (QObject *myparent, const char* name) + : DebuggerInterface(myparent, name) +{ + m_manager = static_cast(parent()); +} + +QuantaDebuggerInterface::~QuantaDebuggerInterface () +{} + +void QuantaDebuggerInterface::haveBreakpoint (const QString& file, int line) +{ + return m_manager->haveBreakpoint(file, line); +} + +void QuantaDebuggerInterface::havenoBreakpoint (const QString& file, int line) +{ + return m_manager->havenoBreakpoint(file, line); +} + +// Public help functions +bool QuantaDebuggerInterface::showStatus(const QString& message, bool log) +{ + return m_manager->showStatus(message, log); +} + +bool QuantaDebuggerInterface::setActiveLine(const QString& file, int line) +{ + return m_manager->setActiveLine(file, line); +} + +void QuantaDebuggerInterface::enableAction(const QString& action, bool enable) +{ + m_manager->enableAction(action, enable); +} + +void QuantaDebuggerInterface::fileOpened(const QString& file) +{ + m_manager->fileOpened(file); +} + +void QuantaDebuggerInterface::sendRequest(const KURL &url) +{ + m_manager->UI()->sendRequest(url); +} + +const QString QuantaDebuggerInterface::activeFileParts(const QString & str) +{ + QString newstr = str; + + // a/r = absolute/relative + // f/p/d = file/project/docroot + // n/d/p = name/dir/path + + // Filename, filedir and filepath + newstr.replace("%afn", ViewManager::ref()->activeDocument()->url().fileName()); + newstr.replace("%afd", ViewManager::ref()->activeDocument()->url().directory()); + newstr.replace("%afp", ViewManager::ref()->activeDocument()->url().path()); + + // filedir and filepath relative to project root + newstr.replace("%rfpp", KURL::relativePath(Project::ref()->projectBaseURL().path(), ViewManager::ref()->activeDocument()->url().path())); + newstr.replace("%rfpd", KURL::relativePath(Project::ref()->projectBaseURL().path(), ViewManager::ref()->activeDocument()->url().directory())); + + // filedir and filepath relative to document root + newstr.replace("%rfdp", KURL::relativePath(Project::ref()->documentFolderForURL(ViewManager::ref()->activeDocument()->url()).directory(), ViewManager::ref()->activeDocument()->url().path())); + newstr.replace("%rfdd", KURL::relativePath(Project::ref()->documentFolderForURL(ViewManager::ref()->activeDocument()->url()).directory(), ViewManager::ref()->activeDocument()->url().directory())); + + newstr.replace("%apd", Project::ref()->projectBaseURL().path()); + newstr.replace("%add", Project::ref()->documentFolderForURL(ViewManager::ref()->activeDocument()->url()).directory()); + + kdDebug(24002) << k_funcinfo << ", BaseURL " << Project::ref()->projectBaseURL().path() << ", active doc : " << ViewManager::ref()->activeDocument()->url().path() << ", documentFolderForURL" << Project::ref()->documentFolderForURL(ViewManager::ref()->activeDocument()->url()) << ", newstr" << newstr << endl; + + return newstr; +} + +void QuantaDebuggerInterface::showVariable(DebuggerVariable* var) +{ + m_manager->UI()->addVariable(var); +} + +DebuggerVariable *QuantaDebuggerInterface::newDebuggerVariable(const QString& name, const QString& value, int type) +{ + return new DebuggerVariable(name, value, type); +} + +DebuggerVariable *QuantaDebuggerInterface::newDebuggerVariable(const QString& name, const ValueList_t& values, int type) +{ + return new DebuggerVariable(name, values, type); +} + +void QuantaDebuggerInterface::showBreakpoint(const DebuggerBreakpoint &bp) +{ + m_manager->UI()->showBreakpoint(bp); +} + +void QuantaDebuggerInterface::refreshBreakpoints() +{ + m_manager->refreshBreakpoints(); +} + +DebuggerBreakpoint *QuantaDebuggerInterface::newDebuggerBreakpoint() +{ + return new DebuggerBreakpoint(); +} + +DebuggerBreakpoint *QuantaDebuggerInterface::findDebuggerBreakpoint(const QString& key) +{ + return m_manager->findDebuggerBreakpoint(key); +} + +/* +void QuantaDebuggerInterface::preWatchUpdate() +{ + m_manager->UI()->preWatchUpdate(); +} + +void QuantaDebuggerInterface::postWatchUpdate() +{ + m_manager->UI()->postWatchUpdate(); +}*/ + +// Path mapping +PathMapper* QuantaDebuggerInterface::Mapper() +{ + return m_manager->Mapper(); +} + +void QuantaDebuggerInterface::updateBreakpointKey( const DebuggerBreakpoint & bp, const QString & newkey ) +{ + m_manager->updateBreakpointKey(bp, newkey); +} + +void QuantaDebuggerInterface::backtraceClear( ) +{ + m_manager->UI()->backtraceClear(); +} + +void QuantaDebuggerInterface::backtraceShow( long level, BacktraceType type, const QString & filename, long line, const QString & func ) +{ + m_manager->UI()->backtraceShow(level, type, filename, line, func); +} + +#include "quantadebuggerinterface.moc" diff --git a/quanta/components/debugger/quantadebuggerinterface.h b/quanta/components/debugger/quantadebuggerinterface.h new file mode 100644 index 00000000..44be8f4a --- /dev/null +++ b/quanta/components/debugger/quantadebuggerinterface.h @@ -0,0 +1,75 @@ +/*************************************************************************** + debugmanager.h + ------------------ + begin : 2004-03-12 + copyright : (C) 2004 Linus McCabe + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 MYDEBUGMANAGER_H +#define MYDEBUGMANAGER_H + +#include +#include +#include "debuggerinterface.h" +#include "debuggervariable.h" + +class DebuggerManager; + +class QuantaDebuggerInterface : public DebuggerInterface +{ + Q_OBJECT + + private: + DebuggerManager *m_manager; + + public: + QuantaDebuggerInterface(QObject *myparent, const char* name); + ~QuantaDebuggerInterface(); + + // Breakpoints + void haveBreakpoint (const QString& file, int line) ; + void havenoBreakpoint (const QString& file, int line) ; + void refreshBreakpoints(); + + // Public help functions + bool showStatus(const QString& message, bool log); + bool setActiveLine (const QString& file, int line) ; + + void enableAction(const QString& action, bool enable); + void fileOpened(const QString& file) ; + void sendRequest(const KURL &url); + virtual const QString activeFileParts(const QString & str); + + // Watches handling + //void preWatchUpdate(); + //void postWatchUpdate(); + DebuggerVariable* newDebuggerVariable(const QString& name, const QString& value, int type); + DebuggerVariable* newDebuggerVariable(const QString& name, const ValueList_t& values, int type); + void showVariable(DebuggerVariable*); + + // Breakpoints + void showBreakpoint(const DebuggerBreakpoint &bp); + DebuggerBreakpoint * newDebuggerBreakpoint(); + DebuggerBreakpoint * findDebuggerBreakpoint(const QString& key); + void updateBreakpointKey(const DebuggerBreakpoint &bp, const QString& newkey); + + // Backtrace + void backtraceClear(); + void backtraceShow(long level, BacktraceType type, const QString &filename, long line, const QString& func); + + // Path mapping + PathMapper* Mapper(); +}; + +#endif + diff --git a/quanta/components/debugger/variableslistview.cpp b/quanta/components/debugger/variableslistview.cpp new file mode 100644 index 00000000..c9d77de3 --- /dev/null +++ b/quanta/components/debugger/variableslistview.cpp @@ -0,0 +1,290 @@ +/*************************************************************************** + variableslistview.cpp + ----------------------- + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// KDE Includes +#include +#include +#include +#include +#include +#include + +// Quanta includes +#include "variableslistview.h" +#include "debuggervariable.h" +#include "resource.h" +#include "quanta.h" +#include "messageoutput.h" +#include "debuggerclient.h" +#include "debuggermanager.h" + +namespace VariablesListViewColumns +{ + // The enums must correspond to the order of the columns + // If you change here, change the column adding + enum Columns + { + Name = 0, + Status, + Value, + Type, + Size + + }; +} + +VariablesListView::VariablesListView(QWidget *parent, const char *name) + : KListView(parent, name) +{ + // If you change here, change the VariablesListViewColumns enums above + addColumn(i18n("Name")); + addColumn(QString::null); + addColumn(i18n("Value")); + addColumn(i18n("Type")); + addColumn(i18n("Size")); + setRootIsDecorated(true); + setSorting(-1); // No sorting + + m_variablePopup = new KPopupMenu(this); + m_variablePopup->insertItem(SmallIcon("editdelete"), i18n("&Remove"), this, SLOT(slotRemoveSelected()), 0, removeWatch); + + if(quantaApp->debugger()->client()->supports(DebuggerClientCapabilities::VariableSetValue)) + m_variablePopup->insertItem(SmallIcon("edit"), i18n("&Set Value"), this, SLOT(slotVariableSetValue()), 0, setValue); + + m_variablePopup->insertItem(SmallIcon("viewmag"), i18n("&Dump in Messages Log"), this, SLOT(slotVariableDump()), 0, dumpValue); + + m_variablePopup->insertItem(SmallIcon("editcopy"), i18n("&Copy to Clipboard"), this, SLOT(slotVariableCopyToClipboard()), 0, copyValue); + + connect(this, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & ) ), this, SLOT(slotVariableContextMenu(KListView *, QListViewItem *, const QPoint &))); +} + + +VariablesListView::~VariablesListView() +{} + +DebuggerVariable* VariablesListView::selected(bool traverse) +{ + if(!selectedItem()) + return NULL; + + DebuggerVariable* v, *found; + for( v = m_variablesList.first(); v; v = m_variablesList.next()) + { + found = v->findItem(selectedItem(), traverse); + if(found) + return found; + } + + return NULL; +} + +void VariablesListView::slotRemoveSelected() +{ + DebuggerVariable* v = selected(); + + if(!v) + return; + + emit removeVariable(v); + m_variablesList.remove(v); + delete v; +} + +void VariablesListView::keyPressEvent(QKeyEvent *e) +{ + if(e->key() != Qt::Key_Delete) + { + e->ignore(); + return; + } + + DebuggerVariable* v = selected(); + + if(!v) + return; + + emit removeVariable(v); + m_variablesList.remove(v); + delete v; +} + +void VariablesListView::addVariable(DebuggerVariable* variable) +{ + if(!variable) + { + kdDebug(24002) << k_funcinfo << " Tried to show NULL variable!" << endl; + return; + } + + // Find the old variable in the tree if it is there + for(DebuggerVariable* v = m_variablesList.first(); v; v = m_variablesList.next()) + { + if(v->name() == variable->name()) + { + replaceVariable(v, variable); + return; + } + } + + // Insert the new variable + DebuggerVariable *newvar = new DebuggerVariable(variable); + m_variablesList.append(newvar); + + KListViewItem * item = new KListViewItem(this); + insertItem(item); + newvar->setItem(item); + replaceVariable(newvar, variable); +} + +void VariablesListView::clear() +{ + KListView::clear(); + m_variablesList.clear(); +} + +void VariablesListView::replaceVariable(DebuggerVariable* oldvar, DebuggerVariable* newvar) +{ + KListViewItem * item; + + // Remove children that doesen't exist anymore + QPtrList oldlist = oldvar->values(); + for(DebuggerVariable* oldchild = oldlist.last(); oldchild; oldchild = oldlist.prev()) + { + bool found = false; + QPtrList newlist = newvar->values(); + for(DebuggerVariable* newchild = newlist.last(); newchild; newchild = newlist.prev()) + { + if(newchild->name() == oldchild->name()) + { + found = true; + break; + } + } + if(!found) + oldvar->deleteChild(oldchild); + } + + // Update and add children + QPtrList newlist = newvar->values(); + for(DebuggerVariable* newchild = newlist.last(); newchild; newchild = newlist.prev()) + { + bool found = false; + QPtrList oldlist = oldvar->values(); + for(DebuggerVariable* oldchild = oldlist.last(); oldchild; oldchild = oldlist.prev()) + { + if(newchild->name() == oldchild->name()) + { + found = true; + replaceVariable( oldchild, newchild); + break; + } + } + if(!found) + { + DebuggerVariable* child = new DebuggerVariable(); + item = new KListViewItem(oldvar->item()); + child->setItem(item); + replaceVariable( child, newchild); + oldvar->append(child); + } + } + + item = oldvar->item(); + + if(oldvar->value() != newvar->value()) + item->setPixmap(VariablesListViewColumns::Status, SmallIcon("ok")); + else + item->setPixmap(VariablesListViewColumns::Status, KPixmap()); + + oldvar->copy(newvar, false); + + item->setText(VariablesListViewColumns::Name, oldvar->name()); + item->setText(VariablesListViewColumns::Type, oldvar->typeName()); + item->setText(VariablesListViewColumns::Size, oldvar->sizeName()); + item->setText(VariablesListViewColumns::Value, (newvar->isScalar() ? oldvar->value() : QString())); + +} + +void VariablesListView::slotVariableContextMenu(KListView *, QListViewItem *, const QPoint& point) +{ + if(!selectedItem()) + return; + + m_variablePopup->setItemEnabled(removeWatch, selected()); + if(quantaApp->debugger()->client()->supports(DebuggerClientCapabilities::VariableSetValue)) + m_variablePopup->setItemEnabled(setValue, selected()); + + DebuggerVariable *v = selected(true); + m_variablePopup->setItemEnabled(dumpValue, v && v->isScalar()); + m_variablePopup->setItemEnabled(copyValue, v && v->isScalar()); + + m_variablePopup->popup(point); +} + +void VariablesListView::slotVariableSetValue() +{ + if(!selected()) + return; + + DebuggerVariable v(selected()); + + QString newvalue; + switch(v.type()) + { + case DebuggerVariableTypes::String: + newvalue = "\"" + v.value() + "\""; + break; + + case DebuggerVariableTypes::Float: + case DebuggerVariableTypes::Boolean: + case DebuggerVariableTypes::Integer: + //case DebuggerVariableTypes::Array: + newvalue = v.value(); + break; + + default: + newvalue = ""; + } + newvalue = KInputDialog::getMultiLineText(i18n("Set Variable"), i18n("New value:"), newvalue, 0, this); + if(newvalue.isNull()) + return; + + v.setValue(newvalue); + quantaApp->debugger()->client()->variableSetValue(v); + +} + +void VariablesListView::slotVariableDump( ) +{ + DebuggerVariable *v = selected(true); + if(!v) + return; + + quantaApp->messageOutput()->showMessage(i18n("Contents of variable %1:\n>>>\n").arg(v->name())); + quantaApp->messageOutput()->showMessage(v->value()); + quantaApp->messageOutput()->showMessage("<<<\n"); +} + +void VariablesListView::slotVariableCopyToClipboard( ) +{ + DebuggerVariable *v = selected(true); + if(!v) + return; + QApplication::clipboard()->setText(v->value()); +} + +#include "variableslistview.moc" diff --git a/quanta/components/debugger/variableslistview.h b/quanta/components/debugger/variableslistview.h new file mode 100644 index 00000000..41de5328 --- /dev/null +++ b/quanta/components/debugger/variableslistview.h @@ -0,0 +1,71 @@ +/*************************************************************************** + variablelistview.h + ------------------------ + begin : 2004-04-04 + copyright : (C) 2004 Thiago Silva + + ***************************************************************************/ + +/**************************************************************************** + * * + * 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 VARIABLESLISTVIEW_H +#define VARIABLESLISTVIEW_H + +#include +#include +#include + +class DebuggerVariable; + +class VariablesListView : public KListView +{ + Q_OBJECT + + enum menuitems + { + setValue = 1, + dumpValue, + copyValue, + removeWatch + }; + + public: + VariablesListView(QWidget *parent = 0, const char *name = 0); + ~VariablesListView(); + + void addVariable(DebuggerVariable* variable); + DebuggerVariable* selected(bool traverse = false); + + DebuggerVariable* first() { return m_variablesList.first(); } + DebuggerVariable* next() { return m_variablesList.next(); } + + void clear(); + + public slots: + void slotRemoveSelected(); + void slotVariableSetValue(); + void slotVariableDump(); + void slotVariableCopyToClipboard(); + void slotVariableContextMenu(KListView *list, QListViewItem * item, const QPoint& point); + + signals: + void valueChanged(DebuggerVariable*); + void removeVariable(DebuggerVariable*); + + private: + void keyPressEvent(QKeyEvent *e); + void replaceVariable(DebuggerVariable* oldvar, DebuggerVariable* newvar); + + QPtrList m_variablesList; + KPopupMenu *m_variablePopup; +}; + +#endif diff --git a/quanta/components/framewizard/Makefile.am b/quanta/components/framewizard/Makefile.am new file mode 100644 index 00000000..ad04c91f --- /dev/null +++ b/quanta/components/framewizard/Makefile.am @@ -0,0 +1,9 @@ +noinst_LTLIBRARIES = libframewizard.la +AM_CPPFLAGS = -I$(top_srcdir)/lib \ + -I$(top_srcdir)/quanta/project \ + -I$(top_srcdir)/quanta/utility \ + $(all_includes) + +libframewizard_la_SOURCES = fmfpeditors.ui fmrceditors.ui framewizards.ui fwglobal.cpp areaattributedb.cpp selectablearea.cpp treenode.cpp visualframeeditor.cpp fmfpeditor.cpp fmrceditor.cpp framewizard.cpp +METASOURCES = AUTO + diff --git a/quanta/components/framewizard/areaattributedb.cpp b/quanta/components/framewizard/areaattributedb.cpp new file mode 100644 index 00000000..96cc77c0 --- /dev/null +++ b/quanta/components/framewizard/areaattributedb.cpp @@ -0,0 +1,40 @@ +/*************************************************************************** + areaattributedb.cpp - description + ------------------- + begin : gio mar 20 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "areaattributedb.h" + +areaAttribute::areaAttribute(){ + resetAttributes(); +} + +void areaAttribute::resetAttributes(){ + m_attributeMap["name"] = ""; + m_attributeMap["longdesc"] = ""; + m_attributeMap["src"] = ""; + m_attributeMap["scrolling"] = "auto"; // default value + m_attributeMap["id"] = ""; + m_attributeMap["style"] = ""; + m_attributeMap["title"] = ""; + m_attributeMap["class"] = ""; + m_attributeMap["noresize"] = "noresize"; + m_attributeMap["frameborder"] = "1"; // default value + m_attributeMap["marginwidth"] = "10"; + m_attributeMap["marginheight"] = "10"; +} +#include "areaattributedb.moc" + + diff --git a/quanta/components/framewizard/areaattributedb.h b/quanta/components/framewizard/areaattributedb.h new file mode 100644 index 00000000..e13682b3 --- /dev/null +++ b/quanta/components/framewizard/areaattributedb.h @@ -0,0 +1,49 @@ +/*************************************************************************** + areaattributedb.h - description + ------------------- + begin : gio mar 20 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 AREAATTRIBUTEDB_H +#define AREAATTRIBUTEDB_H +#include +#include +#include +/**this is + *@author gulmini luciano + */ + +class areaAttribute : public QObject{ + Q_OBJECT + + private: + QRect m_geometry; + QMap m_attributeMap; //tag specific attributes + + public: + areaAttribute(); + ~areaAttribute(){}; + void setAttribute(const QString& name, const QString& value){ m_attributeMap[name] = value; } + void setAllAttributes(QMap map){ m_attributeMap = map; } + void resetAttributes(); + QRect geometry() const { return m_geometry; } + QString src() const{ return m_attributeMap["src"]; } + QString attributeValue(QString l) const { return attributeMap()[l];} + QMap attributeMap() const { return m_attributeMap; } + + public slots: + void setGeometry(QRect g) { m_geometry = g; } +}; + +#endif diff --git a/quanta/components/framewizard/fmfpeditor.cpp b/quanta/components/framewizard/fmfpeditor.cpp new file mode 100644 index 00000000..cc262453 --- /dev/null +++ b/quanta/components/framewizard/fmfpeditor.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + fmfpeditor.cpp - description + ------------------- + begin : mer giu 4 2003 + copyright : (C) 2003 by Gulmini Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "fmfpeditor.h" +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +/*class PreviewWidget : public KPreviewWidgetBase { +};*/ + +fmFPeditor::fmFPeditor() : fmFPeditorS (){ + sbLeft->setWrapping(true); + sbTop->setWrapping(true); + + QString htmlFiles = i18n("*.html *.htm|HTML Files"); + QString phpFiles = i18n("*.php|PHP Files"); + QString xmlFiles = i18n("*.xml|XML Files"); + QString xhtmlFiles = i18n("*xhtml|XHTML Files"); + QString allFiles = i18n("*|All Files"); + + fc->setFilter(htmlFiles+"\n"+phpFiles+"\n"+xmlFiles+"\n"+xhtmlFiles+"\n"+allFiles); + +} +fmFPeditor::~fmFPeditor(){ +} + +QString fmFPeditor::noresizeValue() { + switch(bgNoresize->id(bgNoresize->selected())){ + case 0:return "";break; + default:return "noresize"; + } +} + +QString fmFPeditor::scrollingValue() { + switch(bgScrolling->id(bgScrolling->selected())){ + case 0:return "yes";break; + case 2:return "no";break; + default:return "auto"; + } +} + +QString fmFPeditor::frameborderValue() { + switch(bgBorder->id(bgBorder->selected())){ + case 1:return "0"; break; + default:return "1"; + } +} + +void fmFPeditor::setup(QMap m){ + leId->setText(m["id"]); + fc->setURL(m["src"]); + leClass->setText(m["class"]); + leLongdesc->setText(m["longdesc"]); + leTitle->setText(m["title"]); + leStyle->setText(m["style"]); + leName->setText(m["name"]); + + if(m["noresize"]!="noresize") bgNoresize->setButton(0); + else bgNoresize->setButton(1); + + if(m["scrolling"]=="yes") bgScrolling->setButton(0); + else + if(m["scrolling"]=="no") bgScrolling->setButton(2); + + if(m["frameborder"]=="0") bgBorder->setButton(1); + + sbLeft->setValue(m["marginwidth"].toInt()); + sbTop->setValue(m["marginheight"].toInt()); +} + +QMap fmFPeditor::attributeMap(){ + QMap map; + + map["name"] = leName->text(); + map["longdesc"] = leLongdesc->text(); + map["src"] = fc->url(); + map["scrolling"] = scrollingValue(); + map["id"] = leId->text(); + map["style"] = leStyle->text(); + map["title"] = leTitle->text(); + map["class"] = leClass->text(); + map["noresize"] = noresizeValue(); + map["frameborder"] = frameborderValue(); + map["marginwidth"] = QString::number( sbLeft->value(),10 ); + map["marginheight"] = QString::number( sbTop->value(),10 ); + + return map; +} + +#include "fmfpeditor.moc" diff --git a/quanta/components/framewizard/fmfpeditor.h b/quanta/components/framewizard/fmfpeditor.h new file mode 100644 index 00000000..c434b421 --- /dev/null +++ b/quanta/components/framewizard/fmfpeditor.h @@ -0,0 +1,42 @@ +/*************************************************************************** + fmfpeditor.h - description + ------------------- + begin : mer giu 4 2003 + copyright : (C) 2003 by Gulmini Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 FMFPEDITOR_H +#define FMFPEDITOR_H + +#include + +/** + *@author Gulmini Luciano + */ + +class fmFPeditor : public fmFPeditorS { + Q_OBJECT + + public: + fmFPeditor(); + ~fmFPeditor(); + void setup(QMap); + QMap attributeMap(); + + private: + QString noresizeValue(); + QString scrollingValue(); + QString frameborderValue(); +}; + +#endif diff --git a/quanta/components/framewizard/fmfpeditors.ui b/quanta/components/framewizard/fmfpeditors.ui new file mode 100644 index 00000000..ef8990a9 --- /dev/null +++ b/quanta/components/framewizard/fmfpeditors.ui @@ -0,0 +1,541 @@ + +fmFPeditorS + + + fmFPeditorS + + + + 26 + 5 + 320 + 430 + + + + Frame Properties + + + + unnamed + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + Spacer1 + + + Horizontal + + + Expanding + + + + 55 + 0 + + + + + + pbOk + + + &OK + + + + + pbCancel + + + &Cancel + + + + + + + tw + + + + tab + + + Common + + + + unnamed + + + + bgBorder + + + Border + + + + unnamed + + + 11 + + + 6 + + + + rbBorderYes + + + Yes + + + true + + + + + rbBorderNo + + + No + + + false + + + + + + + gbMargins + + + Margins + + + + unnamed + + + 11 + + + 6 + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + Layout4 + + + + unnamed + + + 0 + + + 6 + + + + TextLabel2_3 + + + From left: + + + + + sbLeft + + + px + + + 10 + + + + + + + Layout3 + + + + unnamed + + + 0 + + + 6 + + + + TextLabel1_3 + + + From top: + + + + + sbTop + + + px + + + 10 + + + + + + + + + + + bgScrolling + + + Scrolling + + + + unnamed + + + 11 + + + 6 + + + + rbScrollingYes + + + Yes + + + + + rbScrollingAuto + + + Auto + + + true + + + + + rbScrollingNo + + + No + + + + + + + bgNoresize + + + Resize + + + false + + + + unnamed + + + 11 + + + 6 + + + + rbResizeYes + + + Yes + + + + + rbResizeNo + + + No + + + true + + + + + + + Layout10 + + + + unnamed + + + 0 + + + 6 + + + + Layout9 + + + + unnamed + + + 0 + + + 6 + + + + tlFrameSource + + + Frame source: + + + + + tlFrameName + + + Frame name: + + + + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + fc + + + + + leName + + + + + + + + + + + tab + + + Others + + + + unnamed + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + tlId + + + Id: + + + + + TextLabel2_2 + + + Class: + + + + + TextLabel3 + + + Style: + + + + + TextLabel4 + + + Title: + + + + + TextLabel6 + + + Long description: + + + + + + + Layout10 + + + + unnamed + + + 0 + + + 6 + + + + leId + + + + + leClass + + + + + leStyle + + + + + leTitle + + + + + leLongdesc + + + + + + + spacer2 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + + + pbOk + clicked() + fmFPeditorS + accept() + + + pbCancel + clicked() + fmFPeditorS + reject() + + + + + diff --git a/quanta/components/framewizard/fmrceditor.cpp b/quanta/components/framewizard/fmrceditor.cpp new file mode 100644 index 00000000..270b3e8c --- /dev/null +++ b/quanta/components/framewizard/fmrceditor.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + fmrceditor.cpp - description + ------------------- + begin : mer giu 4 2003 + copyright : (C) 2003 by Gulmini Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "fmrceditor.h" +#include +#include + +fmRCeditor::fmRCeditor() : fmRCeditorS(){} + +fmRCeditor::~fmRCeditor(){} + +int fmRCeditor::spinBoxValue() const { + return sb->value(); +} + +void fmRCeditor::setLabelText(QString s){ + tl->setText(s); +} + +#include "fmrceditor.moc" diff --git a/quanta/components/framewizard/fmrceditor.h b/quanta/components/framewizard/fmrceditor.h new file mode 100644 index 00000000..55441e91 --- /dev/null +++ b/quanta/components/framewizard/fmrceditor.h @@ -0,0 +1,38 @@ +/*************************************************************************** + fmrceditor.h - description + ------------------- + begin : mer giu 4 2003 + copyright : (C) 2003 by Gulmini Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 FMRCEDITOR_H +#define FMRCEDITOR_H + +#include + +/** + *@author Gulmini Luciano + */ + +class fmRCeditor : public fmRCeditorS { + Q_OBJECT + public: + fmRCeditor(); + ~fmRCeditor(); + public: + int spinBoxValue() const; + void setLabelText(QString); + +}; + +#endif diff --git a/quanta/components/framewizard/fmrceditors.ui b/quanta/components/framewizard/fmrceditors.ui new file mode 100644 index 00000000..25cd41bd --- /dev/null +++ b/quanta/components/framewizard/fmrceditors.ui @@ -0,0 +1,149 @@ + +fmRCeditorS + + + fmRCeditorS + + + + 0 + 0 + 300 + 150 + + + + + 5 + 5 + 0 + 0 + + + + + 300 + 150 + + + + + 300 + 150 + + + + Rows Columns Editor + + + + unnamed + + + 11 + + + 6 + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + tl + + + + + + + + sb + + + 0 + + + 2 + + + + + + + Layout3 + + + + unnamed + + + 0 + + + 6 + + + + Spacer8 + + + Horizontal + + + Expanding + + + + 31 + 0 + + + + + + pbOk + + + &OK + + + + + pbCancel + + + &Cancel + + + + + + + + + pbOk + clicked() + fmRCeditorS + accept() + + + pbCancel + clicked() + fmRCeditorS + reject() + + + + diff --git a/quanta/components/framewizard/framewizard.cpp b/quanta/components/framewizard/framewizard.cpp new file mode 100644 index 00000000..2f3903dd --- /dev/null +++ b/quanta/components/framewizard/framewizard.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + framewizard.cpp - description + ------------------- + begin : mer giu 4 14:14:07 CEST 2003 + copyright : (C) |YEAR| by Gu2003Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "framewizard.h" +#include "fmrceditor.h" +#include "fmfpeditor.h" +#include +//#include +#include +#include + +#include "fwglobal.h" + +static const QString info1=i18n("You must select an area."), + info2=i18n("Before editing a frame you must save the file."); + +FrameWizard::FrameWizard(QWidget *parent, const char *name) : FrameWizardS(parent, name), +m_hasSelected(false),m_saved(false) +{ + m_hasSelected = false; + m_currSA=vfe->internalTree()->root()->label(); + connect(this, SIGNAL(launchDraw()), this, SLOT(draw())); + connect(vfe, SIGNAL(areaSelected(const QString &)), this, SLOT(catchSelectedArea(const QString &))); + + connect(pbHorizontal, SIGNAL(clicked()), this, SLOT(split())); + connect(pbVertical, SIGNAL(clicked()), this, SLOT(split())); + connect(pbEditFrame, SIGNAL(clicked()), this, SLOT(showFrameEditorDlg())); + connect(pbReset, SIGNAL(clicked()), this, SLOT(reset())); + connect(pbDelete, SIGNAL(clicked()), this, SLOT(remove())); +} + +FrameWizard::~FrameWizard(){ +#define QT_CHECK_NULL +Q_CHECK_PTR( vfe ); +} + +void FrameWizard::catchSelectedArea(const QString &id ){ + m_currSA = id; //is the current SelectableArea selected + m_hasSelected = true;// a SelectableArea has been selected +} + +void FrameWizard::split(){ + if(m_hasSelected) { + int split = 0; + QString currNodeLabel = m_currSA; + QString senderName=sender()->name(); + if(senderName=="pbHorizontal"){ + split = showRCeditorDlg(i18n("Enter the desired number of rows:")); + if(split>=2) vfe->split(currNodeLabel,split,HORIZONTAL); + } + else + if(senderName=="pbVertical"){ + split = showRCeditorDlg(i18n("Enter the desired number of columns:")); + if(split>=2) vfe->split(currNodeLabel,split,VERTICAL); + } + emit launchDraw(); + } + else KMessageBox::information( this, info1, i18n("Warning") ); + m_hasSelected=false; +} + +void FrameWizard::draw(){ + vfe->draw(); +} + +int FrameWizard::showRCeditorDlg(const QString &s){ + int res = 0; + fmRCeditor *dlg = new fmRCeditor; + dlg->setLabelText(s); + if(dlg->exec()) res = dlg->spinBoxValue(); + delete dlg; + return res; +} + +void FrameWizard::showFrameEditorDlg(){ + if(m_saved){ + if(m_hasSelected) { + fmFPeditor *dlg = new fmFPeditor(); + dlg->setup(vfe->internalTree()->findAreaAttribute(m_currSA)->attributeMap()); + if(dlg->exec()) { + vfe->internalTree()->findAreaAttribute(m_currSA)->setAllAttributes(dlg->attributeMap()); + vfe->draw(); + } + delete dlg; + } + else KMessageBox::information( this, info1, i18n("Warning") ); + m_hasSelected=false; + } + else KMessageBox::information( this, info2, i18n("Warning") ); +} + +void FrameWizard::reset(){ + vfe->internalTree()->reset(); + draw(); +} + +void FrameWizard::remove(){ + if(m_hasSelected) { + vfe->removeNode(m_currSA); + draw(); + } + else KMessageBox::information( this, info1, i18n("Warning") ); + m_hasSelected=false; +} + +#include "framewizard.moc" diff --git a/quanta/components/framewizard/framewizard.h b/quanta/components/framewizard/framewizard.h new file mode 100644 index 00000000..22e93789 --- /dev/null +++ b/quanta/components/framewizard/framewizard.h @@ -0,0 +1,61 @@ +/*************************************************************************** + framewizard.h - description + ------------------- + begin : mer giu 4 14:14:07 CEST 2003 + copyright : (C) |YEAR| by Gu2003Luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 FRAMEWIZARD_H +#define FRAMEWIZARD_H + +#include +#include "visualframeeditor.h" +class QStringList; + +/** FrameWizard is the base class of the project */ +class FrameWizard : public FrameWizardS +{ + Q_OBJECT + private: + bool m_hasSelected, + m_saved; // if saved = false the the file containing the frameset structure + // has been not saved and so you cannot edit the frame + // This is for me: se non si salva il file no si riesce a conoscere il + // percorso relativo dei file da mettere nell'attributo src + QString m_currSA; + + public: + FrameWizard( QWidget* parent=0, const char *name=0); + ~FrameWizard(); + + private slots: + void showFrameEditorDlg(); + void reset(); + void remove(); + void catchSelectedArea(const QString &id ); + void split(); + void draw(); + int showRCeditorDlg(const QString &s); + + public : + void loadExistingFramesetStructure(const QStringList &list){ vfe->loadExistingStructure(list);} + QString generateFramesetStructure(){ return vfe->framesetStructure(); } + void setSaved( bool b){ m_saved=b; } + void setMarkupLanguage(const QString& s){ vfe->setMarkupLanguage(s);} + + signals: + void launchDraw(); + +}; + +#endif diff --git a/quanta/components/framewizard/framewizards.ui b/quanta/components/framewizard/framewizards.ui new file mode 100644 index 00000000..a06d321b --- /dev/null +++ b/quanta/components/framewizard/framewizards.ui @@ -0,0 +1,369 @@ + +FrameWizardS + + + FrameWizardS + + + + 0 + 0 + 640 + 482 + + + + + 5 + 5 + 0 + 0 + + + + + 0 + 0 + + + + + 32767 + 32767 + + + + Frame Wizard + + + + unnamed + + + 11 + + + 6 + + + + Layout2 + + + + unnamed + + + 0 + + + 6 + + + + pbHelp + + + &Help + + + + + Spacer1 + + + Horizontal + + + Expanding + + + + 30 + 0 + + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + pbOk + + + &OK + + + + + pbCancel + + + &Cancel + + + + + + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + Layout9 + + + + unnamed + + + 0 + + + 6 + + + + tl + + + + + Spacer6 + + + Vertical + + + Expanding + + + + 0 + 30 + + + + + + ButtonGroup4 + + + + 0 + 0 + 0 + 0 + + + + Splitting + + + + unnamed + + + 11 + + + 6 + + + + pbVertical + + + Vertical + + + + + pbHorizontal + + + Horizontal + + + + + + + Spacer9 + + + Vertical + + + Expanding + + + + 0 + 16 + + + + + + ButtonGroup5 + + + + 0 + 0 + 0 + 0 + + + + Editing + + + + unnamed + + + 11 + + + 6 + + + + pbEditFrame + + + Edit Frame + + + + + pbDelete + + + true + + + Delete + + + + + pbReset + + + true + + + Reset + + + + + + + Spacer5 + + + Vertical + + + Expanding + + + + 0 + 30 + + + + + + + + vfe + + + + 3 + 3 + 0 + 0 + + + + ClickFocus + + + + + + + + + VisualFrameEditor +
visualframeeditor.h
+ + -1 + -1 + + 0 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f + + + + + pbCancel + clicked() + FrameWizardS + close() + + + pbOk + clicked() + FrameWizardS + accept() + + + + + + visualframeeditor.h + +
diff --git a/quanta/components/framewizard/fwglobal.cpp b/quanta/components/framewizard/fwglobal.cpp new file mode 100644 index 00000000..f2f971da --- /dev/null +++ b/quanta/components/framewizard/fwglobal.cpp @@ -0,0 +1,22 @@ +/*************************************************************************** + fwglobal.cpp - description + ------------------- + begin : mar feb 17 2004 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "fwglobal.h" + +int proxInt(double d){ + if((d-int(d))>= 0.5 ) return int(d)+1; + return int(d); +} diff --git a/quanta/components/framewizard/fwglobal.h b/quanta/components/framewizard/fwglobal.h new file mode 100644 index 00000000..9377012c --- /dev/null +++ b/quanta/components/framewizard/fwglobal.h @@ -0,0 +1,24 @@ +/*************************************************************************** + fwglobal.h - description + ------------------- + begin : mar feb 17 2004 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 FWGLOBAL_H +#define FWGLOBAL_H + +enum SplitType{ HORIZONTAL,VERTICAL,NONE }; + +int proxInt(double d); + +#endif diff --git a/quanta/components/framewizard/selectablearea.cpp b/quanta/components/framewizard/selectablearea.cpp new file mode 100644 index 00000000..32ea234b --- /dev/null +++ b/quanta/components/framewizard/selectablearea.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + selectablearea.cpp - description + ------------------- + begin : mer mar 5 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "selectablearea.h" +#include +//#include +#include "fwglobal.h" + +SelectableArea::SelectableArea(QWidget *parent, const char *name ) : KHTMLPart(parent,name) { + view()->setFrameShape(QFrame::NoFrame); + view()->setMinimumSize(QSize(1,1)); + view()->installEventFilter(this); +} + +SelectableArea::~SelectableArea(){} + +bool SelectableArea::eventFilter(QObject *o, QEvent *event){ + switch ( event->type() ) { + case QEvent::FocusIn : { + view()->setFrameShape(QFrame::Box); + view()->setFrameShadow ( QFrame::Plain ); + view()->setLineWidth(2); + emit selected(m_idLabel); + return true; + }; + break; + case QEvent::FocusOut : { + view()->setFrameShape(QFrame::NoFrame); + return true; + } + break; + case QEvent::Resize : { + emit Resized( view()->geometry() ); + view()->hide(); + view()->show(); + return true; + } + break; + default: return KHTMLPart::eventFilter( o, event ); + } +} + +#include "selectablearea.moc" diff --git a/quanta/components/framewizard/selectablearea.h b/quanta/components/framewizard/selectablearea.h new file mode 100644 index 00000000..252ec6c9 --- /dev/null +++ b/quanta/components/framewizard/selectablearea.h @@ -0,0 +1,53 @@ +/*************************************************************************** + selectablearea.h - description + ------------------- + begin : mer mar 5 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 SELECTABLEAREA_H +#define SELECTABLEAREA_H + +//#include +#include +#include + +/**a QTextBrowser that can be selected + *@author gulmini luciano + */ + + +class SelectableArea : public KHTMLPart { + Q_OBJECT + + public : + SelectableArea(QWidget *parent=0, const char *name=0); + ~SelectableArea(); + QString idLabel() const { return m_idLabel; } + void setIdLabel(const QString &i) { m_idLabel = i; } + void setSource(const QString& s) { if(!s.isEmpty()) openURL( KURL(s) ); } + + protected : + virtual bool eventFilter(QObject*, QEvent*); + + private : + QString m_idLabel; + + signals : + void selected(const QString &); + void Resized(QRect); +}; + + + +#endif diff --git a/quanta/components/framewizard/treenode.cpp b/quanta/components/framewizard/treenode.cpp new file mode 100644 index 00000000..fcb60231 --- /dev/null +++ b/quanta/components/framewizard/treenode.cpp @@ -0,0 +1,135 @@ +/*************************************************************************** + treenode.cpp - description + ------------------- + begin : lun mar 17 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "treenode.h" + +static const int SIZE = 101; + +treeNode::treeNode(const QString &l, const QString &pl) : m_label(l), m_parentLabel(pl), m_splitType(NONE){ + m_childrenList.setAutoDelete(true); + m_atts = new areaAttribute; +} + +treeNode::~treeNode(){ + delete m_atts; +} + +void treeNode::addChildNode(const QString &l) { + m_childrenList.append( new treeNode(l,m_label) ); +} + +void treeNode::removeChildNode(const QString &l,bool autoDelete) { + m_childrenList.setAutoDelete(autoDelete); + m_childrenList.remove(findChild(l)); +} + +treeNode* treeNode::findChild(const QString &l){ + QPtrListIterator it( m_childrenList ); + treeNode *node; + while ( (node = it.current()) != 0 ) { + ++it; + if(node->label() == l) return node; + } + return 0L; +} + +int tree::nodeId = 0; + +tree::tree(){ + m_root = new treeNode(QString::number(nodeId,10)); + m_nodeList.resize(SIZE); +} + +tree::~tree(){ + delete m_root; +} + +void tree::refreshGeometries(treeNode *n){ + int dim = -6;// so we won't add exceeding pixels + + if(n->hasChildren()){ + n->firstChild(); + while(n->currentChild()){ + refreshGeometries(n->currentChild()); + n->nextChild(); + } + + QPtrList list = n->childrenList(); + QPtrListIterator it( list ); + treeNode *node= it.current(); + QRect newGeometry = n->atts()->geometry(); + if(n->splitType()==VERTICAL){ + newGeometry.setHeight(node->atts()->geometry().height()); + while ( (node = it.current()) != 0 ) { + ++it; + dim += node->atts()->geometry().width(); + dim += 6; + } + newGeometry.setWidth(dim); + } + else + if(n->splitType()==HORIZONTAL){ + newGeometry.setWidth(node->atts()->geometry().width()); + while ( (node = it.current()) != 0 ) { + ++it; + dim += node->atts()->geometry().height(); + dim += 6; + } + newGeometry.setHeight(dim); + } + + n->atts()->setGeometry( newGeometry ); + } +} + +treeNode* tree::findNode(const QString &l){ + if(l==m_root->label()) return m_root; + return m_nodeList.find(l); +} + +QString tree::addChildNode(const QString &l){ + treeNode *node; + if( (node = findNode(l)) != 0) { + ++nodeId; + treeNode *newNode = new treeNode(QString::number(nodeId,10),node->label()); + newNode->atts()->setAttribute( "src",node->atts()->src() ); + node->addChildNode(newNode); + m_nodeList.insert(QString::number(nodeId,10),newNode); + } + return QString::number(nodeId,10); +} + +bool tree::insertChildNode(const QString &l){ + QString parent = findNode(l)->parentLabel(); + int pos=findNode( parent )->childPosition( findNode(l) ); + ++nodeId; + treeNode *newNode = new treeNode(QString::number(nodeId,10),parent); + newNode->atts()->setAttribute( "src",findNode(l)->atts()->src() ); + m_nodeList.insert(QString::number(nodeId,10),newNode); + return findNode( parent )->insertChild(pos,newNode); +} + +void tree::reset(){ + nodeId = 1; + m_root->removeChildren(); + m_root->atts()->resetAttributes(); + m_nodeList.clear(); +} + +void tree::removeChildNode(const QString &pl,const QString &l,bool autoDelete){ + findNode(pl)->removeChildNode(l,autoDelete); +} diff --git a/quanta/components/framewizard/treenode.h b/quanta/components/framewizard/treenode.h new file mode 100644 index 00000000..c2d0f3d6 --- /dev/null +++ b/quanta/components/framewizard/treenode.h @@ -0,0 +1,87 @@ +/*************************************************************************** + treenode.h - description + ------------------- + begin : lun mar 17 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 TREENODE_H +#define TREENODE_H + +#include +#include +#include + +#include "fwglobal.h" +#include "areaattributedb.h" + +/**a node in the tree + *@author gulmini luciano + */ +class treeNode { + private: + QString m_label, + m_parentLabel; + SplitType m_splitType; + QPtrList m_childrenList; + areaAttribute *m_atts; + + public: + treeNode(const QString &l=QString::null, const QString &pl=QString::null); + ~treeNode(); + void addChildNode(const QString &L); + void addChildNode(treeNode *n){ m_childrenList.append(n); } + void removeChildNode(const QString &l, bool autoDelete); + void setSplitType(SplitType s) { m_splitType = s; } + void setLabel(const QString &l) { m_label = l; } + void removeChildren() { m_childrenList.clear(); } + void setParentLabel(const QString &s){ m_parentLabel = s;} + int childPosition(treeNode* n){ return m_childrenList.find(n); } + bool insertChild(unsigned int pos, treeNode* n) { return m_childrenList.insert( pos, n); } + QString label() const { return m_label; } + QString parentLabel() const { return m_parentLabel; } + SplitType splitType() const { return m_splitType; } + QPtrList childrenList() { return m_childrenList; } + + treeNode* firstChild() { return m_childrenList.first(); } + treeNode* nextChild() { return m_childrenList.next(); } + treeNode* lastChild() { return m_childrenList.last(); } + treeNode* currentChild() { return m_childrenList.current(); } + treeNode* findChild(const QString &L); + + areaAttribute* atts() { return m_atts; } + + int countChildren() const { return m_childrenList.count(); } + bool hasChildren() const { return !m_childrenList.isEmpty(); } +}; + +class tree{ + private: + treeNode *m_root; + QDict m_nodeList; + static int nodeId; + + public: + tree(); + ~tree(); + treeNode* root() const { return m_root; } + QString addChildNode(const QString &l); + bool insertChildNode(const QString &L); + void removeChildNode(const QString &pl,const QString &l,bool autoDelete);//parent node,child node + treeNode* findNode(const QString &L); + areaAttribute* findAreaAttribute(const QString &l){ return findNode(l)->atts(); }; + void reset(); + void refreshGeometries(treeNode*); +}; + +#endif diff --git a/quanta/components/framewizard/visualframeeditor.cpp b/quanta/components/framewizard/visualframeeditor.cpp new file mode 100644 index 00000000..3871ac61 --- /dev/null +++ b/quanta/components/framewizard/visualframeeditor.cpp @@ -0,0 +1,449 @@ +/*************************************************************************** + visualframeeditor.cpp - description + ------------------- + begin : mar mar 25 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "visualframeeditor.h" + +#include +#include +//#include + +#include "qextfileinfo.h" +#include "project.h" + +static int cancelledPixels(int n){ + return (n-1)*6; +} + +QMap > SIZES; +static int splitterIdNumber = 0; + + +VisualFrameEditor::VisualFrameEditor(QWidget * parent, const char * name) : QHBox(parent,name){ + m_internalTree = new tree; + m_internalTree->root()->atts()->setGeometry(QRect(0,0,510,422)); + m_firstInsertedSA = 0L; + m_markupLanguage = HTML; +} + +VisualFrameEditor::~VisualFrameEditor(){ + delete m_internalTree; + delete m_firstInsertedSA; +} + +void VisualFrameEditor::setGeometries(const QString &l){ + int cP = cancelledPixels(m_internalTree->findNode(l)->countChildren()); + QRect newGeometry(m_internalTree->findNode(l)->atts()->geometry()); + QPtrList list=m_internalTree->findNode(l)->childrenList(); + QPtrListIterator it( list ); + treeNode *node; + if(m_internalTree->findNode(l)->splitType() == VERTICAL){ + int dummyDimension=m_internalTree->findNode(l)->atts()->geometry().width()-cP; + while ( (node = it.current()) != 0 ) { + ++it; + newGeometry.setWidth( int(dummyDimension/m_internalTree->findNode(l)->countChildren()) ); + m_internalTree->findNode(node->label())->atts()->setGeometry(newGeometry); + } + } + else + if(m_internalTree->findNode(l)->splitType() == HORIZONTAL){ + int dummyDimension=m_internalTree->findNode(l)->atts()->geometry().height()-cP; + while ( (node = it.current()) != 0 ) { + ++it; + newGeometry.setHeight( int(dummyDimension/m_internalTree->findNode(l)->countChildren()) ); + m_internalTree->findNode(node->label())->atts()->setGeometry(newGeometry); + } + } +} + +void VisualFrameEditor::split(const QString &l, int n, SplitType type) { + if(l==m_internalTree->root()->label()){ + m_internalTree->root()->setSplitType(type); + for(int i = 1; i<=n; i++) m_internalTree->addChildNode(l); + setGeometries(l); + } + else { + QString parentLabel=m_internalTree->findNode(l)->parentLabel(); + SplitType parentSplit=m_internalTree->findNode(parentLabel)->splitType(); + if( parentSplit != type ) { + m_internalTree->findNode(l)->setSplitType(type); + for(int i = 1; i<=n; i++) m_internalTree->addChildNode(l); + setGeometries(l); + } + else { + for(int i = 1; i<=n; i++) m_internalTree->insertChildNode(l); + m_internalTree->findNode(parentLabel)->removeChildNode(l,true); + setGeometries(m_internalTree->findNode(parentLabel)->label()); + } + } +} + +void VisualFrameEditor::loadExistingStructure(const QStringList &list){ + if(!list.isEmpty()) { + m_existingStructure = list; + m_existingStructure.remove("");//closure tag not needed + buildInternalTree(m_internalTree->root()->label()); + } +} + +QStringList VisualFrameEditor::convertAsterisks(const QString &s,int d){ + QStringList list=QStringList::split(",",s); + int leftPercentage = 100; + int leftPercentageDistributedAmongAsterisks=0; + int weightAsteriskCounter=0; + // This for is used to determine how much percentage must be assign to an asterisk + // example cols="40%,5*,*" + // then every asterisk must be assigned a percentage of 10% so the real percentage + // notation is cols="40%,50%,10%" + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if(!(*it).contains("%") && !(*it).contains("*")) leftPercentage -= ( (*it).toInt()*100 )/d; + if((*it).contains("%")) leftPercentage -= (*it).section("%",0,0).toInt(); + if((*it).contains("*")) { + int weight= (*it).section("*",0,0).toInt(); + if( weight==0 ) weight=1; + weightAsteriskCounter += weight; + } + } + + if(weightAsteriskCounter!=0) leftPercentageDistributedAmongAsterisks = proxInt(double(leftPercentage)/double(weightAsteriskCounter)); + // this for changes asterisk notation in percentage notation + // This part of the comment is for me: + // NB: I valori delle percentuali generati da if .. else possono non corrispondere + // a quelli effettivamente generati dal metodo build che opera un'altra normalizzazione. + // In genere la differenza �dell' 1% + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if((*it).contains("*")){ + int weight= (*it).section("*",0,0).toInt(); + if(weight==0) weight=1; + int newPercentage = weight*leftPercentageDistributedAmongAsterisks; + (*it)=(QString::number(newPercentage,10)+"%"); + leftPercentage-=newPercentage; + } + } + return list; +} + +void VisualFrameEditor::buildInternalTree(const QString &parent){ + QString line = m_existingStructure.first(); + if(line.contains("findNode(parent)->atts()->geometry(); + QStringList percentages = convertAsterisks(pattern.cap(1),dummy.height()); + + int dummyDimension=dummy.height()-cancelledPixels(line.contains(",")+1); + + QPtrList list=m_internalTree->findNode(parent)->childrenList(); + QPtrListIterator it( list ); + treeNode *node; + while ( (node = it.current()) != 0 ) { + ++it; + QRect newGeometry(dummy); + double newDimension; + if(percentages.first().contains("%")) + newDimension=(dummyDimension*(percentages.first().remove("%").toInt()))/100.0; + else newDimension=(double)percentages.first().toInt(); + newGeometry.setHeight( proxInt(newDimension) ); + node->atts()->setGeometry(newGeometry); + percentages.pop_front(); + } + } + else + if(line.contains("cols")) { + split(parent,(line.contains(",")+1),VERTICAL); + QRegExp pattern("cols\\s*=\"([\\s\\d%,\\*]*)\""); + pattern.search(line); + + QRect dummy=m_internalTree->findNode(parent)->atts()->geometry(); + QStringList percentages = convertAsterisks(pattern.cap(1),dummy.width()); + + int dummyDimension=dummy.width()-cancelledPixels(line.contains(",")+1); + + QPtrList list=m_internalTree->findNode(parent)->childrenList(); + QPtrListIterator it( list ); + treeNode *node; + while ( (node = it.current()) != 0 ) { + ++it; + QRect newGeometry(dummy); + double newDimension; + if(percentages.first().contains("%")) + newDimension=(dummyDimension*(percentages.first().remove("%").toInt()))/100.0; + else newDimension=(double)percentages.first().toInt(); + newGeometry.setWidth( proxInt(newDimension) ); + node->atts()->setGeometry(newGeometry); + percentages.pop_front(); + } + } + + m_existingStructure.pop_front(); + m_internalTree->findNode(parent)->firstChild(); + while(m_internalTree->findNode(parent)->currentChild()) { + buildInternalTree(m_internalTree->findNode(parent)->currentChild()->label()); + m_internalTree->findNode(parent)->nextChild(); + } + } + else { + QMap attributeMap; + if( line.contains( QRegExp("\\s+noresize") ) ) attributeMap["noresize"] = "noresize"; + else attributeMap["noresize"] = QString::null; + + QRegExp srcPattern("\\s+src\\s*=\\s*\"([%-\\w\\s\\./_\\+\\d]*)\""); //search for files + if(srcPattern.search(line) !=-1 ) { + KURL pathToConvert, basePath; + pathToConvert.setPath(srcPattern.cap(1)); + basePath.setPath( Project::ref()->projectBaseURL().path() ); + attributeMap["src"] = QExtFileInfo::toAbsolute( pathToConvert, basePath ).path(); + line.remove(srcPattern);//we don't need to operate on this anymore + } + + QRegExp pattern("\\s+(\\w+\\s*=\\s*\"[\\w\\s\\./_\\+\\d]*\")"); + + int pos = 0; + while ( pos >= 0 ) { + pos = pattern.search( line, pos ); + attributeMap[ pattern.cap(1).section( QRegExp("=\\s*\"") ,0,0) ] = pattern.cap(1).section(QRegExp("=\\s*\""),1,1).remove("\""); + if ( pos >= 0 ) pos += pattern.matchedLength(); + } + m_internalTree->findNode(parent)->atts()->setAllAttributes(attributeMap); + m_existingStructure.pop_front(); + } +} + +void VisualFrameEditor::paintEvent ( QPaintEvent * ){ + hide(); + delete m_firstInsertedSA; + m_firstInsertedSA = 0L; + + QObjectList* splitterList = queryList("QSplitter"); + for (uint i = 0; i < splitterList->count(); i++) { + QObject* o = splitterList->at(i); + removeChild(o); //this will delete all childr of "o" + } + + delete splitterList; + splitterIdNumber = 0; + drawGUI( m_internalTree->root(), this); + show(); +} + +void VisualFrameEditor::removeNode(const QString &l){ + if( l == m_internalTree->root()->label() ) m_internalTree->reset();//trying to remove root node is equivalent to reinitialize + else { + QString parentLabel=m_internalTree->findNode(l)->parentLabel(); + if(m_internalTree->findNode(parentLabel)->countChildren()>=3) + m_internalTree->removeChildNode(parentLabel,l,true); + else { + m_internalTree->removeChildNode(parentLabel,l,true); + if( !m_internalTree->findNode(parentLabel)->firstChild()->hasChildren() ){ //final nodes + QMap map = m_internalTree->findNode(parentLabel)->firstChild()->atts()->attributeMap(); + m_internalTree->findNode(parentLabel)->removeChildren(); + m_internalTree->findNode(parentLabel)->atts()->setAllAttributes( map ) ; + m_internalTree->findNode(parentLabel)->setSplitType(NONE); + } + else { + QPtrList list = m_internalTree->findNode(parentLabel)->firstChild()->childrenList(); + if( parentLabel != m_internalTree->root()->label() ) { + QString grandParentLabel = m_internalTree->findNode(parentLabel)->parentLabel(); + m_internalTree->removeChildNode( parentLabel,m_internalTree->findNode(parentLabel)->firstChild()->label(),false ); + m_internalTree->removeChildNode( grandParentLabel ,parentLabel, true ); + treeNode *node; + for ( node = list.first(); node; node = list.next() ) { + node->setParentLabel(grandParentLabel); + m_internalTree->findNode(grandParentLabel)->addChildNode(node); + } + } + else { + m_internalTree->findNode(parentLabel)->setSplitType( m_internalTree->findNode(parentLabel)->firstChild()->splitType() ); + m_internalTree->removeChildNode( parentLabel,m_internalTree->findNode(parentLabel)->firstChild()->label(),false ); + treeNode *node; + for ( node = list.first(); node; node = list.next() ) { + node->setParentLabel(parentLabel); + m_internalTree->findNode(parentLabel)->addChildNode(node); + } + } + } + } + } +} + +void VisualFrameEditor::drawGUI(treeNode *n, QWidget* parent){ + if(n->hasChildren()) { + QString splitterName("splitter"+QString::number(++splitterIdNumber,10)); + QSplitter *splitter = new QSplitter(parent,splitterName); + if(SIZES.contains(splitterName)) splitter->setSizes( SIZES[splitterName] ); + switch( n->splitType() ){ + case VERTICAL : splitter->setOrientation(QSplitter::Horizontal);break; + case HORIZONTAL : splitter->setOrientation(QSplitter::Vertical);break; + default:break; + } + n->firstChild(); + while(n->currentChild()) { + drawGUI(n->currentChild(),splitter); + n->nextChild(); + } + } + else { + SelectableArea *sa=new SelectableArea(parent,n->label()); + if(parent->isA("QSplitter")) dynamic_cast(parent)->setResizeMode(sa->view(),QSplitter::KeepSize ); + else + if(!m_firstInsertedSA) m_firstInsertedSA = sa; + sa->view()->setGeometry(n->atts()->geometry()); + sa->setIdLabel( n->label() ); + sa->setSource( n->atts()->src() ); + connect(sa, SIGNAL(Resized(QRect)), m_internalTree->findNode(sa->idLabel())->atts(), SLOT(setGeometry(QRect))); + connect(sa, SIGNAL(selected(const QString &)),this, SIGNAL(areaSelected(const QString &))); + } +} + +QString VisualFrameEditor::createFrameTag(areaAttribute *a){ + QString Src(a->attributeValue("src")), + Longdesc(a->attributeValue("longdesc")), + Name(a->attributeValue("name")), + Scrolling(a->attributeValue("scrolling")), + Id(a->attributeValue("id")), + Style(a->attributeValue("style")), + Title(a->attributeValue("title")), + Class(a->attributeValue("class")), + Noresize(a->attributeValue("noresize")), + Frameborder(a->attributeValue("frameborder")), + Marginwidth(a->attributeValue("marginwidth")), + Marginheight(a->attributeValue("marginheight")); + + QString tagBegin="projectBaseURL().path() ); + KURL u; + u.setPath(Src); + tagMiddle+= (" src=\"" + QExtFileInfo::toRelative( u, base).path() + "\""); + } + + if( !Longdesc.isEmpty() ) + tagMiddle+= (" longdesc=\""+Longdesc+"\""); + //if( !Name.isEmpty() ) + tagMiddle+=(" name=\""+Name+"\""); + if( Scrolling!="auto" && !Scrolling.isEmpty() ) tagMiddle+=(" scrolling=\""+Scrolling+"\""); + if( !Id.isEmpty() ) tagMiddle+=(" id=\""+Id+"\""); + if( !Style.isEmpty() ) tagMiddle+=(" style=\""+Style+"\""); + if( !Title.isEmpty() ) tagMiddle+=(" title=\""+Title+"\""); + if( !Class.isEmpty() ) tagMiddle+=(" class=\""+Class+"\""); + if( Frameborder=="0" ) tagMiddle+=(" frameborder=\""+Frameborder+"\""); + if( Marginwidth!="0" && !Marginwidth.isEmpty() ) tagMiddle+=(" marginwidth=\""+Marginwidth+"\""); + if( Marginheight!="0" && !Marginheight.isEmpty()) tagMiddle+=(" marginheight=\""+Marginheight+"\""); + + switch(m_markupLanguage){ + case HTML: if( Noresize=="noresize" ) tagMiddle+=(" "+Noresize); + tagEnd=">\n";break; + case XHTML: if( Noresize=="noresize" ) tagMiddle+=(" noresize=\""+Noresize+"\""); + tagEnd="/>\n";break; + default:; + } + + return tagBegin+tagMiddle+tagEnd; +} + +QString VisualFrameEditor::RCvalue(treeNode *n) { + QString s; + QMap dimMap; + double percentage = 100.0; + int remainingPercentage=100; + int child_number = n->countChildren(); + int lostPixels = (6*(child_number-1)); // 6 pixels are lost every time a splitter is drawn + + switch( n->splitType() ) { + case VERTICAL: percentage/=n->atts()->geometry().width(); + for(int i=1;i<=child_number;++i) dimMap[i]=n->childrenList().at(i-1)->atts()->geometry().width(); + break; + case HORIZONTAL: percentage/=n->atts()->geometry().height(); + for(int i=1;i<=child_number;++i) dimMap[i]=n->childrenList().at(i-1)->atts()->geometry().height(); + break; + default:break; + } + + while( lostPixels > 0) { + for(int i=1;i<=child_number;++i){ + dimMap[i]+=1; + lostPixels--; + if(lostPixels == 0) break; + } + } + + for(int i=1;i<=child_number-1;++i) { + remainingPercentage-=proxInt(dimMap[i]*percentage); + s+=QString::number(proxInt(dimMap[i]*percentage),10); + s+="%,"; + } + + return s+=(QString::number(remainingPercentage,10)+"%"); +} + +static QStringList nonFormattedStructure; + +void VisualFrameEditor::createStructure(treeNode* n){ + if(n==m_internalTree->root() && !n->hasChildren()) return; + if(n->hasChildren()) { + switch( n->splitType() ){ + case VERTICAL: nonFormattedStructure.append("\n");break; + case HORIZONTAL: nonFormattedStructure.append("\n");break; + default:break; + } + n->firstChild(); + while(n->currentChild()){ + createStructure(n->currentChild()); + n->nextChild(); + } + nonFormattedStructure.append("\n"); + } + else nonFormattedStructure.append(createFrameTag(n->atts())); +} + +QString VisualFrameEditor::formatStructure(){ + QString s; + int tabNum = 0; + for ( QStringList::Iterator it = nonFormattedStructure.begin(); it != nonFormattedStructure.end(); ++it ) { + if((*it).contains("")) { + tabNum--; + s.truncate(s.length()-1); + } + s+=*it; + for(int i=1;i<=tabNum;i++) s+='\t'; + } + nonFormattedStructure.clear(); + return s; +} + +QString VisualFrameEditor::framesetStructure() { + m_internalTree->refreshGeometries(m_internalTree->root()); + createStructure(m_internalTree->root()); + return formatStructure(); +} + +void VisualFrameEditor::setMarkupLanguage(const QString& s){ + if( s.contains("xhtml",false)!=0 ) m_markupLanguage = XHTML; + else + if( s.contains("html",false)!=0 ) m_markupLanguage = HTML; +} + +#include "visualframeeditor.moc" diff --git a/quanta/components/framewizard/visualframeeditor.h b/quanta/components/framewizard/visualframeeditor.h new file mode 100644 index 00000000..4924f3cb --- /dev/null +++ b/quanta/components/framewizard/visualframeeditor.h @@ -0,0 +1,66 @@ +/*************************************************************************** + visualframeeditor.h - description + ------------------- + begin : mar mar 25 2003 + copyright : (C) 2003 by gulmini luciano + email : gulmini.luciano@student.unife.it + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 VISUALFRAMEEDITOR_H +#define VISUALFRAMEEDITOR_H + +#include "treenode.h" +#include "selectablearea.h" +#include + +/** + *@author gulmini luciano + */ + + +class VisualFrameEditor : public QHBox { + Q_OBJECT + private: + enum MarkupLanguage{XHTML,HTML}; + tree *m_internalTree; + SelectableArea* m_firstInsertedSA; + QStringList m_existingStructure; + MarkupLanguage m_markupLanguage; + + void buildInternalTree(const QString &parent); + void setGeometries(const QString &l); + void drawGUI(treeNode *n, QWidget* parent); + QStringList convertAsterisks(const QString &s, int d); + + QString createFrameTag(areaAttribute *a); + QString formatStructure(); + QString RCvalue(treeNode *n); + void createStructure(treeNode* n); + + public: + VisualFrameEditor( QWidget * parent = 0, const char * name = 0); + ~VisualFrameEditor(); + void draw() { repaint(); } + void loadExistingStructure(const QStringList &list); + QString framesetStructure(); + void removeNode(const QString &l); + void split(const QString &l, int n, SplitType type); + void setMarkupLanguage(const QString& s); + tree* internalTree() { return m_internalTree;} + + protected: + virtual void paintEvent ( QPaintEvent * ); + signals: + void areaSelected(const QString &); +}; + +#endif diff --git a/quanta/components/tableeditor/Makefile.am b/quanta/components/tableeditor/Makefile.am new file mode 100644 index 00000000..242fae89 --- /dev/null +++ b/quanta/components/tableeditor/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libtableeditor.la + +libtableeditor_la_SOURCES = tableeditors.ui tableeditor.cpp tableitem.cpp + +METASOURCES = AUTO + +AM_CPPFLAGS = -I$(top_srcdir)/quanta/utility \ + -I$(top_srcdir)/quanta/parsers \ + -I$(top_srcdir)/quanta/dialogs/tagdialogs \ + -I$(top_srcdir)/quanta/src \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/quanta/components/tableeditor \ + $(KMDI_INCLUDES) $(all_includes) + +noinst_HEADERS = tableeditor.h tableitem.h diff --git a/quanta/components/tableeditor/tableeditor.cpp b/quanta/components/tableeditor/tableeditor.cpp new file mode 100644 index 00000000..970828a2 --- /dev/null +++ b/quanta/components/tableeditor/tableeditor.cpp @@ -0,0 +1,1298 @@ +/*************************************************************************** + tableeditor.cpp - table editor dialog + begin : Thu 15 Apr 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * + * 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; version 2 of the License. + * + ***************************************************************************/ + +//kde includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//own includes +#include "tagdialog.h" +#include "parser.h" +#include "node.h" +#include "tag.h" + +#include "quantacommon.h" +#include "tableitem.h" +#include "tableeditor.h" + +int newNum; + +TableEditor::TableEditor(QWidget* parent, const char* name) + : TableEditorS(parent, name) +{ + m_popup = new KPopupMenu(); + m_cellEditId = m_popup->insertItem(i18n("&Edit Cell Properties"), this ,SLOT(slotEditCell())); + m_rowEditId = m_popup->insertItem(i18n("Edit &Row Properties"), this ,SLOT(slotEditRow())); + // m_colEditId = m_popup->insertItem(i18n("Edit &Column Properties"), this ,SLOT(slotEditCol())); + m_mergeSeparatorId = m_popup->insertSeparator(); + m_mergeCellsId = m_popup->insertItem(i18n("Merge Cells"), this, SLOT(slotMergeCells())); + m_unmergeCellsId = m_popup->insertItem(i18n("Break Merging"), this, SLOT(slotUnmergeCells())); + + m_popup->insertSeparator(); + m_popup->insertItem(i18n("&Insert Row"), this, SLOT(slotInsertRow())); + m_popup->insertItem(i18n("Insert Co&lumn"), this, SLOT(slotInsertCol())); + m_popup->insertItem(i18n("Remove Row"), this, SLOT(slotRemoveRow())); + m_popup->insertItem(i18n("Remove Column"), this, SLOT(slotRemoveCol())); + m_popup->insertSeparator(); + m_popup->insertItem(i18n("Edit &Table Properties"), this, SLOT(slotEditTable())); + m_editChildId = m_popup->insertItem(i18n("Edit Child Table"), this, SLOT(slotEditChildTable())); + + buttonOk->setIconSet(SmallIconSet("button_ok")); + buttonCancel->setIconSet(SmallIconSet("button_cancel")); + buttonHelp->setIconSet(SmallIconSet("help")); + + m_row = m_col = -1; + m_tbody = 0L; + m_thead = 0L; + m_tfoot = 0L; + m_table = 0L; + m_dtd = 0L; + m_write = 0L; + m_tableDataTags = new QValueList >; + m_tableHeaderTags = new QValueList >; + m_tableFooterTags = new QValueList >; + m_tableTags = 0L; + m_tableDataRows = new QValueList; + m_tableHeaderRows = new QValueList; + m_tableFooterRows = new QValueList; + m_tableRows = 0L; + m_createNodes = true; + newNum += 7; + + connect(headerColSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int))); + connect(headerRowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int))); + connect(rowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int))); + connect(colSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int))); + connect(footerRowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int))); + connect(footerColSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int))); + connect(tableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)), + SLOT(slotContextMenuRequested(int,int,const QPoint&))); + connect(pushButton7, SIGNAL(clicked()), SLOT(slotEditTable())); + connect(pushButton7_2, SIGNAL(clicked()), SLOT(slotEditTableBody())); + connect(pushButton7_3, SIGNAL(clicked()), SLOT(slotEditTableHeader())); + connect(pushButton7_4, SIGNAL(clicked()), SLOT(slotEditTableFooter())); + connect(headerTableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)), + SLOT(slotContextMenuRequested(int,int,const QPoint&))); + connect(footerTableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)), + SLOT(slotContextMenuRequested(int,int,const QPoint&))); + connect(tabWidget, SIGNAL(currentChanged(QWidget*)), SLOT(slotTabChanged(QWidget*))); + connect(buttonHelp, SIGNAL(clicked()), SLOT(slotHelpInvoked())); + connect(tableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int))); + connect(headerTableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int))); + connect(footerTableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int))); +} + +TableEditor::~TableEditor() +{ + delete m_popup; + delete m_tbody; + delete m_thead; + delete m_tfoot; + delete m_table; + newNum -=5; + deleteMatrix(m_tableDataTags); + deleteMatrix(m_tableHeaderTags); + deleteMatrix(m_tableFooterTags); + deleteList(m_tableDataRows); + deleteList(m_tableHeaderRows); + deleteList(m_tableFooterRows); + kdDebug(24000) << "Undeleted new: " << newNum << endl; +} + +void TableEditor::slotContextMenuRequested( int row, int col, const QPoint & pos ) +{ + m_row = row; + m_col = col; + m_popup->setItemEnabled(m_cellEditId, (row >=0 && col >=0)); + m_popup->setItemEnabled(m_rowEditId, (row >=0)); + m_popup->setItemEnabled(m_colEditId, (col >=0)); + m_popup->setItemVisible(m_mergeSeparatorId, false); + m_popup->setItemVisible(m_mergeCellsId, false); + m_popup->setItemVisible(m_unmergeCellsId, false); + if (row >=0 && col >=0) { + TableNode tableNode = (*m_tableTags)[m_row][m_col]; + m_popup->setItemVisible(m_mergeSeparatorId, false); + m_popup->setItemVisible(m_mergeCellsId, false); + m_popup->setItemVisible(m_editChildId, false); + if (tableNode.merged) { + m_popup->setItemVisible(m_unmergeCellsId, true); + m_popup->setItemVisible(m_mergeSeparatorId, true); + } + QTableSelection selection = m_dataTable->selection(m_dataTable->currentSelection()); + QRect rect(QPoint(selection.topRow(), selection.leftCol()) , + QPoint(selection.bottomRow(), selection.rightCol())); + if (rect.isValid() && (rect.width() > 1 || rect.height() > 1) && rect.contains(m_row, m_col)) { + m_popup->setItemVisible(m_mergeCellsId, true); + m_popup->setItemVisible(m_mergeSeparatorId, true); + } + if (m_dataTable->item(m_row, m_col) && !m_dataTable->item(m_row, m_col)->pixmap().isNull()) { + m_popup->setItemVisible(m_editChildId, true); + } + } + m_popup->popup(pos); +} + + +void TableEditor::slotEditCell() +{ + Tag *tag = (*m_tableTags)[m_row][m_col].node->tag; + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd, "td"), tag, m_baseURL); + int many = 0; + if (dlg.exec()) { + for (int row = 0; row < m_dataTable->numRows(); row++) + for (int col = 0; col < m_dataTable->numCols(); col++) { + many++; + if (m_dataTable->isSelected(row, col)) { + (*m_tableTags)[row][col].node->tag->modifyAttributes(dlg.getAttributes()); + configureCell(row, col, (*m_tableTags)[row][col].node); + } + } + if (!many) { + (*m_tableTags)[m_row][m_col].node->tag->modifyAttributes(dlg.getAttributes()); + configureCell(m_row, m_col, (*m_tableTags)[m_row][m_col].node); + } + //TODO: add/remove columns/rows if the colspan/rowspan attribute is changed + } +} + +void TableEditor::slotEditCellText( int r, int ) +{ + m_dataTable->adjustRow(r); +} + + +void TableEditor::slotEditRow() +{ + Tag *tag = (*m_tableRows)[m_row].node->tag; + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tr"), tag, m_baseURL); + if (dlg.exec()) { + tag->modifyAttributes(dlg.getAttributes()); + } +} + + +void TableEditor::slotEditCol() +{ + KMessageBox::information(this, i18n("Edit col: %1").arg(m_col + 1)); + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"col")); + dlg.exec(); +} + + +void TableEditor::slotEditTable() +{ + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"table"), m_table, m_baseURL); + if (dlg.exec()) { + m_table->modifyAttributes(dlg.getAttributes()); + } +} + + +void TableEditor::slotEditTableBody() +{ + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tbody"), m_tbody, m_baseURL); + if (dlg.exec()) { + m_tbody->modifyAttributes(dlg.getAttributes()); + } +} + + +bool TableEditor::setTableArea( int bLine, int bCol, int eLine, int eCol, Parser *docParser ) +{ + const uint pInitialTableSize = 20; + + m_bLine = bLine; + m_bCol = bCol; + m_eLine = eLine; + m_eCol = eCol; + m_createNodes = false; //don't create the cell and row content when adding a new cell/row + Node *node = docParser->nodeAt(bLine, bCol + 1); + Node *lastNode = docParser->nodeAt(eLine, eCol); + if (node) + kdDebug(24000) << "node = " << node->tag->name << endl; + if (lastNode) + kdDebug(24000) << "lastnode = " << lastNode->tag->name << endl; + if (!node || !lastNode) + return false; + m_write = node->tag->write(); + m_dtd = node->tag->dtd(); + if ( !QuantaCommon::closesTag(node->tag, lastNode->tag) ) { + return false; + } + int nCol, nRow, maxCol; + nCol = nRow = maxCol = 0; + bool countRows = false; + bool missingBody = false; + m_rowSpin = 0L; + m_colSpin = 0L; + m_dataTable = 0L; + QValueList tableRowTags; + QValueVector< QValueVector > mergeMatrix; + mergeMatrix.resize(pInitialTableSize); + for (uint i = 0; i < pInitialTableSize; i++) + mergeMatrix[i].resize(pInitialTableSize); + TableNode tableNode; + Node *n = node; + while (n != lastNode->nextSibling()) + { + QString tagName = n->tag->name.lower(); + if (tagName == "table") + { + if (m_table && m_dataTable && nRow > 0 && nCol > 0) //nested table! + { + int line, col; + n->tag->beginPos(line, col); + NestedTable table; + table.row = nRow -1; + table.col = nCol - 1; + table.bLine = line; + table.bCol = col; + if (n->next && QuantaCommon::closesTag(n->tag, n->next->tag)) { + n->next->tag->endPos(table.eLine, table.eCol); + table.node = n; + table.nestedData = m_write->text(table.bLine, table.bCol, table.eLine, table.eCol); + m_nestedTables.append(table); + m_dataTable->item(nRow -1, nCol -1)->setPixmap(QIconSet(UserIcon("quick_table")).pixmap()); + m_dataTable->updateCell(nRow - 1, nCol - 1); + } + n = n->next; + } else + { + m_table = new Tag(*(n->tag)); + newNum++; + } + } + else if (tagName == "thead") + { + headerCheckBox->setChecked(true); + countRows = true; + m_rowSpin = headerRowSpinBox; + m_colSpin = headerColSpinBox; + m_dataTable= headerTableData; + m_tableTags = m_tableHeaderTags; + m_tableRows = m_tableHeaderRows; + if (m_thead) { //there was already a tag in the area + nRow = m_dataTable->numRows(); + } else { + m_thead = new Tag(*(n->tag)); + newNum++; + } + } + else if (tagName == "/thead") + { + headerRowSpinBox->setValue(nRow); + headerColSpinBox->setValue(maxCol); + countRows = false; + nCol = nRow = maxCol = 0; + m_rowSpin = 0L; + m_colSpin = 0L; + m_dataTable = 0L; + } + else if (tagName == "tfoot") + { + footerCheckBox->setChecked(true); + m_rowSpin = footerRowSpinBox; + m_colSpin = footerColSpinBox; + m_tableTags = m_tableFooterTags; + m_tableRows = m_tableFooterRows; + m_dataTable = footerTableData; + countRows = true; + if (m_tfoot) { //there was already a tag in the area + nRow = m_dataTable->numRows(); + } else { + m_tfoot = new Tag(*(n->tag)); + newNum++; + } + } + else if (tagName == "/tfoot") + { + footerRowSpinBox->setValue(nRow); + footerColSpinBox->setValue(maxCol); + countRows = false; + nCol = nRow = maxCol = 0; + m_rowSpin = 0L; + m_colSpin = 0L; + m_dataTable = 0L; + } + else if (tagName == "tbody") + { + m_rowSpin = rowSpinBox; + m_colSpin = colSpinBox; + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + countRows = true; + m_tbody = new Tag(*(n->tag)); + newNum++; + } + else if (tagName == "/tbody") + { + rowSpinBox->setValue(nRow); + colSpinBox->setValue(maxCol); + countRows = false; + nCol = nRow = maxCol = 0; + m_tableTags = 0L; + m_tableRows = 0L; + m_rowSpin = 0L; + m_colSpin = 0L; + m_dataTable = 0L; + } + else if (tagName == "tr") + { + if (!countRows) + { + missingBody = true; + m_rowSpin = rowSpinBox; + m_colSpin = colSpinBox; + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + countRows = true; + m_tbody = new Tag(); + newNum++; + m_tbody->parse("", m_write); + } + nRow++; + if ((uint)nRow >= mergeMatrix.size()) { // Check if there are enough rows in mergeMatriz + mergeMatrix.resize(2 * mergeMatrix.size()); + for (uint i = mergeMatrix.size() / 2; i < mergeMatrix.size(); i++) + mergeMatrix[i].resize(mergeMatrix[0].size()); + } + + m_rowSpin->setValue(nRow); + nCol = 0; + tableNode.node = new Node(0L); + tableNode.node->tag = new Tag(*(n->tag)); + newNum++; + tableNode.merged = false; + m_tableRows->append(tableNode); + } + else if (tagName == "/tr") + { + if (countRows) + { + maxCol = (nCol > maxCol) ? nCol : maxCol; + maxCol = (maxCol == 0) ? 1 : maxCol; + for (int col = nCol; col < maxCol; col++) + { + if (mergeMatrix[nRow - 1][col].node != 0L) { + if (m_colSpin->value() < col) + m_colSpin->setValue(col); + TableNode tableN = mergeMatrix[nRow - 1][col]; + Node *n = tableN.node; + setCellText(m_dataTable, nRow - 1, col, i18n("Merged with (%1, %2).").arg(tableN.mergedRow + 1).arg(tableN.mergedCol + 1)); + m_dataTable->item(nRow-1, col)->setEnabled(false); + tableNode.node = new Node(0L); + tableNode.node->tag = new Tag(*(n->tag)); + configureCell(nRow-1, col, tableNode.node); + newNum++; + tableNode.merged = true; + tableNode.mergedRow = tableN.mergedRow; + tableNode.mergedCol = tableN.mergedCol; + tableRowTags.append(tableNode); + if ((uint)nCol >= mergeMatrix[0].size()) // Check if there are enough cols + for (uint i=0; itag = new Tag(); + tableNode.node->tag->setDtd(m_dtd); + tableNode.node->tag->parse("", m_write); + tableNode.merged = false; + tableRowTags.append(tableNode); + } + } + if (!tableRowTags.isEmpty()) + m_tableTags->append(tableRowTags); + tableRowTags.clear(); + } + } + else if (tagName == "th" || tagName == "td") + { + if (countRows) + { + int col = nCol; + while (mergeMatrix[nRow - 1][col].node != 0L) { + if (m_colSpin->value() < col) + m_colSpin->setValue(col); + TableNode tableN = mergeMatrix[nRow - 1][col]; + Node *n = tableN.node; + setCellText(m_dataTable, nRow - 1, col, i18n("Merged with (%1, %2).").arg(tableN.mergedRow + 1).arg(tableN.mergedCol + 1)); + m_dataTable->item(nRow-1, col)->setEnabled(false); + tableNode.node = new Node(0L); + tableNode.node->tag = new Tag(*(n->tag)); + configureCell(nRow-1, col, tableNode.node); + newNum++; + tableNode.merged = true; + tableNode.mergedRow = tableN.mergedRow; + tableNode.mergedCol = tableN.mergedCol; + tableRowTags.append(tableNode); + col++; + nCol++; + if ((uint)nCol >= mergeMatrix[0].size()) // Check if there are enough cols + for (uint i = 0; i < mergeMatrix.size(); i++) + mergeMatrix[i].resize(2 * mergeMatrix[i].size()); + + } + nCol++; + if (m_rowSpin && m_colSpin && m_dataTable) + { + m_rowSpin->setValue(nRow); + if (m_colSpin->value() < nCol) + m_colSpin->setValue(nCol); + setCellText(m_dataTable, nRow - 1, nCol - 1, tagContent(n)); + tableNode.node = new Node(0L); + tableNode.node->tag = new Tag(*(n->tag)); + configureCell(nRow-1, col, tableNode.node); + newNum++; + tableNode.merged = false; + tableRowTags.append(tableNode); + } + QString colspanValue = n->tag->attributeValue("colspan", true); + int colValue = 1; + int lastCol = nCol; + if (!colspanValue.isEmpty()) + { + bool ok; + colValue = colspanValue.toInt(&ok, 10); + if (ok && colValue > 1) + { + nCol += (colValue - 1); + if (m_colSpin->value() < nCol) + m_colSpin->setValue(nCol); + for (int i = 0; i < colValue - 1; i++) + { + setCellText(m_dataTable, nRow - 1, lastCol + i, i18n("Merged with (%1, %2).").arg(nRow).arg(lastCol)); + m_dataTable->item(nRow-1, lastCol + i)->setEnabled(false); + tableNode.node = new Node(0L); + tableNode.node->tag = new Tag(*(n->tag)); + configureCell(nRow-1, col, tableNode.node); + newNum++; + tableNode.merged = true; + tableNode.mergedRow = nRow - 1; + tableNode.mergedCol = lastCol - 1; + tableRowTags.append(tableNode); + } + } else + colValue = 1; + } + QString rowspanValue = n->tag->attributeValue("rowspan", true); + if (!rowspanValue.isEmpty()) + { + bool ok; + int rowValue = rowspanValue.toInt(&ok, 10); + if (ok && rowValue > 1) + { + lastCol--; + // Check if there are enough columns in mergeMatriz + if ((uint)(lastCol + colValue) >= mergeMatrix[0].size()) + for (uint i = 0; i < mergeMatrix.size(); i++) + mergeMatrix[i].resize(2 * mergeMatrix[i].size()); + // Check if there are enough rows in mergeMatriz + if ((uint)(nRow + rowValue) >= mergeMatrix.size()) { + mergeMatrix.resize(2 * mergeMatrix.size()); + for (uint i = mergeMatrix.size() / 2; i < mergeMatrix.size(); i++) + mergeMatrix[i].resize(mergeMatrix[0].size()); + } + + for (int i = 0; i < rowValue - 1; i++) + for (int j = 0; j < colValue; j++) { + mergeMatrix[nRow + i][lastCol + j].mergedRow = nRow - 1; + mergeMatrix[nRow + i][lastCol + j].mergedCol = lastCol; + mergeMatrix[nRow + i][lastCol + j].node = n; + } + } + } + } + } + else if (tagName == "caption") + { + captionText->setText(tagContent(n)); + } else if (tagName == "col" || tagName == "colgroup") { + m_colTags.append(n->tag); + } + n = n->nextSibling(); + } +/* if (missingBody) { //Hm, why do we need it? I don't remember now. ;-) + rowSpinBox->setValue(nRow); + colSpinBox->setValue(maxCol); + } */ + //by default the current page is the data handling page + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + m_rowSpin = rowSpinBox; + m_colSpin = colSpinBox; + + //create the thead, tbody, tfoot tags if they were not present in the parsed area + if (!m_thead) { + m_thead = new Tag(); + newNum++; + m_thead->parse("", m_write); + } + if (!m_tfoot) { + m_tfoot = new Tag(); + newNum++; + m_tfoot->parse("", m_write); + } + m_createNodes = true; //enable cell/row creation + + configureTable(tableData); + configureTable(headerTableData); + configureTable(footerTableData); + return true; +} + + +void TableEditor::setBaseURL( const KURL & url ) +{ + m_baseURL = url; +} + + +void TableEditor::slotEditTableHeader() +{ + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd, "thead"), m_thead, m_baseURL); + if (dlg.exec()) { + m_thead->modifyAttributes(dlg.getAttributes()); + } +} + + +void TableEditor::slotEditTableFooter() +{ + TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tfoot"), m_tfoot, m_baseURL); + if (dlg.exec()) { + m_tfoot->modifyAttributes(dlg.getAttributes()); + } +} + + +void TableEditor::slotTabChanged( QWidget *w) +{ + int i = tabWidget->indexOf(w); + switch (i) + { + case 0: { + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + m_colSpin = colSpinBox; + m_rowSpin = rowSpinBox; + break; + } + case 1: { + m_tableTags = m_tableHeaderTags; + m_tableRows = m_tableHeaderRows; + m_dataTable = headerTableData; + m_colSpin = headerColSpinBox; + m_rowSpin = headerRowSpinBox; + break; + } + case 2: { + m_tableTags = m_tableFooterTags; + m_tableRows = m_tableFooterRows; + m_dataTable = footerTableData; + m_colSpin = footerColSpinBox; + m_rowSpin = footerRowSpinBox; + break; + } + } + configureTable(m_dataTable); +} + + +QString TableEditor::readModifiedTable() +{ + QString tableString; + tableString = m_table->toString(); + if (!captionText->text().isEmpty()) { + tableString += indent(2); + tableString += "<" + QuantaCommon::tagCase("caption") + ">"; + tableString += captionText->text(); + tableString += ""; + } + for (QValueList::Iterator it = m_colTags.begin(); it != m_colTags.end(); ++it) { + tableString += indent(2); + tableString += (*it)->toString(); + } + if (headerCheckBox->isChecked() && headerTableData->numRows() > 0) { + //insert the tag + tableString += indent(2); + tableString += m_thead->toString(); + + kdDebug(24000) << "thead" << endl; + m_tableTags = m_tableHeaderTags; + m_tableRows = m_tableHeaderRows; + m_dataTable = headerTableData; + tableString += tableToString(); + tableString += indent(2); + tableString += "name) +">"; + } + if (footerCheckBox->isChecked() && footerTableData->numRows() > 0) { + //insert the tag + tableString += indent(2); + tableString += m_tfoot->toString(); + + kdDebug(24000) << "tfoot" << endl; + m_tableTags = m_tableFooterTags; + m_tableRows = m_tableFooterRows; + m_dataTable = footerTableData; + tableString += tableToString(); + tableString += indent(2); + tableString += "name) +">"; + } + //insert the tag + if (!m_tbody) + { + m_tbody = new Tag(); + newNum++; + m_tbody->parse("", m_write); + } + tableString += indent(2); + tableString += m_tbody->toString(); + kdDebug(24000) << "tbody" << endl; + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + tableString += tableToString(); + //close the and tags + tableString += indent(2); + tableString += "name) +">"; + tableString += "\n"; + tableString += "name) + ">"; + + //kdDebug(24000) << tableString << endl; + return tableString; +} + + +QString TableEditor::indent( int n ) +{ + QString str; + str.fill(' ', n); + str.prepend('\n'); + return str; +} + + +QString TableEditor::cellValue( int row, int col ) +{ + if (!m_dataTable) + return QString::null; + QString str; + Node *node = (*m_tableTags)[row][col].node; + if (!node) + return QString::null; + str = node->tag->toString(); + str += m_dataTable->text(row, col); + str += "tag->name) + ">"; + return str; +} + + +QString TableEditor::tableToString() +{ + QString tableStr; + for (int i = 0; i < m_dataTable->numRows(); i++) { + tableStr += indent(4); + Node *node = (*m_tableRows)[i].node; + Tag *tag = 0L; + if (node) + tag = node->tag; + if (tag) + tableStr += tag->toString(); + else + tableStr += QuantaCommon::tagCase(""); + for (int j = 0; j < m_dataTable->numCols(); j++) { + if ((*m_tableTags)[i][j].node && !(*m_tableTags)[i][j].merged) + { + tableStr += indent(6); + tableStr += cellValue(i, j); + } + } + tableStr += indent(4); + if (tag) + tableStr += "name) +">"; + else + tableStr += QuantaCommon::tagCase(""); + } + return tableStr; +} + + +QString TableEditor::tagContent(Node *node) +{ + if (!node) + return QString::null; + QString content; + int bl, bc, el, ec; + node->tag->endPos(bl, bc); + bc++; + if (node->next) + { + node->next->tag->beginPos(el, ec); + ec--; + } + else + { + Node *n = node->nextSibling(); + if (n) { + n->tag->beginPos(el, ec); + ec--; + } else { + return QString::null; + } + } + content = m_write->text(bl, bc, el, ec); + return content; +} + + +void TableEditor::slotInsertRow() +{ + int num = m_dataTable->numRows(); + if (m_row >= 0) + num = m_row; + m_dataTable->insertRows(num); + m_dataTable->setRowHeight(num, 50); + if (m_createNodes) { + TableNode tableNode; + tableNode.merged = false; + tableNode.node = new Node(0L); + newNum++; + tableNode.node->tag = new Tag(); + tableNode.node->tag->setDtd(m_dtd); + tableNode.node->tag->parse("", m_write); + QValueList::Iterator rowIt = m_tableRows->at(num); + if (rowIt != m_tableRows->end()) + m_tableRows->insert(rowIt, tableNode); + else + m_tableRows->append(tableNode); + QValueList tableRowTags; + for (int i = 0; i < m_dataTable->numCols(); i++) { + tableNode.merged = false; + tableNode.node = new Node(0L); + newNum++; + tableNode.node->tag = new Tag(); + tableNode.node->tag->setDtd(m_dtd); + if (m_tableTags == m_tableHeaderTags) { + tableNode.node->tag->parse("
", m_write); + } else { + tableNode.node->tag->parse("", m_write); + } + tableRowTags.append(tableNode); + setCellText(m_dataTable, num, i, ""); + } + QValueList >::Iterator it = m_tableTags->at(num); + if (it != m_tableTags->end()) + m_tableTags->insert(it, tableRowTags); + else + m_tableTags->append(tableRowTags); + } + m_rowSpin->setValue(m_dataTable->numRows()); +} + + +void TableEditor::slotInsertCol() +{ + int num = m_dataTable->numCols(); + if (m_col >= 0) + num = m_col; + m_dataTable->insertColumns(num); + m_dataTable->setColumnWidth(num, 150); + if (m_createNodes) { + TableNode tableNode; + int i = 0; + for (QValueList >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) { + tableNode.merged = false; + tableNode.node = new Node(0L); + newNum++; + tableNode.node->tag = new Tag(); + tableNode.node->tag->setDtd(m_dtd); + if (m_tableTags == m_tableHeaderTags) { + tableNode.node->tag->parse("", m_write); + } else { + tableNode.node->tag->parse("", m_write); + } + (*it).append(tableNode); + setCellText(m_dataTable, i, num, ""); + i++; + } + } + m_colSpin->setValue(m_dataTable->numCols()); +} + + +void TableEditor::slotAddRemoveRow( int num ) +{ + m_row = -1; + int numRows = m_dataTable->numRows(); + if (num > numRows) { + for (int i = numRows; i < num; i++) { + slotInsertRow(); + } + } + else { + for (int i = num; i < numRows; i++) { + slotRemoveRow(); + } + } + //TODO: change the main tag's rowspan if necessary +} + + +void TableEditor::slotAddRemoveCol( int num ) +{ + m_col = -1; + int numCols = m_dataTable->numCols(); + if (num > numCols) { + for (int i = numCols; i < num; i++) { + slotInsertCol(); + } + } + else { + for (int i = num; i < numCols; i++) { + slotRemoveCol(); + } + } + //TODO: change the main tag's colspan if necessary} +} + +void TableEditor::slotRemoveRow() +{ + if (m_row == -1) + m_row = m_dataTable->numRows() - 1; + int i = 0; + int j = 0; + for (QValueList >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) { + j = 0; + for (QValueList::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { + if ((*it2).merged && (*it2).mergedRow == m_row) { + (*it2).merged = false; + setCellText(m_dataTable, i, j, tagContent((*it2).node)); + m_dataTable->item(i, j)->setEnabled(true); + (*it2).node->tag->deleteAttribute("colspan"); + (*it2).node->tag->deleteAttribute("rowspan"); + } + j++; + } + i++; + } + QValueList updatedMainNodes; + QValueList >::Iterator it2 = m_tableTags->at(m_row); + for (QValueList::Iterator it3 = (*it2).begin(); it3 != (*it2).end(); ++it3) { + if ((*it3).merged) + { + TableNode *mainTableNode = &((*m_tableTags)[(*it3).mergedRow][(*it3).mergedCol]); + if (mainTableNode->node && !updatedMainNodes.contains(mainTableNode)) + { + int rowspan = mainTableNode->node->tag->attributeValue("rowspan", true).toInt(); + rowspan--; + if (rowspan > 1) + mainTableNode->node->tag->editAttribute("rowspan", QString("%1").arg(rowspan)); + else + mainTableNode->node->tag->deleteAttribute("rowspan"); + updatedMainNodes.append(mainTableNode); + } + } + Node::deleteNode((*it3).node); + (*it3).node = 0L; + newNum--; + } + m_tableTags->erase(it2); + m_dataTable->removeRow(m_row); + QValueList::Iterator it = m_tableRows->at(m_row); + Node::deleteNode((*it).node); + newNum--; + m_tableRows->erase(it); + m_rowSpin->setValue(m_dataTable->numRows()); +} + + +void TableEditor::slotRemoveCol() +{ + int i = 0; + int j = 0; + for (QValueList >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) { + j = 0; + for (QValueList::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { + if ((*it2).merged && (*it2).mergedCol == m_col) { + (*it2).merged = false; + setCellText(m_dataTable, i, j, tagContent((*it2).node)); + m_dataTable->item(i, j)->setEnabled(true); + (*it2).node->tag->deleteAttribute("colspan"); + (*it2).node->tag->deleteAttribute("rowspan"); + } + j++; + } + i++; + } + if (m_col == -1) + m_col = m_dataTable->numCols() - 1; + QValueList updatedMainNodes; + for (QValueList >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) { + QValueList::Iterator it2 = (*it).at(m_col); + if ((*it2).merged) + { + TableNode *mainTableNode = &((*m_tableTags)[(*it2).mergedRow][(*it2).mergedCol]); + if (mainTableNode->node && !updatedMainNodes.contains(mainTableNode)) + { + int colspan = mainTableNode->node->tag->attributeValue("colspan", true).toInt(); + colspan--; + if (colspan > 1) + mainTableNode->node->tag->editAttribute("colspan", QString("%1").arg(colspan)); + else + mainTableNode->node->tag->deleteAttribute("colspan"); + updatedMainNodes.append(mainTableNode); + } + } + Node::deleteNode((*it2).node); + newNum--; + (*it).erase(it2); + } + m_dataTable->removeColumn(m_col); + m_colSpin->setValue(m_dataTable->numCols()); +} + + +void TableEditor::createNewTable(Document *write, const DTDStruct *dtd) +{ + m_write = write; + m_dtd = dtd; + m_table = new Tag(); + m_table->setDtd(m_dtd); + newNum++; + m_table->parse("", m_write); + m_thead = new Tag(); + m_thead->setDtd(m_dtd); + newNum++; + m_thead->parse("", m_write); + m_tfoot = new Tag(); + m_tfoot->setDtd(m_dtd); + newNum++; + m_tfoot->parse("", m_write); + m_tbody = new Tag(); + m_tbody->setDtd(m_dtd); + newNum++; + m_tbody->parse("", m_write); + //by default the current page is the data handling page + m_tableTags = m_tableDataTags; + m_tableRows = m_tableDataRows; + m_dataTable = tableData; + m_bLine = m_bCol = m_eLine = m_eCol = 0; +} + + +void TableEditor::deleteList( QValueList *table ) +{ + for (QValueList::Iterator it = table->begin(); it != table->end(); ++it) { + Node::deleteNode((*it).node); + newNum--; + } + delete table; + newNum--; +} + + +void TableEditor::deleteMatrix( QValueList > *matrix ) +{ + for (QValueList >::Iterator it = matrix->begin(); it != matrix->end(); ++it) { + for (QValueList::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { + Node::deleteNode((*it2).node); + newNum--; + } + } + delete matrix; + newNum--; +} + + +void TableEditor::slotMergeCells() +{ + slotUnmergeCells(); //first unmerge all cells from the selection + + QTableSelection selection = m_dataTable->selection(m_dataTable->currentSelection()); + int tRow, bRow, lCol, rCol; + tRow = selection.topRow(); + bRow = selection.bottomRow(); + lCol = selection.leftCol(); + rCol = selection.rightCol(); + TableNode *mainTableNode = &((*m_tableTags)[tRow][lCol]); + if (rCol - lCol > 0) + mainTableNode->node->tag->editAttribute("colspan", QString("%1").arg(rCol - lCol + 1)); + if (bRow - tRow > 0) + mainTableNode->node->tag->editAttribute("rowspan", QString("%1").arg(bRow - tRow + 1)); + for (int i = 0; i < bRow - tRow + 1; i++) + for (int j = 0; j < rCol - lCol + 1; j++) { + if (i != 0 || j != 0) { + setCellText(m_dataTable, tRow + i, lCol + j, i18n("Merged with (%1, %2).").arg(tRow + 1).arg(lCol + 1)); + m_dataTable->item(tRow + i, lCol + j)->setEnabled(false); + TableNode *tableNode = &((*m_tableTags)[tRow + i][lCol + j]); + Node::deleteNode(tableNode->node); + tableNode->node = new Node(0L); + newNum++; + tableNode->node->tag = new Tag(*(mainTableNode->node->tag)); + tableNode->merged = true; + tableNode->mergedRow = tRow; + tableNode->mergedCol = lCol; + } + } +} + + +void TableEditor::slotUnmergeCells() +{ + int tRow, bRow, lCol, rCol; + int selectionNum = m_dataTable->currentSelection(); + if (selectionNum != -1) { + QTableSelection selection = m_dataTable->selection(selectionNum); + tRow = selection.topRow(); + bRow = selection.bottomRow(); + lCol = selection.leftCol(); + rCol = selection.rightCol(); + } else { + tRow = m_row; + bRow = m_row; + lCol = m_col; + rCol = m_col; + } + for (int row = tRow; row <= bRow; ++row) + for (int col = lCol; col <= rCol; ++col) { + TableNode tableNode = (*m_tableTags)[row][col]; + if (!tableNode.merged) + continue; + TableNode newTableNode; + int i = 0; + int j = 0; + for (QValueList >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) { + j = 0; + QValueList::Iterator it2 = (*it).begin(); + while (it2 != (*it).end()) { + if ((*it2).merged && + tableNode.mergedRow == (*it2).mergedRow && + tableNode.mergedCol == (*it2).mergedCol) { + + Node::deleteNode((*it2).node); + newNum--; + it2 = (*it).erase(it2); + newTableNode.merged = false; + newTableNode.node = new Node(0L); + newNum++; + newTableNode.node->tag = new Tag(); + newTableNode.node->tag->setDtd(m_dtd); + if (m_tableTags == m_tableHeaderTags) { + newTableNode.node->tag->parse("
", m_write); + } else { + newTableNode.node->tag->parse("", m_write); + } + (*it).insert(it2, newTableNode); + setCellText(m_dataTable, i, j, tagContent(newTableNode.node)); + m_dataTable->item(i, j)->setEnabled(true); + } else { + ++it2; + } + j++; + } + i++; + } + newTableNode = (*m_tableTags)[tableNode.mergedRow][tableNode.mergedCol]; + newTableNode.node->tag->deleteAttribute("colspan"); + newTableNode.node->tag->deleteAttribute("rowspan"); + //change the main node + TableNode tmpNode = newTableNode; + newTableNode.node = new Node(0L); + newNum++; + newTableNode.node->tag = new Tag(*(tmpNode.node->tag)); + QValueList >::Iterator iter1 = m_tableTags->at(tableNode.mergedRow); + QValueList::Iterator iter2 = (*iter1).at(tableNode.mergedCol); + iter2 = (*iter1).erase(iter2); + (*iter1).insert(iter2, newTableNode); + Node::deleteNode(tmpNode.node); + newNum--; + } +} + + + +void TableEditor::slotEditChildTable() +{ + bool tempDocCreated = false; + bool error = false; + QValueList::Iterator errorIt; + Parser *localParser = 0L; + Document *w = 0L; + Node *savedBaseNode = 0L; + NestedTable table; + + for (QValueList::Iterator it = m_nestedTables.begin(); it != m_nestedTables.end(); ++it) { + table = *it; + if (table.row == m_row && table.col == m_col) { + QString cellData = m_dataTable->text(table.row, table.col); + int pos = cellData.find(table.nestedData); + if (pos == -1) { + KMessageBox::error(this, i18n("Cannot edit the child table; you probably modified the cell containing the table manually."), i18n("Cannot Read Table")); + error = true; + errorIt = it; + break; + } + //create a new editor object and save the current state of the table there + KTextEditor::Document *doc = + KTextEditor::createDocument ("libkatepart", 0L, "KTextEditor::Document"); + w = new Document(doc, 0L); + QString tableData = readModifiedTable(); + w->editIf->insertText(0, 0, tableData); + localParser = new Parser(); + savedBaseNode = baseNode; //we must save it as it's deleted in the localParser->parse(); + baseNode = 0L; + baseNode = localParser->parse(w); + tempDocCreated = true; + //try to find the child table position + int pos2 = tableData.find(cellData); + if (pos2 != -1) + pos2 = tableData.find(table.nestedData, pos2); + else { + KMessageBox::error(this, i18n("Cannot edit the child table; you probably modified the cell containing the table manually."), i18n("Cannot Read Table")); + error = true; + errorIt = it; + break; + } + tableData = tableData.left(pos2); + table.bLine = tableData.contains('\n'); + pos2 = tableData.findRev('\n'); + if (pos2 != -1) { + table.bCol = tableData.length() - pos2; + } else { + table.bCol = tableData.length(); + } + Node *childTableNode = localParser->nodeAt(table.bLine, table.bCol); + if (!childTableNode->next || !QuantaCommon::closesTag(childTableNode->tag, childTableNode->next->tag)) { + KMessageBox::error(this, i18n("Cannot find the closing tag of the child table; you have probably introduced unclosed tags in the table and have broken its consistency."), i18n("Cannot Read Table")); + error = true; + errorIt = it; + break; + } + childTableNode->next->tag->endPos(table.eLine, table.eCol); + TableEditor editor; + editor.setCaption("Child Table Editor"); + editor.setBaseURL(m_baseURL); + editor.setTableArea(table.bLine, table.bCol, table.eLine, table.eCol, localParser); + if (editor.exec()) { + int length = table.nestedData.length(); + (*it).nestedData = editor.readModifiedTable(); + cellData.replace(pos, length, (*it).nestedData); + setCellText(m_dataTable, table.row, table.col, cellData); + } + //cleanup on success + Node::deleteNode(baseNode); + baseNode = savedBaseNode; + delete localParser; + delete w; + return; + } + } + //cleanup on error + if (error) { + m_nestedTables.erase(errorIt); + m_dataTable->item(table.row, table.col)->setPixmap(QPixmap()); + m_dataTable->updateCell(table.row, table.col); + if (tempDocCreated) { + Node::deleteNode(baseNode); + baseNode = savedBaseNode; + delete localParser; + delete w; + } + } +} + + +void TableEditor::slotHelpInvoked() +{ + kapp->invokeHelp("table-editor","quanta"); +} + +void TableEditor::configureTable( QTable * table ) +{ + if (!table) + return; + for (int r=0; rnumRows(); r++) { + table->adjustRow(r); + for (int c=0; cnumCols(); c++) + if (table->item(r, c)) + table->item(r, c)->setWordWrap(true); + } + table->setColumnMovingEnabled(true); + table->setRowMovingEnabled(true); +} + +void TableEditor::setCellText( QTable * table, int row, int col, const QString & text ) +{ + table->setItem(row, col, new TableItem(table, QTableItem::OnTyping, text)); +} + +void TableEditor::configureCell(int row, int col, Node * node) +{ + TableItem* item = (TableItem*) m_dataTable->item(row, col); + if (!item) + return; + // Header (TH) or standard cell? + item->setHeader(node->tag->name.lower() == "th"); + // Horizontal alignment + Qt::AlignmentFlags flags; + QString align = node->tag->attributeValue("align", true); + if (align == "right") + flags = Qt::AlignRight; + else if (align == "center") + flags = Qt::AlignHCenter; + else if (align == "justify") + flags = Qt::AlignJustify; + else if (align.isEmpty() && item->header()) + flags = Qt::AlignHCenter; // TH is centered by default + else + flags = Qt::AlignLeft; + item->setAlignment(flags); + // Vertical alignment + QString valign = node->tag->attributeValue("valign", true); + if (valign == "top") + flags = Qt::AlignTop; + else if (valign == "bottom") + flags = Qt::AlignBottom; + else flags = Qt::AlignVCenter; + item->setVAlignment(flags); +} + +#include "tableeditor.moc" diff --git a/quanta/components/tableeditor/tableeditor.h b/quanta/components/tableeditor/tableeditor.h new file mode 100644 index 00000000..b1df7b48 --- /dev/null +++ b/quanta/components/tableeditor/tableeditor.h @@ -0,0 +1,132 @@ +/*************************************************************************** + tableeditor.h - table editor dialog + begin : Thu 15 Apr 2004 + copyright : (C) 2004 by Andras Mantia + ***************************************************************************/ + +/*************************************************************************** + * + * 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; version 2 of the License. + * + ***************************************************************************/ + +#ifndef TABLEEDITOR_H +#define TABLEEDITOR_H + +#include +#include + +#include "tableeditors.h" +#include "document.h" + +class QSpinBox; +class QTable; +class KPopupMenu; +class Tag; +struct DTDStruct; +class Node; + +class TableNode +{ +public: + Node *node; + bool merged; + int mergedRow; + int mergedCol; + TableNode() {node = 0;} +}; + + + +typedef struct NestedTable{ Node *node; int row; int col; int bLine; int bCol; int eLine; int eCol; QString nestedData;}; +class Parser; + + +class TableEditor : public TableEditorS +{ + Q_OBJECT + +public: + TableEditor( QWidget* parent = 0, const char* name = 0 ); + ~TableEditor(); + + virtual bool setTableArea( int bLine, int bCol, int eLine, int eCol, Parser * docParser ); + virtual void setBaseURL( const KURL & url ); + virtual QString readModifiedTable(); + virtual void createNewTable( Document * write, const DTDStruct * dtd ); + // Set defaults for table: enable word wrap, fit content, allow swapping col/rows with D&D + virtual void configureTable( QTable * table ); + virtual void setCellText( QTable * table, int row, int col, const QString & text ); + // Configure TableItem from tag attributes + virtual void configureCell( int row, int col, Node * node ); + +public slots: + virtual void slotContextMenuRequested( int row, int col, const QPoint & pos ); + virtual void slotEditCell(); + // Wrapper for setText to use TableItem instead of QTableItem + virtual void slotEditCellText( int r, int ); + virtual void slotEditRow(); + virtual void slotEditCol(); + virtual void slotEditTable(); + virtual void slotEditTableBody(); + virtual void slotEditTableHeader(); + virtual void slotEditTableFooter(); + virtual void slotTabChanged( QWidget * w ); + virtual void slotInsertRow(); + virtual void slotInsertCol(); + virtual void slotAddRemoveRow( int num ); + virtual void slotAddRemoveCol( int num ); + virtual void slotRemoveRow(); + virtual void slotRemoveCol(); + virtual void slotMergeCells(); + virtual void slotUnmergeCells(); + virtual void slotEditChildTable(); + virtual void slotHelpInvoked(); + +protected: + QValueList m_colTags; + int m_unmergeCellsId; + int m_mergeSeparatorId; + int m_mergeCellsId; + bool m_createNodes; + QValueList > *m_tableTags; + QValueList > *m_tableFooterTags; + QValueList > *m_tableHeaderTags; + QValueList *m_tableFooterRows; + QValueList *m_tableHeaderRows; + QValueList *m_tableRows; + Document* m_write; + Tag *m_table; + Tag *m_tfoot; + Tag *m_thead; + int newVariable; + Tag *m_tbody; + int m_colEditId; + int m_rowEditId; + int m_cellEditId; + int m_col; + int m_row; + KPopupMenu *m_popup; + KURL m_baseURL; + const DTDStruct *m_dtd; + QValueList > *m_tableDataTags; + QValueList *m_tableDataRows; + QTable *m_dataTable; + QSpinBox *m_rowSpin; + QSpinBox *m_colSpin; + int m_bLine, m_bCol, m_eLine, m_eCol; + QValueList m_nestedTables; + int m_editChildId; + + virtual QString indent( int n ); + virtual QString cellValue( int row, int col ); + virtual QString tableToString(); + virtual QString tagContent( Node * node ); + virtual void deleteList( QValueList * table ); + virtual void deleteMatrix( QValueList > * matrix ); + +}; + +#endif diff --git a/quanta/components/tableeditor/tableeditors.ui b/quanta/components/tableeditor/tableeditors.ui new file mode 100644 index 00000000..88def66d --- /dev/null +++ b/quanta/components/tableeditor/tableeditors.ui @@ -0,0 +1,642 @@ + +TableEditorS + + + TableEditorS + + + + 0 + 0 + 692 + 584 + + + + Table Editor + + + + unnamed + + + + buttonCancel + + + Ca&ncel + + + true + + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 16 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonHelp + + + &Help + + + F1 + + + true + + + + + tabWidget + + + + tab + + + &Main + + + + unnamed + + + + textLabel5 + + + Ta&ble data: + + + tableData + + + + + tableData + + + + 7 + 7 + 0 + 0 + + + + AlwaysOn + + + AlwaysOn + + + 0 + + + 0 + + + Single + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 276 + 20 + + + + + + spacer1_2_2 + + + Horizontal + + + Expanding + + + + 276 + 20 + + + + + + rowSpinBox + + + 999 + + + 0 + + + + + textLabel2 + + + Co&lumns: + + + colSpinBox + + + + + captionText + + + + + pushButton7_2 + + + Bod&y Properties + + + + + pushButton7 + + + &Table Properties + + + + + textLabel3 + + + + 5 + 1 + 0 + 0 + + + + C&aption: + + + captionText + + + + + textLabel1 + + + &Rows: + + + rowSpinBox + + + + + colSpinBox + + + 999 + + + 0 + + + + + + + tab + + + Header + + + + unnamed + + + + frame3 + + + false + + + StyledPanel + + + Raised + + + + unnamed + + + + headerTableData + + + AutoOneFit + + + AlwaysOn + + + AlwaysOn + + + 0 + + + 0 + + + Single + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 340 + 20 + + + + + + headerRowSpinBox + + + 0 + + + 0 + + + + + textLabel4_2 + + + Header &rows: + + + headerRowSpinBox + + + + + headerColSpinBox + + + 999 + + + + + textLabel4 + + + Header co&lumns: + + + headerColSpinBox + + + + + textLabel6 + + + Header &data: + + + headerTableData + + + + + + + headerCheckBox + + + Insert ta&ble header + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + pushButton7_3 + + + false + + + &Header Properties + + + + + + + tab + + + Footer + + + + unnamed + + + + frame3_2 + + + false + + + StyledPanel + + + Raised + + + + unnamed + + + + footerTableData + + + AutoOneFit + + + AlwaysOn + + + AlwaysOn + + + 0 + + + 0 + + + Single + + + FollowStyle + + + + + footerRowSpinBox + + + 0 + + + 0 + + + + + textLabel4_2_2 + + + Footer &rows: + + + footerRowSpinBox + + + + + footerColSpinBox + + + 999 + + + + + textLabel4_3 + + + Footer co&lumns: + + + footerColSpinBox + + + + + textLabel6_2 + + + Footer &data: + + + footerTableData + + + + + spacer2_2 + + + Horizontal + + + Expanding + + + + 340 + 20 + + + + + + + + footerCheckBox + + + Insert ta&ble footer + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + pushButton7_4 + + + false + + + &Footer Properties + + + + + + + + + + headerCheckBox + toggled(bool) + frame3 + setEnabled(bool) + + + footerCheckBox + toggled(bool) + frame3_2 + setEnabled(bool) + + + buttonOk + clicked() + TableEditorS + accept() + + + buttonCancel + clicked() + TableEditorS + reject() + + + headerCheckBox + toggled(bool) + pushButton7_3 + setEnabled(bool) + + + footerCheckBox + toggled(bool) + pushButton7_4 + setEnabled(bool) + + + + tabWidget + rowSpinBox + colSpinBox + pushButton7 + pushButton7_2 + captionText + tableData + buttonOk + buttonCancel + buttonHelp + headerCheckBox + pushButton7_3 + headerRowSpinBox + headerColSpinBox + headerTableData + footerCheckBox + pushButton7_4 + footerRowSpinBox + footerColSpinBox + footerTableData + + + diff --git a/quanta/components/tableeditor/tableitem.cpp b/quanta/components/tableeditor/tableitem.cpp new file mode 100644 index 00000000..96d7d37c --- /dev/null +++ b/quanta/components/tableeditor/tableitem.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + tableitem.cpp - description + ------------------- + begin : Mon 15 Mar 2004 + copyright : (C) 2004 by Michal Rudolf + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 +#include +#include "tableitem.h" + +TableItem::TableItem(QTable* table, EditType et) : QTableItem(table, et) +{ + setReplaceable(false); + m_halign = Qt::AlignLeft; + m_valign = Qt::AlignVCenter; +} + +TableItem::TableItem(QTable* table, EditType et, const QString& text) : QTableItem(table, et, text) +{ + setReplaceable(false); + m_halign = Qt::AlignLeft; + m_valign = Qt::AlignVCenter; +} + +TableItem::TableItem (QTable* table, EditType et, const QString& text, const QPixmap& p) : + QTableItem(table, et, text, p) +{ + setReplaceable(false); + m_halign = Qt::AlignLeft; + m_valign = Qt::AlignVCenter; +} + +QWidget* TableItem::createEditor() const +{ + QTextEdit* Editor = new QTextEdit(table()->viewport()); + Editor->setTextFormat(QTextEdit::PlainText); + Editor->setHScrollBarMode(QScrollView::AlwaysOff); + Editor->setVScrollBarMode(QScrollView::AlwaysOff); + Editor->setBold(m_header); + Editor->setText(text()); + QObject::connect(Editor, SIGNAL(textChanged()), table(), SLOT(doValueChanged())); + return Editor; +} + +void TableItem::setContentFromEditor(QWidget *w) +{ + if (w->inherits( "QTextEdit" )) + setText(((QTextEdit*)w)->text()); + else + QTableItem::setContentFromEditor(w); +} + +void TableItem::paint(QPainter* p, const QColorGroup& cg, const QRect& cr, bool selected) +{ + if (m_header) { + QFont editFont = p->font(); + editFont.setBold(true); + p->setFont(editFont); + } + QRect cr0(0, 0, cr.width(), cr.height()); + if (selected) { + p->fillRect(cr0, cg.brush(QColorGroup::Highlight)); + p->setPen(cg.highlightedText()); + } + else { + p->fillRect(cr0, cg.brush(QColorGroup::Base)); + p->setPen(cg.text()); + } + if (!pixmap().isNull()) { + p->drawPixmap(4, 4, pixmap()); + p->drawText(6 + pixmap().width(), 4, cr0.width()-8, cr0.height()-8, m_halign | m_valign | WordBreak, text()); + } + else + p->drawText(4, 4, cr0.width()-8, cr0.height()-8, m_halign | m_valign | WordBreak, text()); +} + +QSize TableItem::sizeHint() const +{ + QSize size = QTableItem::sizeHint(); + size.setWidth(size.width()+8); + size.setHeight(size.height()+8); + return size; +} + diff --git a/quanta/components/tableeditor/tableitem.h b/quanta/components/tableeditor/tableitem.h new file mode 100644 index 00000000..1eff7f59 --- /dev/null +++ b/quanta/components/tableeditor/tableitem.h @@ -0,0 +1,56 @@ +/*************************************************************************** + tableitem.h - description + ------------------- + begin : Mon 15 Mar 2004 + copyright : (C) 2004 by Michal Rudolf + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 TABLEITEM_H +#define TABLEITEM_H + +#include +#include + +class TableItem : public QTableItem +{ +private: + Qt::AlignmentFlags m_halign; + Qt::AlignmentFlags m_valign; + bool m_header; +public: + // Standard constructors copied from QTableItem + TableItem(QTable* table, EditType et); + TableItem(QTable* table, EditType et, const QString& text); + TableItem (QTable* table, EditType et, const QString& text, const QPixmap& p); + // Use QTextEdit instead of standard QLineEdit + virtual QWidget* createEditor() const; + // Get text from QTextEdit + virtual void setContentFromEditor(QWidget *w); + // Paint cell - handle alignment (horizontal and vertical) and bold for header + virtual void paint(QPainter* p, const QColorGroup& cg, const QRect& cr, bool selected); + // Return A bit larger sizeHint because QTextEdit has some margin around + virtual QSize sizeHint() const; + // Get and set vertical aligment + Qt::AlignmentFlags vAlignment() {return m_valign;} + void setVAlignment(Qt::AlignmentFlags flags) {m_valign = flags;} + // Get and set horizontal aligment + Qt::AlignmentFlags alignment() {return m_halign;} + void setAlignment(Qt::AlignmentFlags flags) {m_halign = flags;} + // Get and set header status (use true for TH, false for TD) + bool header() {return m_header;} + void setHeader(bool h) {m_header = h;} +}; + + + +#endif + -- cgit v1.2.3