summaryrefslogtreecommitdiffstats
path: root/kig/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'kig/scripting')
-rw-r--r--kig/scripting/Makefile.am22
-rw-r--r--kig/scripting/newscriptwizard.cc234
-rw-r--r--kig/scripting/newscriptwizard.h72
-rw-r--r--kig/scripting/newscriptwizardbase.ui81
-rw-r--r--kig/scripting/python-kig.xml289
-rw-r--r--kig/scripting/python-scripting-api-dox-mainpage.dox26
-rw-r--r--kig/scripting/python_scripter.cc578
-rw-r--r--kig/scripting/python_scripter.h69
-rw-r--r--kig/scripting/python_type.cc195
-rw-r--r--kig/scripting/python_type.h63
-rw-r--r--kig/scripting/script-common.cc95
-rw-r--r--kig/scripting/script-common.h61
-rw-r--r--kig/scripting/script_mode.cc362
-rw-r--r--kig/scripting/script_mode.h119
14 files changed, 2266 insertions, 0 deletions
diff --git a/kig/scripting/Makefile.am b/kig/scripting/Makefile.am
new file mode 100644
index 00000000..c007a612
--- /dev/null
+++ b/kig/scripting/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES=$(all_includes) $(BOOST_PYTHON_INCLUDES)
+KDE_CXXFLAGS=$(USE_EXCEPTIONS)
+noinst_LTLIBRARIES=libscripting.la
+noinst_HEADERS = \
+ python_type.h \
+ python_scripter.h \
+ script-common.h \
+ script_mode.h \
+ newscriptwizard.h
+libscripting_la_SOURCES = \
+ python_type.cc \
+ python_scripter.cc \
+ script-common.cc \
+ script_mode.cc \
+ newscriptwizardbase.ui \
+ newscriptwizard.cc
+libscripting_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) -lkatepartinterfaces
+libscripting_la_LDFLAGS = $(all_libraries) $(PYTHON_LDFLAGS)
+METASOURCES=AUTO
+
+xml_DATA = python-kig.xml
+xmldir = $(kde_datadir)/katepart/syntax
diff --git a/kig/scripting/newscriptwizard.cc b/kig/scripting/newscriptwizard.cc
new file mode 100644
index 00000000..165f8e98
--- /dev/null
+++ b/kig/scripting/newscriptwizard.cc
@@ -0,0 +1,234 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 "newscriptwizard.h"
+#include "newscriptwizard.moc"
+
+#include "script_mode.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+//#include <kactionclasses.h>
+//#include <kactioncollection.h>
+// make it still work on old kde 3.1...
+#include <kaction.h>
+//
+#include <kapplication.h>
+#include <kglobalsettings.h>
+#include <kpopupmenu.h>
+#include <ktextedit.h>
+#include <ktexteditor/clipboardinterface.h>
+#include <ktexteditor/dynwordwrapinterface.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/editorchooser.h>
+#include <ktexteditor/popupmenuinterface.h>
+#include <ktexteditor/undointerface.h>
+#include <ktexteditor/view.h>
+
+#include <assert.h>
+
+NewScriptWizard::~NewScriptWizard()
+{
+ if ( !document )
+ {
+ delete textedit;
+ }
+ else
+ {
+ //restoring the state of the dynamic word wrap
+ dynamic_cast<KTextEditor::DynWordWrapInterface*>( editor )->setDynWordWrap( prevDynWordWrap );
+ delete editor->document();
+ }
+}
+
+NewScriptWizard::NewScriptWizard( QWidget* parent, ScriptModeBase* mode )
+ : NewScriptWizardBase( parent, "New Script Wizard" ),
+ mmode( mode )
+{
+ document = KTextEditor::EditorChooser::createDocument( 0, "KTextEditor::Document" );
+// document = 0;
+
+ gridLayout->expand( 2, 1 );
+
+ if ( !document )
+ {
+ // there is no KDE textditor component installed, so we'll use a
+ // simplier KTextEdit
+ textedit = new KTextEdit( mpcode, "textedit" );
+ textedit->setFont( KGlobalSettings::fixedFont() );
+ gridLayout->addWidget( textedit, 1, 0 );
+ }
+ else
+ {
+ // creating the 'view', hat is what the user see and interact with
+ editor = document->createView( mpcode, "editor" );
+ gridLayout->addWidget( editor, 1, 0 );
+
+ // casting to the interfaces we'll use often
+ hli = dynamic_cast<KTextEditor::HighlightingInterface*>( document );
+
+ // displaying the left border with line numbers
+ KToggleAction *a = dynamic_cast<KToggleAction*>( editor->actionCollection()->action("view_line_numbers") );
+ a->activate();
+
+ // saving the state of dynamic word wrap and disabling it
+ prevDynWordWrap = dynamic_cast<KTextEditor::DynWordWrapInterface*>( editor )->dynWordWrap();
+ dynamic_cast<KTextEditor::DynWordWrapInterface*>( editor )->setDynWordWrap( false );
+
+ // saving the "no highlight" id
+ noHlStyle = hli->hlMode();
+
+ // creating the popup menu
+ KPopupMenu* pm = new KPopupMenu( editor );
+ // creating the actions for the code editor...
+ KActionCollection* ac = new KActionCollection( editor );
+ KAction* undoAction = KStdAction::undo( this, SLOT( slotUndo() ), ac );
+ KAction* redoAction = KStdAction::redo( this, SLOT( slotRedo() ), ac );
+ KAction* cutAction = KStdAction::cut( this, SLOT( slotCut() ), ac );
+ KAction* copyAction = KStdAction::copy( this, SLOT( slotCopy() ), ac );
+ KAction* pasteAction = KStdAction::paste( this, SLOT( slotPaste() ), ac );
+ // ... and plugging them into the popup menu (to build it, of course :) )
+ undoAction->plug( pm );
+ redoAction->plug( pm );
+ pm->insertSeparator();
+ cutAction->plug( pm );
+ copyAction->plug( pm );
+ pasteAction->plug( pm );
+
+ // finally, we install the popup menu
+ dynamic_cast<KTextEditor::PopupMenuInterface*>( editor )->installPopup( pm );
+ }
+
+ connect( this, SIGNAL( helpClicked() ), this, SLOT( slotHelpClicked() ) );
+}
+
+void NewScriptWizard::back()
+{
+ if ( currentPage() == mpcode )
+ {
+ // currentPage() is not yet updated, so we're now entering the
+ // args page..
+ mmode->argsPageEntered();
+ }
+ else assert( false );
+ NewScriptWizardBase::back();
+}
+
+void NewScriptWizard::next()
+{
+ if ( currentPage() == mpargs )
+ mmode->codePageEntered();
+ else assert( false );
+ if ( !document )
+ {
+ textedit->setFocus();
+ }
+ else
+ {
+ editor->setFocus();
+ }
+ NewScriptWizardBase::next();
+}
+
+void NewScriptWizard::reject()
+{
+ if ( mmode->queryCancel() )
+ NewScriptWizardBase::reject();
+}
+
+void NewScriptWizard::accept()
+{
+ if ( mmode->queryFinish() )
+ NewScriptWizardBase::accept();
+}
+
+void NewScriptWizard::slotHelpClicked()
+{
+ kapp->invokeHelp( QString::fromLatin1( "scripting" ),
+ QString::fromLatin1( "kig" ) );
+}
+
+void NewScriptWizard::setText( const QString& text )
+{
+ if ( !document )
+ {
+ textedit->setText( text );
+ }
+ else
+ {
+ dynamic_cast<KTextEditor::EditInterface*>( document )->setText( text );
+ }
+}
+
+QString NewScriptWizard::text()
+{
+ if ( !document )
+ {
+ return textedit->text();
+ }
+ else
+ {
+ return dynamic_cast<KTextEditor::EditInterface*>( document )->text();
+ }
+}
+
+void NewScriptWizard::setType( ScriptType::Type type )
+{
+ labelFillCode->setText( ScriptType::fillCodeStatement( type ) );
+
+ if ( !!document )
+ {
+ if ( type != ScriptType::Unknown )
+ {
+ for ( uint i = 0; i < hli->hlModeCount(); ++i )
+ {
+ if ( hli->hlModeName( i ) == ScriptType::highlightStyle( type ) )
+ {
+ // we found our highlight style, setting it
+ hli->setHlMode( i );
+ return;
+ }
+ }
+ }
+ else
+ {
+ hli->setHlMode( noHlStyle );
+ }
+ }
+}
+
+void NewScriptWizard::slotUndo()
+{
+ dynamic_cast<KTextEditor::UndoInterface*>( document )->undo();
+}
+
+void NewScriptWizard::slotRedo() {
+ dynamic_cast<KTextEditor::UndoInterface*>( document )->redo();
+}
+
+void NewScriptWizard::slotCut() {
+ dynamic_cast<KTextEditor::ClipboardInterface*>( editor )->cut();
+}
+
+void NewScriptWizard::slotCopy() {
+ dynamic_cast<KTextEditor::ClipboardInterface*>( editor )->copy();
+}
+
+void NewScriptWizard::slotPaste() {
+ dynamic_cast<KTextEditor::ClipboardInterface*>( editor )->paste();
+}
diff --git a/kig/scripting/newscriptwizard.h b/kig/scripting/newscriptwizard.h
new file mode 100644
index 00000000..67b51d94
--- /dev/null
+++ b/kig/scripting/newscriptwizard.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 KIG_SCRIPTING_NEWSCRIPTWIZARD_H
+#define KIG_SCRIPTING_NEWSCRIPTWIZARD_H
+
+#include "newscriptwizardbase.h"
+
+#include "script-common.h"
+
+#include <ktextedit.h>
+#include <ktexteditor/document.h>
+#include <ktexteditor/highlightinginterface.h>
+#include <ktexteditor/view.h>
+
+#include <algorithm>
+
+class ScriptModeBase;
+
+class NewScriptWizard
+ : public NewScriptWizardBase
+{
+ Q_OBJECT
+ ScriptModeBase* mmode;
+public:
+ NewScriptWizard( QWidget* parent, ScriptModeBase* mode );
+ ~NewScriptWizard();
+
+ void back();
+ void next();
+ void reject();
+
+ void setText( const QString& text );
+ QString text();
+
+ void setType( ScriptType::Type type );
+
+public slots:
+ void slotHelpClicked();
+ void accept();
+
+ void slotUndo();
+ void slotRedo();
+ void slotCut();
+ void slotCopy();
+ void slotPaste();
+
+protected:
+ KTextEdit* textedit;
+ KTextEditor::Document* document;
+ KTextEditor::HighlightingInterface* hli;
+ KTextEditor::View* editor;
+
+ uint noHlStyle;
+ bool prevDynWordWrap;
+};
+
+#endif
diff --git a/kig/scripting/newscriptwizardbase.ui b/kig/scripting/newscriptwizardbase.ui
new file mode 100644
index 00000000..30117961
--- /dev/null
+++ b/kig/scripting/newscriptwizardbase.ui
@@ -0,0 +1,81 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>NewScriptWizardBase</class>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>NewScriptWizardBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>610</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>New Script</string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mpargs</cstring>
+ </property>
+ <attribute name="title">
+ <string>Select Arguments</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Select the argument objects ( if any )
+in the Kig window and press "Next".</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mpcode</cstring>
+ </property>
+ <attribute name="title">
+ <string>Enter Code</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>gridLayout</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelFillCode</cstring>
+ </property>
+ <property name="text">
+ <string>Now fill in the code:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktextedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kig/scripting/python-kig.xml b/kig/scripting/python-kig.xml
new file mode 100644
index 00000000..930d5f8f
--- /dev/null
+++ b/kig/scripting/python-kig.xml
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE language>
+<!-- Python syntax highlightning v0.9 by Per Wigren -->
+<!-- Python syntax highlightning v1.2.x for Kig by Pino Toscano -->
+<language name="Python-Kig" version="1.2.1" kateversion="2.1" section="Scripts" extensions="*.py;*.pyw" mimetype="application/x-python;text/x-python" casesensitive="1">
+ <highlighting>
+ <list name="prep">
+ <item> import </item>
+ <item> from </item>
+ <item> as </item>
+ </list>
+
+ <list name="statements">
+ <item> and </item>
+ <item> assert </item>
+ <item> break </item>
+ <item> class </item>
+ <item> continue </item>
+ <item> def </item>
+ <item> del </item>
+ <item> elif </item>
+ <item> else </item>
+ <item> except </item>
+ <item> exec </item>
+ <item> finally </item>
+ <item> for </item>
+ <item> global </item>
+ <item> if </item>
+ <item> in </item>
+ <item> is </item>
+ <item> lambda </item>
+ <item> not </item>
+ <item> or </item>
+ <item> pass </item>
+ <item> print </item>
+ <item> raise </item>
+ <item> return </item>
+ <item> try </item>
+ <item> while </item>
+ <item> yield </item>
+ </list>
+
+ <list name="builtinfuncs">
+ <item> abs </item>
+ <item> apply </item>
+ <item> buffer </item>
+ <item> callable </item>
+ <item> chr </item>
+ <item> cmp </item>
+ <item> coerce </item>
+ <item> compile </item>
+ <item> complex </item>
+ <item> copyright </item>
+ <item> credits </item>
+ <item> delattr </item>
+ <item> dir </item>
+ <item> divmod </item>
+ <item> eval </item>
+ <item> execfile </item>
+ <item> exit </item>
+ <item> filter </item>
+ <item> float </item>
+ <item> getattr </item>
+ <item> globals </item>
+ <item> hasattr </item>
+ <item> hash </item>
+ <item> hex </item>
+ <item> id </item>
+ <item> input </item>
+ <item> int </item>
+ <item> intern </item>
+ <item> isinstance </item>
+ <item> issubclass </item>
+ <item> iter </item>
+ <item> len </item>
+ <item> license </item>
+ <item> list </item>
+ <item> locals </item>
+ <item> long </item>
+ <item> map </item>
+ <item> max </item>
+ <item> min </item>
+ <item> oct </item>
+ <item> open </item>
+ <item> ord </item>
+ <item> pow </item>
+ <item> quit </item>
+ <item> range </item>
+ <item> raw_input </item>
+ <item> reduce </item>
+ <item> reload </item>
+ <item> repr </item>
+ <item> round </item>
+ <item> setattr </item>
+ <item> slice </item>
+ <item> str </item>
+ <item> tuple </item>
+ <item> type </item>
+ <item> unichr </item>
+ <item> unicode </item>
+ <item> vars </item>
+ <item> xrange </item>
+ <item> zip </item>
+ <!-- BEGIN: math module functions -->
+ <item> acos </item>
+ <item> asin </item>
+ <item> atan </item>
+ <item> atan2 </item>
+ <item> ceil </item>
+ <item> cos </item>
+ <item> cosh </item>
+ <item> degrees </item>
+ <item> exp </item>
+ <item> fabs </item>
+ <item> floor </item>
+ <item> fmod </item>
+ <item> frexp </item>
+ <item> hypot </item>
+ <item> ldexp </item>
+ <item> log </item>
+ <item> log10 </item>
+ <item> modf </item>
+ <item> radians </item>
+ <item> sin </item>
+ <item> sinh </item>
+ <item> sqrt </item>
+ <item> tan </item>
+ <item> tanh </item>
+ <!-- END: math module functions -->
+ </list>
+
+ <list name="specialvars">
+ <item> None </item>
+ <item> self </item>
+ </list>
+
+ <list name="kigobjects">
+ <item> AbstractLine </item>
+ <item> Angle </item>
+ <item> Arc </item>
+ <item> BogusObject </item>
+ <item> CartesianConic </item>
+ <item> Circle </item>
+ <item> Conic </item>
+ <item> ConicCartesianData </item>
+ <item> ConicPolarData </item>
+ <item> Coordinate </item>
+ <item> Cubic </item>
+ <item> CubicCartesianData </item>
+ <item> Curve </item>
+ <item> DoubleObject </item>
+ <item> IntObject </item>
+ <item> InvalidObject </item>
+ <item> Line </item>
+ <item> LineData </item>
+ <item> Object </item>
+ <item> ObjectType </item>
+ <item> Point </item>
+ <item> PolarConic </item>
+ <item> Ray </item>
+ <item> Segment </item>
+ <item> StringObject </item>
+ <item> TestResultObject </item>
+ <item> Transformation </item>
+ <item> Vector </item>
+ </list>
+
+ <list name="mathconsts">
+ <item> e </item>
+ <item> pi </item>
+ </list>
+
+ <contexts>
+ <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
+ <keyword attribute="Preprocessor" String="prep" context="#stay"/>
+ <keyword attribute="Keyword" String="statements" context="#stay"/>
+ <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
+ <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
+ <keyword attribute="Kig Object" String="kigobjects" context="#stay" />
+ <keyword attribute="Math Constants" String="mathconsts" context="#stay" />
+ <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
+
+ <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
+ <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
+ <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
+ <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
+ <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
+ <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
+
+ <RegExpr attribute="Raw String" String="[rR]'" context="Raw A-string"/>
+ <RegExpr attribute="Raw String" String="[rR]&quot;" context="Raw Q-string"/>
+
+ <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
+ <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment"/>
+ <RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment"/>
+
+ <StringDetect attribute="String" String="'''" context="Tripple A-string"/>
+ <StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string"/>
+ <DetectChar attribute="String" char="'" context="Single A-string"/>
+ <DetectChar attribute="String" char="&quot;" context="Single Q-string"/>
+
+ <RegExpr attribute="Operator" String="[+*/\(\)%\|\[\]\{\}:=;\!&lt;&gt;!^&amp;~-]" context="#stay"/>
+
+ </context>
+
+ <context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay">
+ <HlCChar attribute="Comment" context="#stay"/>
+ <RegExpr attribute="Comment" String="'''" context="#pop"/>
+ </context>
+
+ <context name="Tripple Q-comment" attribute="Comment" lineEndContext="#stay">
+ <HlCChar attribute="Comment" context="#stay"/>
+ <RegExpr attribute="Comment" String="&quot;&quot;&quot;" context="#pop"/>
+ </context>
+
+ <context name="Tripple A-string" attribute="String" lineEndContext="#stay">
+ <HlCChar attribute="String" context="#stay"/>
+ <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
+ <RegExpr attribute="String" String="'''" context="#pop"/>
+ </context>
+
+ <context name="Tripple Q-string" attribute="String" lineEndContext="#stay">
+ <HlCStringChar attribute="String" context="#stay"/>
+ <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
+ <RegExpr attribute="String" String="&quot;&quot;&quot;" context="#pop"/>
+ </context>
+
+ <context name="Single A-comment" attribute="Comment" lineEndContext="#stay">
+ <HlCStringChar attribute="Comment" context="#stay"/>
+ <DetectChar attribute="Comment" char="'" context="#pop"/>
+ </context>
+
+ <context name="Single Q-comment" attribute="Comment" lineEndContext="#stay">
+ <HlCStringChar attribute="Comment" context="#stay"/>
+ <DetectChar attribute="Comment" char="&quot;" context="#pop"/>
+ </context>
+
+ <context name="Single A-string" attribute="String" lineEndContext="#stay">
+ <HlCStringChar attribute="String" context="#stay"/>
+ <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
+ <DetectChar attribute="String" char="'" context="#pop"/>
+ </context>
+
+ <context name="Single Q-string" attribute="String" lineEndContext="#stay">
+ <HlCStringChar attribute="String" context="#stay"/>
+ <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
+ <DetectChar attribute="String" char="&quot;" context="#pop"/>
+ </context>
+
+ <context name="Raw A-string" attribute="Raw String" lineEndContext="#stay">
+ <HlCStringChar attribute="Raw String" context="#stay"/>
+ <DetectChar attribute="Raw String" char="'" context="#pop"/>
+ </context>
+
+ <context name="Raw Q-string" attribute="Raw String" lineEndContext="#stay">
+ <HlCStringChar attribute="Raw String" context="#stay"/>
+ <DetectChar attribute="Raw String" char="&quot;" context="#pop"/>
+ </context>
+
+
+ </contexts>
+ <itemDatas>
+ <itemData name="Normal Text" defStyleNum="dsNormal"/>
+ <itemData name="Operator" defStyleNum="dsChar"/>
+ <itemData name="Keyword" defStyleNum="dsKeyword"/>
+ <itemData name="Builtin Function" defStyleNum="dsDataType"/>
+ <itemData name="Kig Object" defStyleNum="dsKeyword" color="#000080" selColor="#ffffff" bold="0" italic="0"/>
+ <itemData name="Math Constants" defStyleNum="dsKeyword" color="#008000" selColor="#00FF00" bold="0" italic="0"/>
+ <itemData name="Special Variable" defStyleNum="dsOthers"/>
+ <itemData name="Preprocessor" defStyleNum="dsChar"/>
+ <itemData name="Long" defStyleNum="dsOthers"/>
+ <itemData name="Float" defStyleNum="dsFloat"/>
+ <itemData name="Int" defStyleNum="dsDecVal"/>
+ <itemData name="Hex" defStyleNum="dsOthers"/>
+ <itemData name="Octal" defStyleNum="dsOthers"/>
+ <itemData name="Complex" defStyleNum="dsOthers"/>
+ <itemData name="Comment" defStyleNum="dsComment"/>
+ <itemData name="String" defStyleNum="dsString"/>
+ <itemData name="Raw String" defStyleNum="dsString"/>
+ </itemDatas>
+ </highlighting>
+ <general>
+<!-- <folding indentationsensitive="1" /> -->
+ <comments>
+ <comment name="singleLine" start="#" />
+ </comments>
+ <keywords casesensitive="1" />
+ </general>
+</language>
diff --git a/kig/scripting/python-scripting-api-dox-mainpage.dox b/kig/scripting/python-scripting-api-dox-mainpage.dox
new file mode 100644
index 00000000..9bf6bbcb
--- /dev/null
+++ b/kig/scripting/python-scripting-api-dox-mainpage.dox
@@ -0,0 +1,26 @@
+/** \mainpage Kig Python Scripting API Documentation
+ * \section Introduction
+ * This is the documentation of the Kig Python Scripting API. It is
+ * intended as a reference for people using the Kig Python Scripting
+ * System. The Documentation is generated from the C++ sources for
+ * the classes, and unfortunately, this means that the documentation
+ * uses a C++ syntax. However, if you ignore this fact, and simply
+ * look at the API as a set of classes with member and static
+ * functions, then you should be fine.
+ *
+ * \section The API
+ * This API is mostly meant to be used from user-defined calc()
+ * functions. In these functions, it is necessary to
+ * \li access the information of the argument \ref ObjectImp's
+ * \li construct and return a new ObjectImp
+ *
+ * Both uses require the ObjectImp API to be exported to Python, and
+ * this is the major part of this API. Some more classes are also
+ * exported, but mostly because they are used from one of the
+ * ObjectImp's APIs.
+ *
+ * \section Links
+ *
+ * Next suggested reading is the
+ * \ref ObjectImp "documentation of the ObjectImp class".
+ */
diff --git a/kig/scripting/python_scripter.cc b/kig/scripting/python_scripter.cc
new file mode 100644
index 00000000..7e833d5c
--- /dev/null
+++ b/kig/scripting/python_scripter.cc
@@ -0,0 +1,578 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 "python_scripter.h"
+
+#include <iostream>
+#include <string>
+#include <Python.h>
+#include <boost/python.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include "../misc/common.h"
+#include "../misc/coordinate.h"
+#include "../misc/cubic-common.h"
+#include "../misc/kigtransform.h"
+#include "../objects/bogus_imp.h"
+#include "../objects/common.h"
+#include "../objects/circle_imp.h"
+#include "../objects/cubic_imp.h"
+#include "../objects/line_imp.h"
+#include "../objects/other_imp.h"
+#include "../objects/point_imp.h"
+
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE_INIT( kig )
+{
+ class_<Coordinate>( "Coordinate" )
+ .def( init<double, double>() )
+ .def( init<const Coordinate&>() )
+ .def( "invalidCoord", &Coordinate::invalidCoord )
+ .staticmethod( "invalidCoord" )
+ .def( "valid", &Coordinate::valid )
+ .def( "distance", &Coordinate::distance )
+ .def( "length", &Coordinate::length )
+ .def( "squareLength", &Coordinate::squareLength )
+ .def( "orthogonal", &Coordinate::orthogonal )
+ .def( "round", &Coordinate::round )
+ .def( "normalize", &Coordinate::normalize )
+ .def( -self )
+// .def( self = self )
+ .def( self += self )
+ .def( self -= self )
+ .def( self *= other<double>() )
+ .def( self *= other<int>() )
+ .def( self /= other<double>() )
+ .def( self / other<double>() )
+ .def( self + self )
+ .def( self - self )
+ .def( self * other<double>() )
+ .def( other<double>() * self )
+ .def( self * self )
+ .def_readwrite( "x", &Coordinate::x )
+ .def_readwrite( "y", &Coordinate::y )
+ ;
+
+ class_<LineData>( "LineData" )
+ .def( init<Coordinate, Coordinate>() )
+ .def( "dir", &LineData::dir )
+ .def( "length", &LineData::length )
+ .def( "isParallelTo", &LineData::isParallelTo )
+ .def_readwrite( "a", &LineData::a )
+ .def_readwrite( "b", &LineData::b )
+ ;
+
+ // we need this cause Transformation::apply is overloaded and
+ // otherwise using Transformation::apply would be ambiguous..
+ const Coordinate (Transformation::*transformapplyfunc)( const Coordinate& ) const = &Transformation::apply;
+ class_<Transformation>( "Transformation", no_init )
+ .def( "apply", transformapplyfunc )
+ .def( "isHomothetic", &Transformation::isHomothetic )
+ .def( "inverse", &Transformation::inverse )
+ .def( "identity", &Transformation::identity )
+ .def( "translation", &Transformation::translation )
+ .def( "rotation", &Transformation::rotation )
+ .def( "pointReflection", &Transformation::pointReflection )
+ .def( "lineReflection", &Transformation::lineReflection )
+ .def( "castShadow", &Transformation::castShadow )
+ .def( "projectiveRotation", &Transformation::projectiveRotation )
+ .def( "scalingOverPoint", &Transformation::scalingOverPoint )
+ .def( "scalingOverLine", &Transformation::scalingOverLine )
+ .def( self * self )
+ .def( self == self )
+ .staticmethod( "identity" )
+ .staticmethod( "translation" )
+ .staticmethod( "rotation" )
+ .staticmethod( "pointReflection" )
+ .staticmethod( "lineReflection" )
+ .staticmethod( "castShadow" )
+ .staticmethod( "projectiveRotation" )
+ .staticmethod( "scalingOverPoint" )
+ .staticmethod( "scalingOverLine" )
+ ;
+
+ class_<ObjectImpType, boost::noncopyable>( "ObjectType", no_init )
+ .def( "fromInternalName", &ObjectImpType::typeFromInternalName,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "fromInternalName" )
+ .def( "inherits", &ObjectImpType::inherits )
+ .def( "internalName", &ObjectImpType::internalName )
+ .def( "translatedName", &ObjectImpType::translatedName )
+ .def( "selectStatement", &ObjectImpType::selectStatement )
+ .def( "removeAStatement", &ObjectImpType::removeAStatement )
+ .def( "addAStatement", &ObjectImpType::addAStatement )
+ .def( "moveAStatement", &ObjectImpType::moveAStatement )
+ .def( "attachToThisStatement", &ObjectImpType::attachToThisStatement )
+ ;
+
+ class_<ObjectImp, boost::noncopyable>( "Object", no_init )
+ .def( "stype", &ObjectImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "inherits", &ObjectImp::inherits )
+ .def( "transform", &ObjectImp::transform,
+ return_value_policy<manage_new_object>() )
+ .def( "valid", &ObjectImp::valid )
+ .def( "copy", &ObjectImp::copy,
+ return_value_policy<manage_new_object>() )
+ .def( "equals", &ObjectImp::equals )
+ ;
+
+ class_<CurveImp, bases<ObjectImp>, boost::noncopyable>( "Curve", no_init )
+ .def( "stype", &CurveImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+// .def( "getParam", &CurveImp::getParam )
+// .def( "getPoint", &CurveImp::getPoint );
+ ;
+ class_<PointImp, bases<ObjectImp> >( "Point", init<Coordinate>() )
+ .def( "stype", &PointImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "coordinate", &PointImp::coordinate,
+ return_internal_reference<1>() )
+ .def( "setCoordinate", &PointImp::setCoordinate )
+ ;
+
+ class_<AbstractLineImp, bases<CurveImp>, boost::noncopyable >( "AbstractLine", no_init )
+ .def( "stype", &AbstractLineImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "slope", &AbstractLineImp::slope )
+ .def( "equationString", &AbstractLineImp::equationString )
+ .def( "data", &AbstractLineImp::data )
+ ;
+
+ class_<SegmentImp, bases<AbstractLineImp> >( "Segment", init<Coordinate, Coordinate>() )
+ .def( "stype", &SegmentImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( init<LineData>() )
+ .def( "length", &SegmentImp::length )
+ ;
+
+ class_<RayImp, bases<AbstractLineImp> >( "Ray", init<Coordinate, Coordinate>() )
+ .def( "stype", &RayImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( init<LineData>() )
+ ;
+
+ class_<LineImp, bases<AbstractLineImp> >( "Line", init<Coordinate, Coordinate>() )
+ .def( "stype", &LineImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( init<LineData>() )
+ ;
+
+ class_<ConicCartesianData>( "ConicCartesianData", init<double,double,double,double,double,double>() )
+ .def( init<ConicPolarData>() )
+ .def( "invalidData", &ConicCartesianData::invalidData )
+ .staticmethod( "invalidData" )
+ .def( "valid", &ConicCartesianData::valid )
+// .def( init<double[6]>() )
+// .def_readwrite( "coeffs", &ConicCartesianData::coeffs )
+ ;
+
+ class_<ConicPolarData>( "ConicPolarData", init<Coordinate, double, double, double>() )
+ .def( init<ConicCartesianData>() )
+ .def_readwrite( "focus1", &ConicPolarData::focus1 )
+ .def_readwrite( "pdimen", &ConicPolarData::pdimen )
+ .def_readwrite( "ecostheta0", &ConicPolarData::ecostheta0 )
+ .def_readwrite( "esintheta0", &ConicPolarData::esintheta0 )
+ ;
+
+ class_<ConicImp, bases<CurveImp>, boost::noncopyable >( "Conic", no_init )
+ .def( "stype", &ConicImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "conicType", &ConicImp::conicType )
+// .def( "conicTypeString", &ConicImp::conicTypeString )
+// .def( "cartesianEquationString", &ConicImp::cartesianEquationString )
+// .def( "polarEquationString", &ConicImp::polarEquationString )
+ .def( "cartesianData", &ConicImp::cartesianData )
+ .def( "polarData", &ConicImp::polarData )
+ .def( "focus1", &ConicImp::focus1 )
+ .def( "focus2", &ConicImp::focus2 )
+ ;
+
+ class_<ConicImpCart, bases<ConicImp> >( "CartesianConic", init<ConicCartesianData>() )
+ ;
+ class_<ConicImpPolar, bases<ConicImp> >( "PolarConic", init<ConicPolarData>() )
+ ;
+
+ class_<CircleImp, bases<ConicImp> >( "Circle", init<Coordinate, double>() )
+ .def( "stype", &CircleImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "center", &CircleImp::center )
+ .def( "radius", &CircleImp::radius )
+ .def( "squareRadius", &CircleImp::squareRadius )
+ .def( "surface", &CircleImp::surface )
+ .def( "circumference", &CircleImp::circumference )
+ ;
+
+ class_<VectorImp, bases<CurveImp> >( "Vector", init<Coordinate, Coordinate>() )
+ .def( "stype", &VectorImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "length", &VectorImp::length )
+ .def( "dir", &VectorImp::dir )
+ .def( "data", &VectorImp::data )
+ ;
+
+ class_<AngleImp, bases<ObjectImp> >( "Angle", init<Coordinate, double, double>() )
+ .def( "stype", &AngleImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "size", &AngleImp::size )
+ .def( "point", &AngleImp::point )
+ .def( "startAngle", &AngleImp::startAngle )
+ .def( "angle", &AngleImp::angle )
+ ;
+
+ class_<ArcImp, bases<ObjectImp> >( "Arc", init<Coordinate, double, double, double>() )
+ .def( "stype", &ArcImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "startAngle", &ArcImp::startAngle )
+ .def( "angle", &ArcImp::angle )
+ .def( "radius", &ArcImp::radius )
+ .def( "center", &ArcImp::center )
+ .def( "firstEndPoint", &ArcImp::firstEndPoint )
+ .def( "secondEndPoint", &ArcImp::secondEndPoint )
+ .def( "sectorSurface", &ArcImp::sectorSurface )
+ ;
+
+ class_<BogusImp, bases<ObjectImp>, boost::noncopyable >( "BogusObject", no_init )
+ .def( "stype", &BogusImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ ;
+
+ class_<InvalidImp, bases<BogusImp> >( "InvalidObject", init<>() )
+ .def( "stype", &InvalidImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ ;
+
+ class_<DoubleImp, bases<BogusImp> >( "DoubleObject", init<double>() )
+ .def( "stype", &DoubleImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "data", &DoubleImp::data )
+ .def( "setData", &DoubleImp::setData )
+ ;
+
+ class_<IntImp, bases<BogusImp> >( "IntObject", init<int>() )
+ .def( "stype", &IntImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "data", &IntImp::data )
+ .def( "setData", &IntImp::setData )
+ ;
+
+ class_<StringImp, bases<BogusImp> >( "StringObject", no_init )
+ .def( "stype", &StringImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+// .def( "data", &StringImp::data )
+// .def( "setData", &StringImp::setData )
+ ;
+
+ class_<TestResultImp, bases<BogusImp> >( "TestResultObject", no_init )
+ .def( "stype", &TestResultImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+// .def( "data", &TestResultImp::data )
+ ;
+
+// class_<TextImp, bases<ObjectImp> >( "Text", init<string, Coordinate, bool>() )
+// .def( "stype", &TextImp::stype,
+// return_value_policy<reference_existing_object>() )
+// .staticmethod( "stype" )
+// .def( "text", &TextImp::text )
+// .def( "coordinate", &TextImp::coordinate )
+// .def( "hasFrame", &TextImp::hasFrame )
+// ;
+
+ class_<CubicCartesianData>( "CubicCartesianData", init<double,double,double,double,double,double,double,double,double,double>() )
+ .def( "invalidData", &CubicCartesianData::invalidData )
+ .staticmethod( "invalidData" )
+ .def( "valid", &CubicCartesianData::valid )
+// .def( init<double[10]>() )
+// .def_readwrite( "coeffs", &CubicCartesianData::coeffs )
+ ;
+
+ class_<CubicImp, bases<CurveImp> >( "Cubic", init<CubicCartesianData>() )
+ .def( "stype", &CubicImp::stype,
+ return_value_policy<reference_existing_object>() )
+ .staticmethod( "stype" )
+ .def( "data", &CubicImp::data )
+ ;
+
+}
+
+PythonScripter* PythonScripter::instance()
+{
+ static PythonScripter t;
+ return &t;
+}
+
+class PythonScripter::Private
+{
+public:
+ dict mainnamespace;
+};
+
+// allocates a new string using new [], and copies contents into it..
+static char* newstring( const char* contents )
+{
+ char* ret = new char[strlen( contents ) + 1];
+ strcpy( ret, contents );
+ return ret;
+}
+
+PythonScripter::PythonScripter()
+{
+ d = new Private;
+
+ // tell the python interpreter about our API..
+
+ // the newstring stuff is to prevent warnings about conversion from
+ // const char* to char*..
+ char* s = newstring( "kig" );
+ PyImport_AppendInittab( s, initkig );
+ // we can't delete this yet, since python keeps a pointer to it..
+ // This means we have a small but harmless memory leak here, but it
+ // doesn't hurt at all, since it could only be freed at the end of
+ // the program, at which time it is freed by the system anyway if we
+ // don't do it..
+ //delete [] s;
+
+ Py_Initialize();
+
+ s = newstring( "import math; from math import *;" );
+ PyRun_SimpleString( s );
+ delete [] s;
+ s = newstring( "import kig; from kig import *;" );
+ PyRun_SimpleString( s );
+ delete [] s;
+ s = newstring( "import traceback;" );
+ PyRun_SimpleString( s );
+ delete [] s;
+
+ // find the main namespace..
+
+ s = newstring( "__main__" );
+ handle<> main_module( borrowed( PyImport_AddModule( s ) ) );
+ delete [] s;
+
+ handle<> mnh(borrowed( PyModule_GetDict(main_module.get()) ));
+ d->mainnamespace = extract<dict>( mnh.get() );
+}
+
+PythonScripter::~PythonScripter()
+{
+ PyErr_Clear();
+ Py_Finalize();
+ delete d;
+}
+
+class CompiledPythonScript::Private
+{
+public:
+ int ref;
+ object calcfunc;
+ // TODO
+// object movefunc;
+};
+
+ObjectImp* CompiledPythonScript::calc( const Args& args, const KigDocument& )
+{
+ return PythonScripter::instance()->calc( *this, args );
+}
+
+CompiledPythonScript::~CompiledPythonScript()
+{
+ --d->ref;
+ if ( d->ref == 0 )
+ delete d;
+}
+
+CompiledPythonScript::CompiledPythonScript( Private* ind )
+ : d( ind )
+{
+ ++d->ref;
+}
+
+CompiledPythonScript PythonScripter::compile( const char* code )
+{
+ clearErrors();
+ dict retdict;
+ bool error = false;
+ try
+ {
+ (void) PyRun_String( const_cast<char*>( code ), Py_file_input,
+ d->mainnamespace.ptr(), retdict.ptr() );
+ }
+ catch( ... )
+ {
+ error = true;
+ };
+ error |= static_cast<bool>( PyErr_Occurred() );
+ if ( error )
+ {
+ saveErrors();
+ retdict.clear();
+ }
+
+ // debugging stuff, removed.
+// std::string dictstring = extract<std::string>( str( retdict ) );
+
+ CompiledPythonScript::Private* ret = new CompiledPythonScript::Private;
+ ret->ref = 0;
+ ret->calcfunc = retdict.get( "calc" );
+ return CompiledPythonScript( ret );
+}
+
+CompiledPythonScript::CompiledPythonScript( const CompiledPythonScript& s )
+ : d( s.d )
+{
+ ++d->ref;
+}
+
+std::string PythonScripter::lastErrorExceptionType() const
+{
+ return lastexceptiontype;
+}
+
+std::string PythonScripter::lastErrorExceptionValue() const
+{
+ return lastexceptionvalue;
+}
+
+std::string PythonScripter::lastErrorExceptionTraceback() const
+{
+ return lastexceptiontraceback;
+}
+
+ObjectImp* PythonScripter::calc( CompiledPythonScript& script, const Args& args )
+{
+ clearErrors();
+ object calcfunc = script.d->calcfunc;
+ try
+ {
+ std::vector<object> objectvect;
+ objectvect.reserve( args.size() );
+
+ for ( int i = 0; i < (int) args.size(); ++i )
+ {
+ object o( boost::ref( *args[i] ) );
+ objectvect.push_back( o );
+ }
+
+ handle<> argstuph( PyTuple_New( args.size() ) );
+ for ( int i = 0; i < (int) objectvect.size(); ++i )
+ {
+ PyTuple_SetItem( argstuph.get(), i, (objectvect.begin() +i)->ptr() );
+ };
+ tuple argstup( argstuph );
+
+ handle<> reth( PyEval_CallObject( calcfunc.ptr(), argstup.ptr() ) );
+// object resulto = calcfunc( argstup );
+// handle<> reth( PyEval_CallObject( calcfunc.ptr(), args ) );
+ object resulto( reth );
+
+ extract<ObjectImp&> result( resulto );
+ if( ! result.check() ) return new InvalidImp;
+ else
+ {
+ ObjectImp& ret = result();
+ return ret.copy();
+ };
+ }
+ catch( ... )
+ {
+ saveErrors();
+
+ return new InvalidImp;
+ };
+}
+
+void PythonScripter::saveErrors()
+{
+ erroroccurred = true;
+ PyObject* poexctype;
+ PyObject* poexcvalue;
+ PyObject* poexctraceback;
+ PyErr_Fetch( &poexctype, &poexcvalue, &poexctraceback );
+ handle<> exctypeh( poexctype );
+ handle<> excvalueh( poexcvalue );
+
+ object exctype( exctypeh );
+ object excvalue( excvalueh );
+ object exctraceback;
+ if ( poexctraceback )
+ {
+ handle<> exctracebackh( poexctraceback );
+ exctraceback = object( exctracebackh );
+ }
+
+ lastexceptiontype = extract<std::string>( str( exctype ) )();
+ lastexceptionvalue = extract<std::string>( str( excvalue ) )();
+
+ object printexcfunc = d->mainnamespace[ "traceback" ].attr( "format_exception" );
+
+ list tracebacklist = extract<list>( printexcfunc( exctype, excvalue, exctraceback ) )();
+ str tracebackstr( "" );
+ while ( true )
+ {
+ try {
+ str s = extract<str>( tracebacklist.pop() );
+ tracebackstr += s;
+ }
+ catch( ... )
+ {
+ break;
+ }
+ }
+
+ lastexceptiontraceback = extract<std::string>( tracebackstr )();
+ PyErr_Clear();
+}
+
+void PythonScripter::clearErrors()
+{
+ PyErr_Clear();
+ lastexceptiontype.clear();
+ lastexceptionvalue.clear();
+ lastexceptiontraceback.clear();
+ erroroccurred = false;
+}
+
+bool CompiledPythonScript::valid()
+{
+ return !!d->calcfunc;
+}
+
+bool PythonScripter::errorOccurred() const
+{
+ return erroroccurred;
+}
+
diff --git a/kig/scripting/python_scripter.h b/kig/scripting/python_scripter.h
new file mode 100644
index 00000000..464b5d3e
--- /dev/null
+++ b/kig/scripting/python_scripter.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 KIG_SCRIPTING_PYTHON_SCRIPTER_H
+#define KIG_SCRIPTING_PYTHON_SCRIPTER_H
+
+#include "../objects/common.h"
+
+#include <string>
+
+class KigDocument;
+class ObjectImp;
+
+class CompiledPythonScript
+{
+ friend class PythonScripter;
+ class Private;
+ Private* const d;
+ CompiledPythonScript( Private* );
+public:
+ CompiledPythonScript( const CompiledPythonScript& s );
+ ~CompiledPythonScript();
+ ObjectImp* calc( const Args& a, const KigDocument& doc );
+
+ bool valid();
+};
+
+class PythonScripter
+{
+ friend class CompiledPythonScript;
+ class Private;
+ Private* d;
+ PythonScripter();
+ ~PythonScripter();
+
+ void clearErrors();
+ void saveErrors();
+
+ bool erroroccurred;
+ std::string lastexceptiontype;
+ std::string lastexceptionvalue;
+ std::string lastexceptiontraceback;
+public:
+ static PythonScripter* instance();
+
+ bool errorOccurred() const;
+ std::string lastErrorExceptionType() const;
+ std::string lastErrorExceptionValue() const;
+ std::string lastErrorExceptionTraceback() const;
+
+ CompiledPythonScript compile( const char* code );
+ ObjectImp* calc( CompiledPythonScript& script, const Args& args );
+};
+
+#endif
diff --git a/kig/scripting/python_type.cc b/kig/scripting/python_type.cc
new file mode 100644
index 00000000..0180e828
--- /dev/null
+++ b/kig/scripting/python_type.cc
@@ -0,0 +1,195 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 "python_type.h"
+
+#include "python_scripter.h"
+
+#include "../objects/object_imp.h"
+#include "../objects/bogus_imp.h"
+
+class PythonCompiledScriptImp
+ : public BogusImp
+{
+ mutable CompiledPythonScript mscript;
+public:
+ typedef BogusImp Parent;
+ static const ObjectImpType* stype();
+ const ObjectImpType* type() const;
+
+ PythonCompiledScriptImp( const CompiledPythonScript& s );
+
+ void visit( ObjectImpVisitor* vtor ) const;
+ ObjectImp* copy() const;
+ bool equals( const ObjectImp& rhs ) const;
+
+ bool isCache() const;
+
+ CompiledPythonScript& data() const { return mscript; };
+};
+
+PythonCompiledScriptImp::PythonCompiledScriptImp( const CompiledPythonScript& s )
+ : BogusImp(), mscript( s )
+{
+
+}
+
+const ObjectImpType* PythonCompiledScriptImp::stype()
+{
+ static const ObjectImpType t( BogusImp::stype(), "python-compiled-script-imp",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+ return &t;
+}
+
+const ObjectImpType* PythonCompiledScriptImp::type() const
+{
+ return PythonCompiledScriptImp::stype();
+}
+
+void PythonCompiledScriptImp::visit( ObjectImpVisitor* ) const
+{
+ // TODO ?
+}
+
+ObjectImp* PythonCompiledScriptImp::copy() const
+{
+ return new PythonCompiledScriptImp( mscript );
+}
+
+bool PythonCompiledScriptImp::equals( const ObjectImp& ) const
+{
+ // problem ?
+ return true;
+}
+
+bool PythonCompiledScriptImp::isCache() const
+{
+ return true;
+}
+
+KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonCompileType )
+
+PythonCompileType::PythonCompileType()
+ : ObjectType( "PythonCompileType" )
+{
+}
+
+PythonCompileType::~PythonCompileType()
+{
+}
+
+const PythonCompileType* PythonCompileType::instance()
+{
+ static const PythonCompileType t;
+ return &t;
+}
+
+const ObjectImpType* PythonCompileType::impRequirement( const ObjectImp*, const Args& ) const
+{
+ return StringImp::stype();
+}
+
+const ObjectImpType* PythonCompileType::resultId() const
+{
+ return PythonCompiledScriptImp::stype();
+}
+
+ObjectImp* PythonCompileType::calc( const Args& parents, const KigDocument& ) const
+{
+ assert( parents.size() == 1 );
+ if ( !parents[0]->inherits( StringImp::stype() ) ) return new InvalidImp;
+
+ const StringImp* si = static_cast<const StringImp*>( parents[0] );
+ QString s = si->data();
+
+ CompiledPythonScript cs = PythonScripter::instance()->compile( s.latin1() );
+
+ if ( cs.valid() )
+ return new PythonCompiledScriptImp( cs );
+ else
+ return new InvalidImp();
+}
+
+KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PythonExecuteType )
+
+PythonExecuteType::PythonExecuteType()
+ : ObjectType( "PythonExecuteType" )
+{
+}
+
+PythonExecuteType::~PythonExecuteType()
+{
+}
+
+const PythonExecuteType* PythonExecuteType::instance()
+{
+ static const PythonExecuteType t;
+ return &t;
+}
+
+ObjectImp* PythonExecuteType::calc( const Args& parents, const KigDocument& d ) const
+{
+ assert( parents.size() >= 1 );
+ if( !parents[0]->inherits( PythonCompiledScriptImp::stype() ) ) return new InvalidImp;
+
+ CompiledPythonScript& script = static_cast<const PythonCompiledScriptImp*>( parents[0] )->data();
+
+ Args args( parents.begin() + 1, parents.end() );
+ return script.calc( args, d );
+}
+
+const ObjectImpType* PythonExecuteType::impRequirement( const ObjectImp* o, const Args& parents ) const
+{
+ if ( o == parents[0] ) return PythonCompiledScriptImp::stype();
+ else return ObjectImp::stype();
+}
+
+const ObjectImpType* PythonExecuteType::resultId() const
+{
+ return ObjectImp::stype();
+}
+
+std::vector<ObjectCalcer*> PythonCompileType::sortArgs( const std::vector<ObjectCalcer*>& args ) const
+{
+ return args;
+}
+
+Args PythonCompileType::sortArgs( const Args& args ) const
+{
+ return args;
+}
+
+std::vector<ObjectCalcer*> PythonExecuteType::sortArgs( const std::vector<ObjectCalcer*>& args ) const
+{
+ return args;
+}
+
+Args PythonExecuteType::sortArgs( const Args& args ) const
+{
+ return args;
+}
+
+bool PythonCompileType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const
+{
+ return false;
+}
+
+bool PythonExecuteType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const
+{
+ return false;
+}
+
diff --git a/kig/scripting/python_type.h b/kig/scripting/python_type.h
new file mode 100644
index 00000000..1e76b0b8
--- /dev/null
+++ b/kig/scripting/python_type.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 KIG_SCRIPTING_PYTHON_TYPE_H
+#define KIG_SCRIPTING_PYTHON_TYPE_H
+
+#include "../objects/object_type.h"
+
+class PythonCompileType
+ : public ObjectType
+{
+ PythonCompileType();
+ ~PythonCompileType();
+public:
+ static const PythonCompileType* instance();
+
+ ObjectImp* calc( const Args& parents, const KigDocument& d ) const;
+
+ const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const;
+ bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const;
+ const ObjectImpType* resultId() const;
+
+ std::vector<ObjectCalcer*> sortArgs( const std::vector<ObjectCalcer*>& args ) const;
+ Args sortArgs( const Args& args ) const;
+};
+
+class PythonExecuteType
+ : public ObjectType
+{
+ PythonExecuteType();
+ ~PythonExecuteType();
+public:
+ static const PythonExecuteType* instance();
+
+ ObjectImp* calc( const Args& parents, const KigDocument& d ) const;
+
+ const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const;
+ bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const;
+ const ObjectImpType* resultId() const;
+
+ std::vector<ObjectCalcer*> sortArgs( const std::vector<ObjectCalcer*>& args ) const;
+ Args sortArgs( const Args& args ) const;
+
+// virtual QStringList specialActions() const;
+// virtual void executeAction( int i, RealObject* o, KigDocument& d, KigWidget& w,
+// NormalMode& m ) const;
+};
+
+#endif
diff --git a/kig/scripting/script-common.cc b/kig/scripting/script-common.cc
new file mode 100644
index 00000000..4bd2cbd8
--- /dev/null
+++ b/kig/scripting/script-common.cc
@@ -0,0 +1,95 @@
+// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.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 "script-common.h"
+
+#include <qstring.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+struct script_prop
+{
+ const char* fillCodeStatement;
+ const char* icon;
+ const char* highlightStyle;
+};
+
+static const script_prop scripts_properties[] =
+{
+ { I18N_NOOP( "Now fill in the code:" ), "shellscript", "" },
+ { I18N_NOOP( "Now fill in the Python code:" ), "source_py", "Python-Kig" }
+};
+
+QString ScriptType::fillCodeStatement( ScriptType::Type type )
+{
+ return i18n( scripts_properties[type].fillCodeStatement );
+}
+
+QString ScriptType::templateCode( ScriptType::Type type, std::list<ObjectHolder*> args )
+{
+ if ( type == Python )
+ {
+ QString tempcode = QString::fromLatin1( "def calc( " );
+ bool firstarg = true;
+ QString temparg = i18n( "Note to translators: this should be a default "
+ "name for an argument in a Python function. The "
+ "default is \"arg%1\" which would become arg1, "
+ "arg2, etc. Give something which seems "
+ "appropriate for your language.", "arg%1" );
+
+ uint id = 1;
+ for ( std::list<ObjectHolder*>::const_iterator i = args.begin(); i != args.end(); ++i )
+ {
+ if ( !firstarg ) tempcode += ", ";
+ else firstarg = false;
+ QString n = ( *i )->name();
+ tempcode += n.isEmpty() ? temparg.arg( id ) : n;
+ id++;
+ };
+ tempcode +=
+ " ):\n"
+ "\t# Calculate whatever you want to show here, and return it.\n"
+ "\t# For example, to implement a mid point, you would put\n"
+ "\t# this code here:\n"
+ "\t#\treturn Point( ( arg1.coordinate() + arg2.coordinate() ) / 2 )\n"
+ "\t# Please refer to the manual for more information.\n"
+ "\n";
+ return tempcode;
+ }
+
+ kdDebug() << "No such script type: " << type << endl;
+ return "";
+}
+
+const char* ScriptType::icon( ScriptType::Type type )
+{
+ return scripts_properties[type].icon;
+}
+
+QString ScriptType::highlightStyle( ScriptType::Type type )
+{
+ return QString( scripts_properties[type].highlightStyle );
+}
+
+ScriptType::Type ScriptType::intToType( int type )
+{
+ if ( type == 1 )
+ return Python;
+
+ return Unknown;
+}
diff --git a/kig/scripting/script-common.h b/kig/scripting/script-common.h
new file mode 100644
index 00000000..1c384453
--- /dev/null
+++ b/kig/scripting/script-common.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.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 KIG_SCRIPTING_SCRIPT_COMMON_H
+#define KIG_SCRIPTING_SCRIPT_COMMON_H
+
+#include <algorithm>
+#include <list>
+
+#include "../objects/object_holder.h"
+
+class QString;
+
+class ScriptType
+{
+public:
+ /**
+ * This enum represents all the script language types actually in
+ * Kig. The first type ( Unknown ) can be used if we don't want
+ * particular tunings for a script language.
+ */
+ enum Type { Unknown = 0, Python = 1 };
+ /**
+ * Returns an i18n'ed statement like 'Now fill in the code:' with
+ * the name of the script language.
+ */
+ static QString fillCodeStatement( ScriptType::Type type );
+ /**
+ * Returns a template code for a script language.
+ */
+ static QString templateCode( ScriptType::Type type, std::list<ObjectHolder*> args );
+ /**
+ * Returns the icon's name for a script language.
+ */
+ static const char* icon( ScriptType::Type type );
+ /**
+ * Returns the Kate highlight stytle name for a script language.
+ */
+ static QString highlightStyle( ScriptType::Type type );
+ /**
+ * Converts an int to a ScriptType::Type. Useful when reading script
+ * types from files.
+ */
+ static ScriptType::Type intToType( int type );
+};
+
+#endif
diff --git a/kig/scripting/script_mode.cc b/kig/scripting/script_mode.cc
new file mode 100644
index 00000000..000b99f8
--- /dev/null
+++ b/kig/scripting/script_mode.cc
@@ -0,0 +1,362 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 "script_mode.h"
+
+#include "newscriptwizard.h"
+#include "python_type.h"
+#include "python_scripter.h"
+
+#include "../kig/kig_commands.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../misc/calcpaths.h"
+#include "../misc/kigpainter.h"
+#include "../modes/dragrectmode.h"
+#include "../objects/bogus_imp.h"
+#include "../objects/object_imp.h"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+void ScriptModeBase::dragRect( const QPoint& p, KigWidget& w )
+{
+ if ( mwawd != SelectingArgs ) return;
+
+ DragRectMode dm( p, mdoc, w );
+ mdoc.runMode( &dm );
+ std::vector<ObjectHolder*> ret = dm.ret();
+
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+ if ( dm.needClear() )
+ {
+ std::vector<ObjectHolder*> tmp( margs.begin(), margs.begin() );
+ pter.drawObjects( tmp, false );
+ margs.clear();
+ }
+
+ std::copy( ret.begin(), ret.end(), std::inserter( margs, margs.begin() ) );
+ pter.drawObjects( ret, true );
+
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+}
+
+void ScriptModeBase::leftClickedObject( ObjectHolder* o, const QPoint&,
+ KigWidget& w, bool )
+{
+ std::list<ObjectHolder*>::iterator dup_o;
+
+ if ( mwawd != SelectingArgs ) return;
+
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+
+ if ( (dup_o = std::find( margs.begin(), margs.end(), o )) != margs.end() )
+ {
+ margs.erase( dup_o );
+ pter.drawObject( o, false );
+ }
+ else
+ {
+ margs.push_back( o );
+ pter.drawObject( o, true );
+ };
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+}
+
+void ScriptModeBase::mouseMoved( const std::vector<ObjectHolder*>& os,
+ const QPoint& pt, KigWidget& w, bool )
+{
+ if ( mwawd != SelectingArgs ) return;
+
+ w.updateCurPix();
+ if ( os.empty() )
+ {
+ w.setCursor( KCursor::arrowCursor() );
+ mdoc.emitStatusBarText( 0 );
+ w.updateWidget();
+ }
+ else
+ {
+ // the cursor is over an object, show object type next to cursor
+ // and set statusbar text
+
+ w.setCursor( KCursor::handCursor() );
+ QString selectstat = os.front()->selectStatement();
+
+ // statusbar text
+ mdoc.emitStatusBarText( selectstat );
+ KigPainter p( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ // set the text next to the arrow cursor
+ QPoint point = pt;
+ point.setX(point.x()+15);
+
+ p.drawTextStd( point, selectstat );
+ w.updateWidget( p.overlay() );
+ }
+}
+
+ScriptModeBase::ScriptModeBase( KigPart& doc )
+ : BaseMode( doc ), mwizard( 0 ), mpart( doc ),
+ mwawd( SelectingArgs )
+{
+ mwizard = new NewScriptWizard( doc.widget(), this );
+
+ doc.redrawScreen();
+}
+
+ScriptModeBase::~ScriptModeBase()
+{
+}
+
+void ScriptModeBase::killMode()
+{
+ mdoc.doneMode( this );
+}
+
+bool ScriptCreationMode::queryCancel()
+{
+ killMode();
+ return true;
+}
+
+void ScriptModeBase::argsPageEntered()
+{
+ mwawd = SelectingArgs;
+ mdoc.redrawScreen();
+}
+
+void ScriptModeBase::enableActions()
+{
+ KigMode::enableActions();
+ // we don't enable any actions..
+}
+
+void ScriptModeBase::codePageEntered()
+{
+ if ( mwizard->text().isEmpty() )
+ {
+ // insert template code..
+ QString tempcode = ScriptType::templateCode( mtype, margs );
+ mwizard->setText( tempcode );
+ };
+ mwizard->setFinishEnabled( mwizard->mpcode, true );
+ mwawd = EnteringCode;
+ mdoc.redrawScreen();
+}
+
+void ScriptModeBase::redrawScreen( KigWidget* w )
+{
+ std::vector<ObjectHolder*> sel;
+ if ( mwawd == SelectingArgs )
+ sel = std::vector<ObjectHolder*>( margs.begin(), margs.end() );
+ w->redrawScreen( sel );
+ w->updateScrollBars();
+}
+
+bool ScriptCreationMode::queryFinish()
+{
+ std::vector<ObjectCalcer*> args;
+
+ QString script = mwizard->text();
+ args.push_back( new ObjectConstCalcer( new StringImp( script ) ) );
+
+ ObjectTypeCalcer* compiledscript =
+ new ObjectTypeCalcer( PythonCompileType::instance(), args );
+ compiledscript->calc( mdoc.document() );
+
+ args.clear();
+ args.push_back( compiledscript );
+ for ( std::list<ObjectHolder*>::iterator i = margs.begin();
+ i != margs.end(); ++i )
+ args.push_back( ( *i )->calcer() );
+
+ ObjectTypeCalcer::shared_ptr reto =
+ new ObjectTypeCalcer( PythonExecuteType::instance(), args );
+ reto->calc( mdoc.document() );
+
+ if ( reto->imp()->inherits( InvalidImp::stype() ) )
+ {
+ PythonScripter* inst = PythonScripter::instance();
+ QCString errtrace = inst->lastErrorExceptionTraceback().c_str();
+ if ( inst->errorOccurred() )
+ {
+ KMessageBox::detailedSorry(
+ mwizard, i18n( "The Python interpreter caught an error during the execution of your "
+ "script. Please fix the script and click the Finish button again." ),
+ i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace ) );
+ }
+ else
+ {
+ KMessageBox::sorry(
+ mwizard, i18n( "There seems to be an error in your script. The Python interpreter "
+ "reported no errors, but the script does not generate "
+ "a valid object. Please fix the script, and click the Finish button "
+ "again." ) );
+ }
+ return false;
+ }
+ else
+ {
+ mdoc.addObject( new ObjectHolder( reto.get() ) );
+ killMode();
+ return true;
+ }
+}
+
+void ScriptModeBase::midClicked( const QPoint&, KigWidget& )
+{
+}
+
+void ScriptModeBase::rightClicked( const std::vector<ObjectHolder*>&,
+ const QPoint&, KigWidget& )
+{
+}
+
+void ScriptModeBase::setScriptType( ScriptType::Type type )
+{
+ mtype = type;
+ mwizard->setType( mtype );
+ if ( mtype != ScriptType::Unknown )
+ {
+ KIconLoader* il = mpart.instance()->iconLoader();
+ mwizard->setIcon( il->loadIcon( ScriptType::icon( mtype ), KIcon::Small ) );
+ }
+}
+
+void ScriptModeBase::addArgs( const std::vector<ObjectHolder*>& obj, KigWidget& w )
+{
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+
+ std::copy( obj.begin(), obj.end(), std::inserter( margs, margs.begin() ) );
+ pter.drawObjects( obj, true );
+
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+}
+
+void ScriptModeBase::goToCodePage()
+{
+ mwizard->next();
+}
+
+ScriptCreationMode::ScriptCreationMode( KigPart& doc )
+ : ScriptModeBase( doc )
+{
+ mwizard->show();
+}
+
+ScriptCreationMode::~ScriptCreationMode()
+{
+}
+
+ScriptEditMode::ScriptEditMode( ObjectTypeCalcer* exec_calc, KigPart& doc )
+ : ScriptModeBase( doc ), mexecuted( exec_calc )
+{
+ mwawd = EnteringCode;
+
+ mexecargs = mexecuted->parents();
+ assert( mexecargs.size() >= 1 );
+
+ mcompiledargs = mexecargs[0]->parents();
+ assert( mcompiledargs.size() == 1 );
+
+ const ObjectImp* imp = static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->imp();
+ assert( dynamic_cast<const StringImp*>( imp ) );
+ // save the original script text, in case the user modifies the text
+ // in the editor and aborts the editing
+ morigscript = static_cast<const StringImp*>( imp )->data();
+
+ mwizard->setCaption( i18n( "'Edit' is a verb", "Edit Script" ) );
+ mwizard->setText( morigscript );
+ mwizard->show();
+ mwizard->next();
+ mwizard->backButton()->setEnabled( false );
+ mwizard->finishButton()->setEnabled( true );
+}
+
+ScriptEditMode::~ScriptEditMode()
+{
+}
+
+bool ScriptEditMode::queryFinish()
+{
+ MonitorDataObjects mon( mcompiledargs );
+
+ static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->switchImp( new StringImp( mwizard->text() ) );
+ mexecargs[0]->calc( mpart.document() );
+
+ mexecuted->calc( mpart.document() );
+
+ mpart.redrawScreen();
+
+ KigCommand* comm = new KigCommand( mpart, i18n( "Edit Python Script" ) );
+ mon.finish( comm );
+
+ if ( mexecuted->imp()->inherits( InvalidImp::stype() ) )
+ {
+ PythonScripter* inst = PythonScripter::instance();
+ QCString errtrace = inst->lastErrorExceptionTraceback().c_str();
+ if ( inst->errorOccurred() )
+ {
+ KMessageBox::detailedSorry(
+ mpart.widget(), i18n( "The Python interpreter caught an error during the execution of your "
+ "script. Please fix the script." ),
+ i18n( "The Python Interpreter generated the following error output:\n%1").arg( errtrace ) );
+ }
+ else
+ {
+ KMessageBox::sorry(
+ mpart.widget(), i18n( "There seems to be an error in your script. The Python interpreter "
+ "reported no errors, but the script does not generate "
+ "a valid object. Please fix the script." ) );
+ }
+ delete comm;
+ return false;
+ }
+
+ mpart.history()->addCommand( comm );
+ mpart.setModified( true );
+
+ killMode();
+ return true;
+}
+
+bool ScriptEditMode::queryCancel()
+{
+ // reverting the original script text
+ static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->switchImp( new StringImp( morigscript ) );
+ mexecargs[0]->calc( mpart.document() );
+
+ mexecuted->calc( mpart.document() );
+ // paranoic check
+ assert( !mexecuted->imp()->inherits( InvalidImp::stype() ) );
+
+ mpart.redrawScreen();
+
+ // no need to further checks here, as the original script text is ok
+
+ killMode();
+ return true;
+}
+
diff --git a/kig/scripting/script_mode.h b/kig/scripting/script_mode.h
new file mode 100644
index 00000000..4cbfd737
--- /dev/null
+++ b/kig/scripting/script_mode.h
@@ -0,0 +1,119 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 KIG_SCRIPTING_SCRIPT_MODE_H
+#define KIG_SCRIPTING_SCRIPT_MODE_H
+
+#include "script-common.h"
+
+#include "../modes/base_mode.h"
+
+#include <list>
+
+class NewScriptWizard;
+
+/**
+ * Base mode to interact with a script.
+ */
+class ScriptModeBase
+ : public BaseMode
+{
+protected:
+ ScriptModeBase( KigPart& doc );
+
+// mp: argument list is implemented as a std::list instead of std::set
+// because otherwise the user loses the correct argument ordering (in
+// case of more than one argument
+ std::list<ObjectHolder*> margs;
+ NewScriptWizard* mwizard;
+
+ KigPart& mpart;
+
+ enum WAWD { SelectingArgs, EnteringCode };
+ WAWD mwawd;
+
+private:
+ ScriptType::Type mtype;
+
+public:
+ virtual ~ScriptModeBase();
+
+ void dragRect( const QPoint& p, KigWidget& w );
+// void dragObject( const Objects& os, const QPoint& pointClickedOn, KigWidget& w, bool ctrlOrShiftDown );
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool actrlOrShiftDown );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p,
+ KigWidget& w, bool shiftpressed );
+ void midClicked( const QPoint&, KigWidget& );
+ void rightClicked( const std::vector<ObjectHolder*>&, const QPoint&, KigWidget& );
+
+ void argsPageEntered();
+ void codePageEntered();
+
+ virtual bool queryFinish() = 0;
+ virtual bool queryCancel() = 0;
+
+ void redrawScreen( KigWidget* w );
+
+ void killMode();
+
+ void enableActions();
+
+ void setScriptType( ScriptType::Type type );
+
+ void addArgs( const std::vector<ObjectHolder*>& obj, KigWidget& w );
+
+ void goToCodePage();
+
+};
+
+/**
+ * Script mode to create a script.
+ */
+class ScriptCreationMode
+ : public ScriptModeBase
+{
+public:
+ ScriptCreationMode( KigPart& doc );
+ virtual ~ScriptCreationMode();
+
+ virtual bool queryFinish();
+ virtual bool queryCancel();
+};
+
+/**
+ * Script mode to edit an already-built script.
+ */
+class ScriptEditMode
+ : public ScriptModeBase
+{
+private:
+ ObjectTypeCalcer* mexecuted;
+ std::vector<ObjectCalcer*> mexecargs;
+ std::vector<ObjectCalcer*> mcompiledargs;
+
+ QString morigscript;
+
+public:
+ ScriptEditMode( ObjectTypeCalcer* exec_calc, KigPart& doc );
+ virtual ~ScriptEditMode();
+
+ virtual bool queryFinish();
+ virtual bool queryCancel();
+};
+
+#endif