diff options
Diffstat (limited to 'kig/scripting')
-rw-r--r-- | kig/scripting/Makefile.am | 22 | ||||
-rw-r--r-- | kig/scripting/newscriptwizard.cc | 234 | ||||
-rw-r--r-- | kig/scripting/newscriptwizard.h | 72 | ||||
-rw-r--r-- | kig/scripting/newscriptwizardbase.ui | 81 | ||||
-rw-r--r-- | kig/scripting/python-kig.xml | 289 | ||||
-rw-r--r-- | kig/scripting/python-scripting-api-dox-mainpage.dox | 26 | ||||
-rw-r--r-- | kig/scripting/python_scripter.cc | 578 | ||||
-rw-r--r-- | kig/scripting/python_scripter.h | 69 | ||||
-rw-r--r-- | kig/scripting/python_type.cc | 195 | ||||
-rw-r--r-- | kig/scripting/python_type.h | 63 | ||||
-rw-r--r-- | kig/scripting/script-common.cc | 95 | ||||
-rw-r--r-- | kig/scripting/script-common.h | 61 | ||||
-rw-r--r-- | kig/scripting/script_mode.cc | 362 | ||||
-rw-r--r-- | kig/scripting/script_mode.h | 119 |
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]"" context="Raw Q-string"/> + + <RegExpr attribute="Comment" String="#.*$" context="#stay"/> + <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment"/> + <RegExpr attribute="Comment" String="^\s*"""" context="Tripple Q-comment"/> + + <StringDetect attribute="String" String="'''" context="Tripple A-string"/> + <StringDetect attribute="String" String=""""" context="Tripple Q-string"/> + <DetectChar attribute="String" char="'" context="Single A-string"/> + <DetectChar attribute="String" char=""" context="Single Q-string"/> + + <RegExpr attribute="Operator" String="[+*/\(\)%\|\[\]\{\}:=;\!<>!^&~-]" 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=""""" 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=""""" 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=""" 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=""" 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=""" 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 |