diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch) | |
tree | acaf47eb0fa12142d3896416a69e74cbf5a72242 /languages/kjssupport | |
download | tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip |
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/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'languages/kjssupport')
20 files changed, 1878 insertions, 0 deletions
diff --git a/languages/kjssupport/Makefile.am b/languages/kjssupport/Makefile.am new file mode 100644 index 00000000..d61fc67c --- /dev/null +++ b/languages/kjssupport/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = -I$(kde_includes)/kdevelop $(all_includes) + +kde_module_LTLIBRARIES = libkdevkjssupport.la +libkdevkjssupport_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkdevkjssupport_la_LIBADD = -lkjsembed -lkdevelop +libkdevkjssupport_la_SOURCES = kjssupport_part.cpp kjsproblems.cpp jscodecompletion.cpp subclassingdlg.cpp subclassingdlgbase.ui + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir) +service_DATA = kdevkjssupport.desktop + +mimesrcdir = $(kde_mimedir)/text +mimesrc_DATA = x-javascript-source.desktop + +EXTRA_DIST = $(mimesrc_DATA) + +rcdir = $(kde_datadir)/kdevkjssupport +rc_DATA = kdevkjssupport.rc + +SUBDIRS = template subclassing_template +noinst_HEADERS = kjsproblems.h diff --git a/languages/kjssupport/jscodecompletion.cpp b/languages/kjssupport/jscodecompletion.cpp new file mode 100644 index 00000000..8fd59f57 --- /dev/null +++ b/languages/kjssupport/jscodecompletion.cpp @@ -0,0 +1,174 @@ +// +// C++ Implementation: jscodecompletion +// +// Description: +// +// +// Author: ian reinhart geiser <geiseri@kde.org>, (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "jscodecompletion.h" +#include <qwhatsthis.h> + +#include <qfileinfo.h> +#include <qstringlist.h> +#include <qtextstream.h> +#include <qtimer.h> +#include <kapplication.h> +#include <qregexp.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kprocess.h> +#include <kdebug.h> +#include <kaction.h> +#include <kparts/part.h> +#include <kdialogbase.h> + + +#include <kdevelop/kdevcore.h> +#include <kdevelop/kdevmainwindow.h> +#include <kdevelop/kdevlanguagesupport.h> +#include <kdevelop/kdevpartcontroller.h> +#include <kdevelop/kdevproject.h> +#include <kdevelop/kdevappfrontend.h> +#include <kdevelop/domutil.h> +#include <kdevelop/codemodel.h> + +JSCodeCompletion::JSCodeCompletion(QObject *parent, const char *name) + : QObject(parent, name) +{ + m_argWidgetShow = false; + m_completionBoxShow=false; +} + + +JSCodeCompletion::~JSCodeCompletion() +{} + +void JSCodeCompletion::setActiveEditorPart( KParts::Part * part ) +{ + if (!part || !part->widget()) + return; + + kdDebug() << "JSCodeCompletion::setActiveEditorPart" << endl; + + // We need to think about this + // if(!(m_config->getCodeCompletion() || m_config->getCodeHinting())){ + // return; // no help + // } + + m_editInterface = dynamic_cast<KTextEditor::EditInterface*>(part); + if (!m_editInterface) + { + kdDebug() << "editor doesn't support the EditDocumentIface" << endl; + return; + } + + m_cursorInterface = dynamic_cast<KTextEditor::ViewCursorInterface*>(part->widget()); + if (!m_cursorInterface) + { + kdDebug() << "editor does not support the ViewCursorInterface" << endl; + return; + } + + m_codeInterface = dynamic_cast<KTextEditor::CodeCompletionInterface*>(part->widget()); + if (!m_codeInterface) + { // no CodeCompletionDocument available + kdDebug() << "editor doesn't support the CodeCompletionDocumentIface" << endl; + return; + } + + disconnect(part->widget(), 0, this, 0 ); // to make sure that it is't connected twice + connect(part->widget(), SIGNAL(cursorPositionChanged()), + this, SLOT(cursorPositionChanged())); + connect(part->widget(), SIGNAL(argHintHidden()), this, SLOT(argHintHidden())); + connect(part->widget(), SIGNAL(completionAborted()), this, SLOT(completionBoxAbort())); + connect(part->widget(), SIGNAL(completionDone()), this, SLOT(completionBoxHidden())); +} + +QValueList< KTextEditor::CompletionEntry > JSCodeCompletion::getVars( const QString & startText ) +{ + kdDebug() << "getVars for " << startText << endl; + QValueList<KTextEditor::CompletionEntry> varList; + /* + QValueList<QString>::ConstIterator it; + for (it = m_vars.begin(); it != m_vars.end(); ++it) + { + QString var = "$" + (*it); + kdDebug() << "Compair " << var << endl; + if( var.startsWith( startText )) + { + KTextEditor::CompletionEntry e; + e.text = var; + //e.postfix =""; + //e.prefix =""; + kdDebug() << "getVar: " << var << endl; + varList.append(e); + } + } + */ + return varList; +} + +void JSCodeCompletion::cursorPositionChanged( ) +{ + uint line, col; + m_cursorInterface->cursorPositionReal(&line, &col); + kdDebug() << "JSCodeCompletion::cursorPositionChanged:" << line << ":" << col << endl; + + QString lineStr = m_editInterface->textLine(line); + if(lineStr.isNull() || lineStr.isEmpty()) + { + kdDebug() << "No Text..." << endl; + return; // nothing to do + } + // if(m_config->getCodeCompletion()) + // { + QString restLine = lineStr.mid(col); + QString prevText = lineStr.mid(0,col); + + if(restLine.left(1) != " " && restLine.left(1) != "\t" && !restLine.isNull()) + { + kdDebug() << "no codecompletion because no empty character after cursor:" << restLine << ":" << endl; + return; + } + + QRegExp prevReg("([\\d\\w]*)[.]$"); + + if (prevReg.search( prevText ) != -1 ) + { + // We are in completion mode + QString startMatch = prevReg.cap(0); + kdDebug() << "Matching: " << startMatch << endl; + m_completionBoxShow=true; + m_codeInterface->showCompletionBox(getVars(startMatch),2); + } + else + { + kdDebug() << "no vars in: " << prevText << endl; + return; + } + + // } + + +} + +void JSCodeCompletion::completionBoxHidden( ) +{ + kdDebug() << "Complete..." << endl; + m_completionBoxShow=false; +} + +void JSCodeCompletion::completionBoxAbort( ) +{ + kdDebug() << "aborted..." << endl; + m_completionBoxShow=false; + +} + + +#include "jscodecompletion.moc" diff --git a/languages/kjssupport/jscodecompletion.h b/languages/kjssupport/jscodecompletion.h new file mode 100644 index 00000000..0cceb1e0 --- /dev/null +++ b/languages/kjssupport/jscodecompletion.h @@ -0,0 +1,53 @@ +// +// C++ Interface: jscodecompletion +// +// Description: +// +// +// Author: ian reinhart geiser <geiseri@kde.org>, (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef JSCODECOMPLETION_H +#define JSCODECOMPLETION_H + +#include <qobject.h> +#include <kdevelop/codemodel.h> +#include <kdevelop/kdevplugin.h> +#include <kdevelop/kdevlanguagesupport.h> + +#include <ktexteditor/editinterface.h> +#include <ktexteditor/viewcursorinterface.h> +#include <ktexteditor/codecompletioninterface.h> + +/** +The code completion engine for Javascript. + +@author ian reinhart geiser +*/ +class JSCodeCompletion : public QObject +{ + Q_OBJECT + public: + JSCodeCompletion(QObject *parent = 0, const char *name = 0); + + ~JSCodeCompletion(); + void setActiveEditorPart(KParts::Part* editorPart); + QValueList<KTextEditor::CompletionEntry> getVars(const QString& textHint); + + public slots: + void cursorPositionChanged(); + void completionBoxHidden(); + void completionBoxAbort(); + + private: + bool m_argWidgetShow; + bool m_completionBoxShow; + KTextEditor::EditInterface *m_editInterface; + KTextEditor::CodeCompletionInterface *m_codeInterface; + KTextEditor::ViewCursorInterface *m_cursorInterface; + +}; + +#endif diff --git a/languages/kjssupport/kdevkjssupport.desktop b/languages/kjssupport/kdevkjssupport.desktop new file mode 100644 index 00000000..d60863b8 --- /dev/null +++ b/languages/kjssupport/kdevkjssupport.desktop @@ -0,0 +1,54 @@ +[Desktop Entry] +Type=Service +Exec=blubb +Comment=kjsSupport +Comment[da]=kjs-understøttelse +Comment[et]=kjs toetus +Comment[fa]=پشتیبانی kjs +Comment[nds]=KDE-Ünnerstütten för JavaScript +Comment[pl]=Obsługakjs +Comment[sk]=kjs podpora +Comment[sv]=Javaskript-stöd +Comment[zh_TW]=kjs 支援 +Name=KDevkjsSupport +Name[da]=KDevelop Bash-understøttelse +Name[nds]=KJS-Ünnerstütten för KDevelop +Name[pl]=KDevObsługakjs +Name[sk]=KDev kjs podpora +Name[sv]=KDevelop Javaskript-stöd +Name[zh_TW]=KDevelop kjs 支援 +GenericName=KDE JavaScript Support +GenericName[ca]=Suport per a JavaScript per al KDE +GenericName[da]=KDE JavaScript-understøttelse +GenericName[de]=Unterstützung für KDE-JavaScript +GenericName[el]=Υποστήριξη KDE JavaScript +GenericName[es]=Soporte para JavaScript de KDE +GenericName[et]=KDE JavaScripti toetus +GenericName[eu]=KDE JavaScript euskarria +GenericName[fa]=پشتیبانی جاوااسکریپت KDE +GenericName[fr]=Prise en charge du JavaScript pour KDE +GenericName[ga]=Tacaíocht JavaScript KDE +GenericName[gl]=Soporte para JavaScript de KDE +GenericName[hu]=KDE Javascript-támogatás +GenericName[it]=Supporto JavaScript di KDE +GenericName[ja]=KDE JavaScript サポート +GenericName[nds]=KDE-Ünnerstütten för JavaScript +GenericName[ne]=केडीई जाभास्क्रिप्ट समर्थन +GenericName[nl]=KDE ondersteuning voor JavaScript +GenericName[pl]=Obsługa JavaScriptu KDE +GenericName[pt]=Suporte KDE a JavaScript +GenericName[pt_BR]=Suporte ao JavaScript do KDE +GenericName[ru]=Поддержка языка JavaScript +GenericName[sk]=KDE JavaScript podpora +GenericName[sl]=Podpora javascriptu v KDE +GenericName[sr]=KDE-ова подршка за Javascript +GenericName[sr@Latn]=KDE-ova podrška za Javascript +GenericName[sv]=KDE Javaskript-stöd +GenericName[tr]=KDE JavaScript Desteği +GenericName[zh_CN]=KDE JavaScript 支持 +GenericName[zh_TW]=KDE JavaScript 支援 +Icon=kdevelop +ServiceTypes=KDevelop/LanguageSupport +X-KDevelop-Language=Javascript +X-KDE-Library=libkdevkjssupport +X-KDevelop-Version=3 diff --git a/languages/kjssupport/kdevkjssupport.rc b/languages/kjssupport/kdevkjssupport.rc new file mode 100644 index 00000000..e48fc863 --- /dev/null +++ b/languages/kjssupport/kdevkjssupport.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="KDevkjsSupport" version="1"> +<MenuBar> + <Menu name="build" > + <Action name="build_execute" /> + </Menu> +</MenuBar> +<ToolBar name="mainToolBar"> + <Action name="build_execute" group="build_operations" /> +</ToolBar> +</kpartgui> diff --git a/languages/kjssupport/kjsproblems.cpp b/languages/kjssupport/kjsproblems.cpp new file mode 100644 index 00000000..39084169 --- /dev/null +++ b/languages/kjssupport/kjsproblems.cpp @@ -0,0 +1,78 @@ +/* + Copyright (C) 2003 ian reinhart geiser <geiseri@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + version 2, License as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kjsproblems.h" +#include "kjssupport_part.h" +#include <kiconloader.h> + +class KJSProblemItem: public KListViewItem +{ + public: + KJSProblemItem( QListView* parent, const QString& level, const QString& problem, + const QString& file, const QString& line, const QString& column ) + : KListViewItem( parent, level, problem, file, line, column ) + {} + + KJSProblemItem( QListViewItem* parent, const QString& level, const QString& problem, + const QString& file, const QString& line, const QString& column ) + : KListViewItem( parent, level, problem, file, line, column ) + {} + + int compare( QListViewItem* item, int column, bool ascending ) const + { + if( column == 2 || column == 3 ) + { + int a = text( column ).toInt(); + int b = item->text( column ).toInt(); + if( a == b ) + return 0; + return( a > b ? 1 : -1 ); + } + return KListViewItem::compare( item, column, ascending ); + } + +}; + +KJSProblems::KJSProblems(kjsSupportPart *part, QWidget *parent, const char *name) : KListView(parent,name), m_part(part) +{ + addColumn ("File"); + addColumn ("Line #"); + addColumn ("Problem:"); + setIcon( SmallIcon("info") ); +} + + +KJSProblems::~KJSProblems() +{ + +} + +void KJSProblems::clearItems() +{ + clear(); + setIcon( SmallIcon("info") ); +} + +void KJSProblems::addLine(const QString &file, int lineNo, const QString &message) +{ + new QListViewItem( this, file, QString::number( lineNo ), message); + setIcon( SmallIcon("error") ); +} + + +#include "kjsproblems.moc" diff --git a/languages/kjssupport/kjsproblems.h b/languages/kjssupport/kjsproblems.h new file mode 100644 index 00000000..d7d47c63 --- /dev/null +++ b/languages/kjssupport/kjsproblems.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2003 ian reinhart geiser <geiseri@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + version 2, License as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef KJSPROBLEMS_H +#define KJSPROBLEMS_H + +#include <klistview.h> +class kjsSupportPart; + +/** +@author ian reinhart geiser +*/ +class KJSProblems : public KListView +{ +Q_OBJECT +public: + + KJSProblems(kjsSupportPart *part, QWidget *parent = 0L, const char *name = 0L); + ~KJSProblems(); + + void clearItems(); + void addLine(const QString &file, int lineNo, const QString &message); + +private: + kjsSupportPart *m_part; +}; + +#endif diff --git a/languages/kjssupport/kjssupport_part.cpp b/languages/kjssupport/kjssupport_part.cpp new file mode 100644 index 00000000..c4907991 --- /dev/null +++ b/languages/kjssupport/kjssupport_part.cpp @@ -0,0 +1,448 @@ +/* + Copyright (C) 2003 ian reinhart geiser <geiseri@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + version 2, License as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <qwhatsthis.h> +#include <qtimer.h> +#include <qfileinfo.h> +#include <qtextstream.h> +#include <qregexp.h> +#include <qpopupmenu.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kgenericfactory.h> +#include <kdevcore.h> +#include <kdevpartcontroller.h> +#include <kdevmainwindow.h> +#include <domutil.h> +#include <codemodel.h> +#include <kparts/part.h> + + +#include <kdevproject.h> +#include <kaction.h> +#include <kdebug.h> +#include <kapplication.h> + +#include <kjsembed/kjsembedpart.h> +#include <kjsembed/jsconsolewidget.h> + +#include <kdevplugininfo.h> + +#include "kjssupport_part.h" +#include "kjsproblems.h" +#include "jscodecompletion.h" +#include "subclassingdlg.h" + +typedef KDevGenericFactory<kjsSupportPart> kjsSupportFactory; +static const KDevPluginInfo data("kdevkjssupport"); +K_EXPORT_COMPONENT_FACTORY( libkdevkjssupport, kjsSupportFactory( data ) ); + + +class typeProperty +{ + public: + QString type; + QString name; + int depth; +}; + +kjsSupportPart::kjsSupportPart(QObject *parent, const char *name, const QStringList& ) +: KDevLanguageSupport(&data, parent, name ? name : "kjsSupportPart" ) +{ + setInstance(kjsSupportFactory::instance()); + setXMLFile("kdevkjssupport.rc"); + + + m_build = new KAction( i18n("&Run"), "exec",Key_F9,this, SLOT(slotRun()),actionCollection(), "build_execute" ); + m_build->setStatusText( i18n("Test the active script.") ); + + kdDebug() << "Creating kjssupport Part" << endl; + + connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)), + this, SLOT(projectConfigWidget(KDialogBase*)) ); + connect( core(), SIGNAL(projectOpened()), this, SLOT(projectOpened()) ); + connect( core(), SIGNAL(projectClosed()), this, SLOT(projectClosed()) ); + connect( partController(), SIGNAL(savedFile(const QString&)), this, SLOT(savedFile(const QString&)) ); + connect(partController(), SIGNAL(activePartChanged(KParts::Part*)), + this, SLOT(slotActivePartChanged(KParts::Part *))); + connect(core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)), + this, SLOT(contextMenu(QPopupMenu *, const Context *))); + + + // Building kjs interpreter. + m_js = new KJSEmbed::KJSEmbedPart(); + mainWindow()->embedOutputView( m_js->view() , i18n("KJS Console"),i18n("KJS Embed Console") ); + + // get the problem reporter + m_problemReporter = new KJSProblems( this, 0, "problems" ); + mainWindow( )->embedOutputView( m_problemReporter, i18n("Problems"), i18n("Problem reporter")); + m_cc = new JSCodeCompletion(); + } + + +kjsSupportPart::~kjsSupportPart() +{ + delete m_problemReporter; + delete m_cc; + delete m_build; + delete m_js; +} + +KDevLanguageSupport::Features kjsSupportPart::features() +{ + return Features(Classes | Variables | Functions); +} + +KMimeType::List kjsSupportPart::mimeTypes() +{ + KMimeType::List list; + + KMimeType::Ptr mime = KMimeType::mimeType( "application/x-javascript" ); + if( mime ) + list << mime; + + return list; +} +void kjsSupportPart::slotRun() +{ + // Execute the application here. + + KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart*>( partController()->activePart() ); + if ( ro_part ) + { + m_js->runFile( ro_part->url().path() ); + } + +} + +void kjsSupportPart::projectConfigWidget(KDialogBase *dlg) +{ + Q_UNUSED( dlg ); + // Create your config dialog here. +} +void kjsSupportPart::projectOpened() +{ + kdDebug(9014) << "projectOpened()" << endl; + + connect( project(), SIGNAL(addedFilesToProject(const QStringList &)), + this, SLOT(addedFilesToProject(const QStringList &)) ); + connect( project(), SIGNAL(removedFilesFromProject(const QStringList &)), + this, SLOT(removedFilesFromProject(const QStringList &)) ); + + // We want to parse only after all components have been + // properly initialized + QTimer::singleShot(0, this, SLOT(parse())); +} +void kjsSupportPart::projectClosed() +{ + +} +void kjsSupportPart::savedFile(const QString &fileName) +{ + + + if (project()->allFiles().contains(fileName.mid ( project()->projectDirectory().length() + 1 ))) + { + kdDebug(9014) << "parse file " << fileName << endl; + parse( fileName ); + emit addedSourceInfo( fileName ); + } +} +void kjsSupportPart::addedFilesToProject(const QStringList &fileList) +{ + kdDebug(9014) << "addedFilesToProject()" << endl; + + QStringList::ConstIterator it; + + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + kdDebug(9014) << "maybe parse " << project()->projectDirectory() + "/" + ( *it ) << endl; + parse( project()->projectDirectory() + "/" + (*it) ); + } + + emit updatedSourceInfo(); +} +void kjsSupportPart::removedFilesFromProject(const QStringList &fileList) +{ + + + QStringList::ConstIterator it; + + for ( it = fileList.begin(); it != fileList.end(); ++it ) + { + QString fileName = project()->projectDirectory() + "/" + ( *it ); + if( codeModel()->hasFile(fileName) ) + { + kdDebug(9014) << "removed " << fileName << endl; + emit aboutToRemoveSourceInfo( fileName ); + codeModel()->removeFile( codeModel()->fileByName(fileName) ); + } + } + +} +void kjsSupportPart::parse() +{ + kdDebug(9014) << "initialParse()" << endl; + + if (project()) + { + kapp->setOverrideCursor(waitCursor); + QStringList files = project()->allFiles(); + m_problemReporter->clear(); + + for (QStringList::Iterator it = files.begin(); it != files.end() ;++it) + { + kdDebug(9014) << "maybe parse " << project()->projectDirectory() + "/" + (*it) << endl; + + parse( project()->projectDirectory() + "/" + (*it) ); + + } + emit updatedSourceInfo(); + kapp->restoreOverrideCursor(); + } else { + kdDebug(9014) << "No project" << endl; + } +} +void kjsSupportPart::slotActivePartChanged(KParts::Part *part) +{ + kdDebug() << "Changeing active part..." << endl; + m_cc->setActiveEditorPart(part); +} + +/*! + \fn kjsSupportPart::parse(const QString &fileName) + */ +void kjsSupportPart::parse(const QString &fileName) +{ + QFileInfo fi(fileName); + if (fi.extension() == "js") + { + if( codeModel()->hasFile(fileName) ) + { + emit aboutToRemoveSourceInfo( fileName ); + codeModel()->removeFile( codeModel()->fileByName(fileName) ); + } + + FileDom m_file = codeModel()->create<FileModel>(); + m_file->setName( fileName ); + m_file->setFileName( fileName ); + + QFile f(QFile::encodeName(fileName)); + if (!f.open(IO_ReadOnly)) + return; + QString rawline; + QString line; + uint lineNo = 0; + QTextStream stream(&f); + int depth = 0; + bool inFunction = false; + QString lastFunction = ""; + int lastLineNo = 0; + ClassDom currentClass; + + QRegExp varRx("var[\\s]([_a-zA-Z\\d]+)"); + QRegExp classVarRx("this\\.([_a-zA-Z\\d]+)"); + QRegExp classMethRx("this\\.([_a-zA-Z\\d]+)[\\s]*=[\\s]*function(\\([^){}\\n\\r]*\\))"); + QRegExp methRx("function[\\s]+([_a-zA-Z\\d]+[\\s]*\\([^){}\\n\\r]*\\))"); + QRegExp allocRx("([_\\d\\w]+)[\\s]*=[\\s]*new[\\s]*([_\\d\\w]+)"); + QRegExp assnRx("var[\\s]+([_\\d\\w]+)[\\s]+[=][\\s]+([_\\d\\w]+)[;]"); + + while (!stream.atEnd()) + { + rawline = stream.readLine(); + line = rawline.stripWhiteSpace().local8Bit(); + kdDebug() << "Trying line: " << line << endl; + + if (methRx.search(line) != -1 && depth == 0) + { + if (lastFunction != "" ) + addMethod(lastFunction, m_file, lastLineNo); + lastFunction = methRx.cap(1); + lastLineNo = lineNo; + } + else if(varRx.search(line) != -1 && depth == 0) + { + addAttribute(varRx.cap(1), m_file, lineNo); + } + else if(classMethRx.search(line) != -1 && depth > 0) + { + if ( lastFunction != "" ) + { + currentClass = addClass(lastFunction, m_file, lastLineNo ); + lastFunction = ""; + } + addMethod(classMethRx.cap(1)+classMethRx.cap(2), currentClass, lineNo); + } + else if(classVarRx.search(line) != -1 && depth > 0) + { + if ( lastFunction != "" ) + { + currentClass = addClass(lastFunction, m_file, lastLineNo ); + lastFunction = ""; + } + addAttribute(classVarRx.cap(1), currentClass, lineNo); + } + + if( allocRx.search(line) != -1 ) + { + QString varName = allocRx.cap(1); + QString varType = allocRx.cap(2); + + typeProperty *type = new typeProperty(); + type->depth = depth; + type->name = varName; + type->type = varType; + + m_typeMap.insert(varName, type); + kdDebug() << "Adding " << varName << " of type " << varType << " at scope " << depth << endl; + + } + + + kdDebug() << "Syntax check..." << endl; + KJS::UString jsLine( line.latin1() ); + int lineNumber = 0; + KJS::UString errorMessage; + + if ( !m_js->interpreter()->checkSyntax( jsLine, &lineNumber, &errorMessage ) ) + { + kdDebug() << errorMessage.qstring() << " on line " << lineNo << endl; + m_problemReporter->addLine(m_file->fileName(), lineNo, errorMessage.qstring()); + } + + if( line.contains("{") ) + ++depth; + + if( line.contains("}") ) + --depth; + + ++lineNo; + } + + if (lastFunction != "" ) + addMethod(lastFunction, m_file, lastLineNo); + + f.close(); + + kdDebug() << "Trying to add list..." << endl; + + codeModel()->addFile( m_file ); + + + } +} + +ClassDom kjsSupportPart::addClass(const QString &name, FileDom file, uint lineNo) +{ + ClassDom clazz = codeModel()->create<ClassModel>(); + clazz->setName(name); + clazz->setFileName(file->fileName()); + clazz->setStartPosition(lineNo, 0); + + if( !file->hasClass(clazz->name()) ){ + kdDebug() << "Add global class " << clazz->name() << endl; + file->addClass( clazz ); + } + return clazz; +} + +void kjsSupportPart::addMethod(const QString &name, ClassDom clazz, uint lineNo) +{ + FunctionDom method = codeModel()->create<FunctionModel>(); + method->setName(name); + method->setFileName(clazz->fileName()); + method->setStartPosition(lineNo, 0); + + if( !clazz->hasFunction(method->name()) ){ + kdDebug() << "Add class method " << method->name() << endl; + clazz->addFunction( method ); + } +} + +void kjsSupportPart::addAttribute(const QString &name, ClassDom clazz, uint lineNo) +{ + VariableDom var = codeModel()->create<VariableModel>(); + var->setName(name); + var->setFileName(clazz->fileName()); + var->setStartPosition( lineNo, 0 ); + var->setType(i18n("Variable")); + + if( !clazz->hasVariable(var->name()) ){ + kdDebug() << "Add class attribute " << var->name() << endl; + clazz->addVariable(var); + } +} + +void kjsSupportPart::addMethod(const QString &name, FileDom file, uint lineNo) +{ + FunctionDom method = codeModel()->create<FunctionModel>(); + method->setName(name); + method->setFileName(file->fileName()); + method->setStartPosition(lineNo, 0); + + if( !file->hasFunction(method->name()) ){ + kdDebug() << "Add global method " << method->name() << endl; + file->addFunction( method ); + } +} + +void kjsSupportPart::addAttribute(const QString &name, FileDom file, uint lineNo) +{ + VariableDom var = codeModel()->create<VariableModel>(); + var->setName(name); + var->setFileName(file->fileName()); + var->setStartPosition( lineNo, 0 ); + var->setType(i18n("Variable")); + + if( !file->hasVariable(var->name()) ){ + kdDebug() << "Add global attribute " << var->name() << endl; + file->addVariable(var); + } +} + +void kjsSupportPart::contextMenu(QPopupMenu * popupMenu, const Context *context) +{ + kdDebug() << "1" << endl; + if (!context->hasType( Context::FileContext )) + return; + + kdDebug() << "2" << endl; + const FileContext *fcontext = static_cast<const FileContext*>(context); + m_selectedUI = fcontext->fileName(); + if (m_selectedUI.right(3).lower() == ".ui") + int id = popupMenu->insertItem(i18n("Implement Slots"), + this, SLOT(implementSlots())); + else + m_selectedUI = QString::null; +} + +void kjsSupportPart::implementSlots() +{ + if (m_selectedUI.isEmpty()) + return; + + QStringList newFiles; + SubclassingDlg *sub = new SubclassingDlg(this, m_selectedUI, newFiles); + if (sub->exec()) + project()->addFiles(newFiles); + + delete sub; +} + +#include "kjssupport_part.moc" diff --git a/languages/kjssupport/kjssupport_part.h b/languages/kjssupport/kjssupport_part.h new file mode 100644 index 00000000..67e35f07 --- /dev/null +++ b/languages/kjssupport/kjssupport_part.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2003 ian reinhart geiser <geiseri@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + version 2, License as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#ifndef __KDEVPART_KJSSUPPORT_H__ +#define __KDEVPART_KJSSUPPORT_H__ + + +#include <kdevelop/kdevplugin.h> +#include <kdevelop/codemodel.h> +#include <kdevelop/kdevlanguagesupport.h> +#include <kdialogbase.h> +#include <qstringlist.h> +#include <qdict.h> + +namespace KJSEmbed +{ +class KJSEmbedPart; +class KJSConsoleWidget; +}; + +class QPopupMenu; +class KAction; +class KJSProblems; +class JSCodeCompletion; +class Context; + +class typeProperty; + + +class kjsSupportPart : public KDevLanguageSupport +{ + Q_OBJECT + public: + kjsSupportPart(QObject *parent, const char *name, const QStringList &); + ~kjsSupportPart(); + protected: + virtual Features features(); + virtual KMimeType::List mimeTypes(); + + private slots: + void slotRun(); + void projectConfigWidget(KDialogBase *dlg); + void projectOpened(); + void projectClosed(); + void savedFile(const QString &fileName); + void addedFilesToProject(const QStringList &fileList); + void removedFilesFromProject(const QStringList &fileList); + void parse(); + void slotActivePartChanged(KParts::Part *part); + void contextMenu(QPopupMenu *popupMenu, const Context *context); + void implementSlots(); + private: + void parse(const QString &fileName); + void addAttribute(const QString &name, ClassDom clazz, uint lineNo); + void addMethod(const QString &name, ClassDom clazz, uint lineNo); + void addAttribute(const QString &name, FileDom file, uint lineNo); + void addMethod(const QString &name, FileDom file, uint lineNo); + ClassDom addClass(const QString &name, FileDom file, uint lineNo); + KAction *m_build; + KJSEmbed::KJSEmbedPart *m_js; + KJSProblems *m_problemReporter; + QDict<typeProperty> m_typeMap; + JSCodeCompletion *m_cc; + + QString m_selectedUI; +}; + + +#endif diff --git a/languages/kjssupport/subclassing_template/Makefile.am b/languages/kjssupport/subclassing_template/Makefile.am new file mode 100644 index 00000000..8c99d172 --- /dev/null +++ b/languages/kjssupport/subclassing_template/Makefile.am @@ -0,0 +1,3 @@ +kjssupportdatadir = ${kde_datadir}/kdevkjssupport +subclassingdir = ${kjssupportdatadir}/subclassing +subclassing_DATA = subclass_template.js diff --git a/languages/kjssupport/subclassing_template/subclass_template.js b/languages/kjssupport/subclassing_template/subclass_template.js new file mode 100644 index 00000000..568c5699 --- /dev/null +++ b/languages/kjssupport/subclassing_template/subclass_template.js @@ -0,0 +1,2 @@ +//Slot implementations and slot-signal connections for $BASEFILENAME$ form +/*$SPECIALIZATION$*/ diff --git a/languages/kjssupport/subclassingdlg.cpp b/languages/kjssupport/subclassingdlg.cpp new file mode 100644 index 00000000..be1ad83e --- /dev/null +++ b/languages/kjssupport/subclassingdlg.cpp @@ -0,0 +1,461 @@ +/*************************************************************************** + * Copyright (C) 2002 by Jakob Simon-Gaarde * + * jsgaarde@tdcspace.dk * + * Copyright (C) 2003 by Alexander Dymo * + * cloudtemple@mksat.net * + * * + * 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 "subclassingdlg.h" +#include "kjssupport_part.h" +/*#include "backgroundparser.h" +#include "store_walker.h" +#include "cppsupportfactory.h"*/ +#include <kdevelop/kdevsourceformatter.h> +#include <kdevelop/kdevproject.h> +#include <kdevelop/filetemplate.h> +#include <kdevelop/codemodel.h> + +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qcheckbox.h> +#include <qmessagebox.h> +#include <kfiledialog.h> +#include <klineedit.h> +#include <qpushbutton.h> +#include <domutil.h> +#include <qdom.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <klocale.h> +#include <qfile.h> +#include <qregexp.h> +#include <kconfig.h> + + +#define WIDGET_CAPTION_NAME "widget/property|name=caption/string" +#define WIDGET_CLASS_NAME "class" +#define WIDGET_SLOTS "slots" +#define WIDGET_FUNCTIONS "functions" + +// All widgets +#define SLOT_ACCEPT SlotItem(m_slotView,"accept()","virtual","protected","void",false,true) +#define SLOT_REJECT SlotItem(m_slotView,"reject()","virtual","protected","void",false,true) + +// Wizards +#define SLOT_BACK SlotItem(m_slotView,"back()","virtual","protected","void",false,true) +#define SLOT_NEXT SlotItem(m_slotView,"next()","virtual","protected","void",false,true) +#define SLOT_HELP SlotItem(m_slotView,"help()","virtual","protected","void",false,true) + + +SlotItem::SlotItem(QListView *parent,const QString &methodName, + const QString &specifier, + const QString &access, const QString &returnType, + bool isFunc,bool callBaseClass) +: QCheckListItem(parent,methodName,QCheckListItem::CheckBox) +{ + setOn(true); + m_methodName = methodName; + m_access = access.isEmpty() ? (const QString) "public" : access; + m_specifier = specifier.isEmpty() ? (const QString) "virtual" : specifier; + m_returnType = returnType.isEmpty() ? (const QString) "void" : returnType; + m_isFunc = isFunc; + m_callBaseClass = callBaseClass; + setText(0,m_methodName); + setText(1,m_access); + setText(2,m_specifier); + setText(3,m_returnType); + setText(4,m_isFunc ? "Function" : "Slot"); + if (m_access=="private" || + m_specifier=="non virtual") + { + setOn(false); + setEnabled(false); + } + if (m_specifier=="pure virtual") + { + setOn(true); + setEnabled(false); + } + m_alreadyInSubclass = false; +} + +void SlotItem::setAllreadyInSubclass() +{ + setOn(true); + setEnabled(false); + m_alreadyInSubclass = true; +} + + +SubclassingDlg::SubclassingDlg(kjsSupportPart* kjsSupport, const QString &formFile,QStringList &newFileNames, + QWidget* parent, const char* name,bool modal, WFlags fl) +: SubclassingDlgBase(parent,name,modal,fl), +m_newFileNames(newFileNames), m_kjsSupport( kjsSupport ) +//================================================= +{ + m_formFile = formFile; + readUiFile(); + m_creatingNewSubclass = true; + +/* KConfig *config = kjsSupportFactory::instance()->config(); + if (config) + { + config->setGroup("Subclassing"); + reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); + if (reformatDefault_box->isChecked()) + reformat_box->setChecked(true); + }*/ +// m_btnOk->setEnabled(true); +} + + +/*SubclassingDlg::SubclassingDlg(kjsSupportPart* kjsSupport, const QString &formFile,const QString &filename,QStringList &dummy, + QWidget* parent, const char* name,bool modal, WFlags fl) +: SubclassingDlgBase(parent,name,modal,fl), +m_newFileNames(dummy), m_kjsSupport( kjsSupport ) +//================================================= +{ + m_formFile = formFile; + m_creatingNewSubclass = false; + m_filename = filename; + + KConfig *config = kjsSupportFactory::instance()->config(); + if (config) + { + config->setGroup("Subclassing"); + reformatDefault_box->setChecked(config->readBoolEntry("Reformat Source", 0)); + if (reformatDefault_box->isChecked()) + reformat_box->setChecked(true); + } + + QStringList pathsplit(QStringList::split('/',filename)); + + QString baseClass = readBaseClassName(); + if (!kjsSupport->codeModel()->hasFile(filename+QString(".h"))) + return; + ClassList myClasses = kjsSupport->codeModel()->fileByName(filename+QString(".h"))->classList(); + for (ClassList::const_iterator classIt = myClasses.begin(); classIt != myClasses.end(); ++classIt) + { + kdDebug() << "base class " << baseClass << " class " << (*classIt)->name() + << " parents " << (*classIt)->baseClassList().join(",") << endl; + if ( (*classIt)->baseClassList().findIndex(baseClass) != -1 ) + { + kdDebug() << "base class matched " << endl; + m_edClassName->setText((*classIt)->name()); + m_edFileName->setText(pathsplit[pathsplit.count()-1]); + + FunctionList functionList = (*classIt)->functionList(); + for (FunctionList::const_iterator methodIt = functionList.begin(); + methodIt != functionList.end(); ++methodIt) + { + m_parsedMethods << (*methodIt)->name() + "("; + } + } + } + readUiFile(); + m_btnOk->setEnabled(true); +} +*/ +bool SubclassingDlg::alreadyInSubclass(const QString &method) +{ + for (uint i=0;i<m_parsedMethods.count();i++) + if (method.find(m_parsedMethods[i])==0) + return true; + return false; +} + +void SubclassingDlg::readUiFile() +{ + QStringList splitPath = QStringList::split('/',m_formFile); + m_formName = QStringList::split('.',splitPath[splitPath.count()-1])[0]; // "somedlg.ui" = "somedlg" + splitPath.pop_back(); + m_formPath = "/" + splitPath.join("/"); // join path to ui-file + + m_btnOk->setEnabled(false); + QDomDocument doc; + + DomUtil::openDOMFile(doc,m_formFile); + m_baseClassName = DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); + + m_baseCaption = DomUtil::elementByPathExt(doc,WIDGET_CAPTION_NAME).text(); + setCaption(i18n("Create Subclass of ")+m_baseClassName); + + // Special widget specific slots + SlotItem *newSlot; + m_qtBaseClassName = DomUtil::elementByPathExt(doc,"widget").attribute("class","QDialog"); + + if ( (m_qtBaseClassName=="QMainWindow") || (m_qtBaseClassName=="QWidget") ) + m_canBeModal = false; + else + m_canBeModal = true; + if (m_qtBaseClassName != "QWidget") + { + newSlot = new SLOT_ACCEPT; + newSlot->setOn(false); + if (alreadyInSubclass("accept()")) + newSlot->setAllreadyInSubclass(); + m_slotView->insertItem(newSlot); + m_slots << newSlot; + + newSlot = new SLOT_REJECT; + newSlot->setOn(false); + if (alreadyInSubclass("reject()")) + newSlot->setAllreadyInSubclass(); + m_slotView->insertItem(newSlot); + m_slots << newSlot; + } + + if (m_qtBaseClassName == "QWizard") + { + newSlot = new SLOT_NEXT; + m_slotView->insertItem(newSlot); + if (alreadyInSubclass("next()")) + newSlot->setAllreadyInSubclass(); + m_slots << newSlot; + newSlot = new SLOT_BACK; + m_slotView->insertItem(newSlot); + if (alreadyInSubclass("back()")) + newSlot->setAllreadyInSubclass(); + m_slots << newSlot; + newSlot = new SLOT_HELP; + newSlot->setOn(false); + if (alreadyInSubclass("help()")) + newSlot->setAllreadyInSubclass(); + m_slotView->insertItem(newSlot); + m_slots << newSlot; + } + + QDomElement slotsElem = DomUtil::elementByPathExt(doc,WIDGET_SLOTS); + QDomNodeList slotnodes = slotsElem.childNodes(); + + for (unsigned int i=0; i<slotnodes.count();i++) + { + QDomElement slotelem = slotnodes.item(i).toElement(); + newSlot = new SlotItem(m_slotView,slotelem.text(), + slotelem.attributeNode("specifier").value(), + slotelem.attributeNode("access").value(), + slotelem.attributeNode("returnType").value(),false); + m_slotView->insertItem(newSlot); + if (alreadyInSubclass(slotelem.text())) + newSlot->setAllreadyInSubclass(); + m_slots << newSlot; + } + + QDomElement funcsElem = DomUtil::elementByPathExt(doc,WIDGET_FUNCTIONS); + QDomNodeList funcnodes = funcsElem.childNodes(); + SlotItem *newFunc; + for (unsigned int i=0; i<funcnodes.count();i++) + { + QDomElement funcelem = funcnodes.item(i).toElement(); + newFunc = new SlotItem(m_slotView,funcelem.text(), + funcelem.attributeNode("specifier").value(), + funcelem.attributeNode("access").value(), + funcelem.attributeNode("returnType").value(),true); + m_slotView->insertItem(newFunc); + if (alreadyInSubclass(funcelem.text())) + newFunc->setAllreadyInSubclass(); + m_slots << newFunc; + } + + QDomElement connElem = DomUtil::elementByPathExt(doc,"connections"); + QDomNodeList connnodes = connElem.childNodes(); + for (unsigned int i=0; i<connnodes.count();i++) + { + QDomElement connelem = connnodes.item(i).toElement(); + connections += "$NEWCLASS$.connect("; + if (connelem.namedItem("sender").toElement().text() == m_baseClassName) + connections += "this"; + else + connections += "$NEWCLASS$.child('" + connelem.namedItem("sender").toElement().text() + "')"; + connections += ", '" + connelem.namedItem("signal").toElement().text() + "', "; + if (connelem.namedItem("receiver").toElement().text() == m_baseClassName) + connections += "this"; + else + connections += "$NEWCLASS$.child('" + connelem.namedItem("receiver").toElement().text() + "')"; + connections += ", '" + connelem.namedItem("slot").toElement().text().remove("()") + "');\n"; + } +} + +SubclassingDlg::~SubclassingDlg() +//=============================== +{ +} + + +void SubclassingDlg::updateDlg() +//============================== +{ +} + +void SubclassingDlg::replace(QString &string, const QString& search, const QString& replace) +//========================================================================================== +{ + int nextPos = string.find(search); + unsigned int searchLength = search.length(); + while (nextPos>-1) + { + string = string.replace(nextPos,searchLength,replace); + nextPos = string.find(search,nextPos+replace.length()); + } +} + +bool SubclassingDlg::loadBuffer(QString &buffer, const QString& filename) +//====================================================================== +{ + // open file and buffer it + QFile dataFile(filename); + if (!dataFile.open(IO_ReadOnly)) + return false; + char *temp = new char[dataFile.size()+1]; + dataFile.readBlock(temp,dataFile.size()); + temp[dataFile.size()]='\0'; + buffer = temp; + delete [] temp; + dataFile.close(); + return true; +} + +bool SubclassingDlg::replaceKeywords(QString &buffer,bool canBeModal) +//=================================================================== +{ + replace(buffer,"$NEWFILENAMEUC$",m_edFileName->text().upper()); + replace(buffer,"$BASEFILENAMELC$",m_formName.lower()); + replace(buffer,"$BASEFILENAME$",m_formName); + replace(buffer,"$NEWCLASS$",m_edClassName->text()); + replace(buffer,"$BASECLASS$",m_baseClassName); + replace(buffer,"$NEWFILENAMELC$",m_edFileName->text().lower()); + if (canBeModal) + { + replace(buffer,"$CAN_BE_MODAL_H$",", bool modal = FALSE"); + replace(buffer,"$CAN_BE_MODAL_CPP1$",", bool modal"); + replace(buffer,"$CAN_BE_MODAL_CPP2$",", modal"); + } + else + { + replace(buffer,"$CAN_BE_MODAL_H$",""); + replace(buffer,"$CAN_BE_MODAL_CPP1$",""); + replace(buffer,"$CAN_BE_MODAL_CPP2$",""); + } + + return true; +} + +bool SubclassingDlg::saveBuffer(QString &buffer, const QString& filename) +//======================================================================= +{ + // save buffer + + QFile dataFile(filename); + if (!dataFile.open(IO_WriteOnly | IO_Truncate)) + return false; + dataFile.writeBlock((buffer+"\n").ascii(),(buffer+"\n").length()); + dataFile.close(); + return true; +} + + +void SubclassingDlg::accept() +//=========================== +{ +/* KConfig *config = kjsSupportFactory::instance()->config(); + if (config) + { + config->setGroup("Subclassing"); + config->writeEntry("Reformat Source", reformatDefault_box->isChecked()); + }*/ + + unsigned int i; + + // h - file + + QString public_slot = + "/*$PUBLIC_SLOTS$*/\n "; + + QString protected_slot = + "/*$PROTECTED_SLOTS$*/\n "; + + QString public_func = + "/*$PUBLIC_FUNCTIONS$*/\n "; + + QString protected_func = + "/*$PROTECTED_FUNCTIONS$*/\n "; + + QString buffer; + if (m_creatingNewSubclass) + { + loadBuffer(buffer,::locate("data", "kdevkjssupport/subclassing/subclass_template.js")); + kdDebug() << "buffer: " << buffer << endl; + buffer = "var $NEWCLASS$ = Factory.loadui(\"$BASEFILENAME$.ui\", this);\n\n" + buffer; + buffer = FileTemplate::read(m_kjsSupport, "js") + buffer + connections; + kdDebug() << "buffer: " << buffer << endl; + QFileInfo fi(m_filename + ".js"); + QString module = fi.baseName(); + QString basefilename = fi.baseName(true); + buffer.replace(QRegExp("\\$MODULE\\$"),module); + buffer.replace(QRegExp("\\$FILENAME\\$"),basefilename); + } + else + loadBuffer(buffer,m_filename+".js"); + + // js - file + + QString implementation = + "/*$SPECIALIZATION$*/\n" + "function $METHOD$\n" + "{\n" + "}\n"; + + replaceKeywords(buffer,m_canBeModal); + for (i=0; i<m_slots.count(); i++) + { + SlotItem *slitem = m_slots[i]; + if (!slitem->isOn() || + slitem->m_alreadyInSubclass) + continue; + QString impl = implementation; + replace(impl,"$RETURNTYPE$",slitem->m_returnType); + replace(impl,"$NEWCLASS$",m_edClassName->text()); + replace(impl,"$METHOD$", slitem->m_methodName); + replace(impl,"$QTBASECLASS$", m_qtBaseClassName); + replace(buffer,"/*$SPECIALIZATION$*/",impl); + } + kdDebug() << buffer << endl; + + if (reformat_box->isChecked()) + buffer = m_kjsSupport->sourceFormatter()->formatSource(buffer); + + if (m_creatingNewSubclass) + saveBuffer(buffer,m_formPath + "/" + m_edFileName->text()+".js"); + else + saveBuffer(buffer,m_filename+".js"); + + if (m_creatingNewSubclass) + { + m_newFileNames.append(m_formPath + "/" + m_edFileName->text()+".js"); + } + SubclassingDlgBase::accept(); +} + +void SubclassingDlg::onChangedClassName() +//======================================= +{ + m_edFileName->setText(m_edClassName->text().lower()); + if (m_edFileName->text().isEmpty() || + m_edClassName->text().isEmpty()) + m_btnOk->setEnabled(false); + else + m_btnOk->setEnabled(true); +} + +QString SubclassingDlg::readBaseClassName( ) +{ + QDomDocument doc; + DomUtil::openDOMFile(doc,m_formFile); + return DomUtil::elementByPathExt(doc,WIDGET_CLASS_NAME).text(); +} diff --git a/languages/kjssupport/subclassingdlg.h b/languages/kjssupport/subclassingdlg.h new file mode 100644 index 00000000..c727b648 --- /dev/null +++ b/languages/kjssupport/subclassingdlg.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2002 by Jakob Simon-Gaarde * + * jsgaarde@tdcspace.dk * + * * + * 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 SUBCLASSINGDLG_H +#define SUBCLASSINGDLG_H + +#include <qlistview.h> + +#include "subclassingdlgbase.h" + +class QStringList; +class QDomDocument; +class kjsSupportPart; + +class SlotItem : public QCheckListItem +{ + public: + SlotItem(QListView *parent,const QString &text, + const QString &specifier, const QString &Access, + const QString &returnType,bool isFunc, + bool callBaseClass=false); + void setAllreadyInSubclass(); + QString m_access; + QString m_methodName; + QString m_returnType; + QString m_specifier; + bool m_isFunc; + bool m_callBaseClass; + bool m_alreadyInSubclass; +}; + + +class SubclassingDlg : public SubclassingDlgBase +{ +public: + SubclassingDlg(kjsSupportPart* kjsSupport, const QString &formFile,QStringList &newFileNames, + QWidget* parent = 0, const char* name = 0, + bool modal = FALSE, WFlags fl = 0 ); +/* SubclassingDlg(CppSupportPart* kjsSupport, const QString &formFile,const QString &filename,QStringList &dummy, + QWidget* parent = 0, const char* name = 0, + bool modal = FALSE, WFlags fl = 0 );*/ + ~SubclassingDlg(); + +private: + void readUiFile(); + QString readBaseClassName(); + void updateDlg(); + bool replaceKeywords(QString &buffer, bool canBeModal=true); + void replace(QString &string, const QString& search, const QString& replace); + bool saveBuffer(QString &buffer, const QString& filename); + bool loadBuffer(QString &buffer, const QString& filename); + bool alreadyInSubclass(const QString &method); + bool m_creatingNewSubclass; + +public slots: + virtual void accept(); + virtual void onChangedClassName(); + +protected: + QStringList &m_newFileNames; + QString m_filename; + QString m_formFile; + QString m_baseClassName; + QString m_qtBaseClassName; + QString m_baseCaption; + QString m_formName; + QString m_formPath; + QStringList m_parsedMethods; + bool m_canBeModal; + QValueList<SlotItem*> m_slots; + QValueList<SlotItem*> m_functions; + kjsSupportPart* m_kjsSupport; + QString connections; +}; + +#endif + diff --git a/languages/kjssupport/subclassingdlgbase.ui b/languages/kjssupport/subclassingdlgbase.ui new file mode 100644 index 00000000..fea5ef6d --- /dev/null +++ b/languages/kjssupport/subclassingdlgbase.ui @@ -0,0 +1,253 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>SubclassingDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>SubclassingDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>588</width> + <height>493</height> + </rect> + </property> + <property name="caption"> + <string>Implement Slots</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Properties</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>reformat_box</cstring> + </property> + <property name="text"> + <string>Re&format source</string> + </property> + </widget> + <widget class="QCheckBox" row="4" column="2"> + <property name="name"> + <cstring>reformatDefault_box</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Reformat source by &default</string> + </property> + </widget> + <widget class="QListView" row="3" column="0" rowspan="1" colspan="3"> + <column> + <property name="text"> + <string>Method</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Access</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Specifier</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Return Type</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Type</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_slotView</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Specialize following slots:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_slotView</cstring> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_edFileName</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>F&ile name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_edFileName</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>C&lass name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_edClassName</cstring> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_edClassName</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_btnOk</cstring> + </property> + <property name="text"> + <string>C&reate</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" row="1" column="2"> + <property name="name"> + <cstring>m_btnCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>110</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> +</widget> +<connections> + <connection> + <sender>m_btnOk</sender> + <signal>clicked()</signal> + <receiver>SubclassingDlgBase</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>m_btnCancel</sender> + <signal>clicked()</signal> + <receiver>SubclassingDlgBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>m_edClassName</sender> + <signal>textChanged(const QString&)</signal> + <receiver>SubclassingDlgBase</receiver> + <slot>onChangedClassName()</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_edClassName</tabstop> + <tabstop>m_edFileName</tabstop> + <tabstop>m_slotView</tabstop> + <tabstop>reformat_box</tabstop> + <tabstop>reformatDefault_box</tabstop> + <tabstop>m_btnOk</tabstop> + <tabstop>m_btnCancel</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<slots> + <slot>onChangedClassName()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/languages/kjssupport/template/Makefile.am b/languages/kjssupport/template/Makefile.am new file mode 100644 index 00000000..3244188a --- /dev/null +++ b/languages/kjssupport/template/Makefile.am @@ -0,0 +1,20 @@ +appwizarddatadir = ${kde_datadir}/kdevappwizard +commondatadir = ${appwizarddatadir}/template-common +jshellodir = ${appwizarddatadir}/template-jshello +templatedir = ${appwizarddatadir}/templates + +jshello_DATA = app.js app.kdevelop +template_DATA = jshello + +DISTCLEANFILES = script.local +EXTRA_DIST = script + +perl = perl + +script.local: ${srcdir}/script + cp ${srcdir}/script script.local ; \ + perl -npi -e 's%^#\!.*$$%#!'${perl}' -I'${commondatadir}'%g;' script.local + +install-data-local: script.local + $(mkinstalldirs) $(DESTDIR)$(jshellodir) + $(INSTALL_DATA) script.local $(DESTDIR)$(jshellodir)/script diff --git a/languages/kjssupport/template/app.js b/languages/kjssupport/template/app.js new file mode 100644 index 00000000..aa564dd6 --- /dev/null +++ b/languages/kjssupport/template/app.js @@ -0,0 +1,18 @@ +#!/usr/bin/env kjscmd + +// Create main view +var mw = new KMainWindow(); +var lv = new KListView( mw ); +mw.setCentralWidget(lv); + +lv.addColumn('One'); +lv.addColumn('Two'); +lv.addColumn('Three'); + +lv.insertItem( 'Something', "Nothing", "Thing" ); +lv.insertItem( 'Something', "Nothing", "Thing" ); +lv.insertItem( 'Something', "Nothing", "Thing" ); +lv.insertItem( 'Something', "Nothing", "Thing" ); + +mw.show(); + diff --git a/languages/kjssupport/template/app.kdevelop b/languages/kjssupport/template/app.kdevelop new file mode 100644 index 00000000..2bb39a0a --- /dev/null +++ b/languages/kjssupport/template/app.kdevelop @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<kdevelop> + <general> + <author>$AUTHOR$</author> + <email>$EMAIL$</email> + <version>$VERSION$</version> + <projectmanagement>KDevScriptProject</projectmanagement> + <primarylanguage>Javascript</primarylanguage> + <keywords> + <keyword>Javascript</keyword> + </keywords> + <ignoreparts> + <part>KDevFileView</part> + <part>KDevdistpart</part> + <part>KDevDebugger</part> + </ignoreparts> + </general> + <kdevscriptproject> + <general> + <activedir>src</activedir> + <includepatterns>*.js</includepatterns> + <excludepatterns>*~</excludepatterns> + </general> + </kdevscriptproject> + <kdevfileview> + <groups> + <group pattern="*.js" name="Scripts" /> + </groups> + </kdevfileview> + <kdevdoctreeview> + <ignoretocs> + <toc>kde</toc> + <toc>gtk</toc> + <toc>gnustep</toc> + <toc>python</toc> + <toc>perl</toc> + <toc>php</toc> + </ignoretocs> + </kdevdoctreeview> + <kdevfilecreate> + <useglobaltypes> + <type ext="js"/> + </useglobaltypes> + </kdevfilecreate> +</kdevelop> diff --git a/languages/kjssupport/template/jshello b/languages/kjssupport/template/jshello new file mode 100644 index 00000000..8013b033 --- /dev/null +++ b/languages/kjssupport/template/jshello @@ -0,0 +1,6 @@ +# KDE Config File +[General] +Name=Simple KJSEmbed Script +Category=Script +Comment=This generates a simplistic 'Hello world' program in KJSEmbed +FileTemplates=js,Javascript diff --git a/languages/kjssupport/template/script b/languages/kjssupport/template/script new file mode 100644 index 00000000..d3a808c5 --- /dev/null +++ b/languages/kjssupport/template/script @@ -0,0 +1,13 @@ +#!perl -I/usr/kde/3.1/share/apps/kdevappwizard/template-common + +use gideon; + +initGideon(); + +print "Installing project file\n"; +installHTML( "${src}/template-jshello/app.kdevelop", "${dest}/${APPNAMELC}.kdevelop" ); + +print "Installing application sources\n"; +install( "${src}/template-jshello/app.js", "${dest}/${APPNAMELC}.js" ); + +print "Finished\n"; diff --git a/languages/kjssupport/x-javascript-source.desktop b/languages/kjssupport/x-javascript-source.desktop new file mode 100644 index 00000000..5beeb52a --- /dev/null +++ b/languages/kjssupport/x-javascript-source.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +MimeType=dummy +Hidden=true + |