1
// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
3
// This program is free software; you can redistribute it and/or
4
// modify it under the terms of the GNU General Public License
5
// as published by the Free Software Foundation; either version 2
6
// of the License, or (at your option) any later version.
8
// This program is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
// GNU General Public License for more details.
13
// You should have received a copy of the GNU General Public License
14
// along with this program; if not, write to the Free Software
15
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
#include "script_mode.h"
20
#include "newscriptwizard.h"
21
#include "python_type.h"
22
#include "python_scripter.h"
24
#include "../kig/kig_commands.h"
25
#include "../kig/kig_part.h"
26
#include "../kig/kig_view.h"
27
#include "../misc/calcpaths.h"
28
#include "../misc/kigpainter.h"
29
#include "../modes/dragrectmode.h"
30
#include "../objects/bogus_imp.h"
31
#include "../objects/object_imp.h"
32
#include "../objects/object_factory.h"
34
#include <qbytearray.h>
36
#include <qpushbutton.h>
41
#include <kmessagebox.h>
43
void ScriptModeBase::dragRect( const QPoint& p, KigWidget& w )
45
if ( mwawd != SelectingArgs ) return;
47
DragRectMode dm( p, mdoc, w );
49
std::vector<ObjectHolder*> ret = dm.ret();
51
KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
54
std::vector<ObjectHolder*> tmp( margs.begin(), margs.begin() );
55
pter.drawObjects( tmp, false );
59
std::copy( ret.begin(), ret.end(), std::inserter( margs, margs.begin() ) );
60
pter.drawObjects( ret, true );
62
w.updateCurPix( pter.overlay() );
66
void ScriptModeBase::leftClickedObject( ObjectHolder* o, const QPoint&,
69
std::list<ObjectHolder*>::iterator dup_o;
71
if ( mwawd != SelectingArgs ) return;
73
KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
75
if ( (dup_o = std::find( margs.begin(), margs.end(), o )) != margs.end() )
78
pter.drawObject( o, false );
83
pter.drawObject( o, true );
85
w.updateCurPix( pter.overlay() );
89
void ScriptModeBase::mouseMoved( const std::vector<ObjectHolder*>& os,
90
const QPoint& pt, KigWidget& w, bool )
92
if ( mwawd != SelectingArgs ) return;
97
w.setCursor( Qt::ArrowCursor );
98
mdoc.emitStatusBarText( 0 );
103
// the cursor is over an object, show object type next to cursor
104
// and set statusbar text
106
w.setCursor( Qt::PointingHandCursor );
107
QString selectstat = os.front()->selectStatement();
110
mdoc.emitStatusBarText( selectstat );
111
KigPainter p( w.screenInfo(), &w.curPix, mdoc.document() );
113
// set the text next to the arrow cursor
115
point.setX(point.x()+15);
117
p.drawTextStd( point, selectstat );
118
w.updateWidget( p.overlay() );
122
ScriptModeBase::ScriptModeBase( KigPart& doc )
123
: BaseMode( doc ), mwizard( 0 ), mpart( doc ),
124
mwawd( SelectingArgs )
126
mwizard = new NewScriptWizard( doc.widget(), this, doc.iconLoader() );
131
ScriptModeBase::~ScriptModeBase()
135
void ScriptModeBase::killMode()
137
mdoc.doneMode( this );
140
bool ScriptCreationMode::queryCancel()
146
void ScriptModeBase::argsPageEntered()
148
mwawd = SelectingArgs;
152
void ScriptModeBase::enableActions()
154
KigMode::enableActions();
155
// we don't enable any actions..
158
void ScriptModeBase::codePageEntered()
160
if ( mwizard->text().isEmpty() )
162
// insert template code..
163
QString tempcode = ScriptType::templateCode( mtype, margs );
164
mwizard->setText( tempcode );
166
mwawd = EnteringCode;
170
void ScriptModeBase::redrawScreen( KigWidget* w )
172
std::vector<ObjectHolder*> sel;
173
if ( mwawd == SelectingArgs )
174
sel = std::vector<ObjectHolder*>( margs.begin(), margs.end() );
175
w->redrawScreen( sel );
176
w->updateScrollBars();
179
bool ScriptCreationMode::queryFinish()
181
std::vector<ObjectCalcer*> args;
183
QString script = mwizard->text();
184
args.push_back( new ObjectConstCalcer( new StringImp( script ) ) );
186
ObjectTypeCalcer* compiledscript =
187
new ObjectTypeCalcer( PythonCompileType::instance(), args );
188
compiledscript->calc( mdoc.document() );
191
args.push_back( compiledscript );
192
for ( std::list<ObjectHolder*>::iterator i = margs.begin();
193
i != margs.end(); ++i )
194
args.push_back( ( *i )->calcer() );
196
ObjectTypeCalcer::shared_ptr reto =
197
new ObjectTypeCalcer( PythonExecuteType::instance(), args );
198
reto->calc( mdoc.document() );
200
if ( reto->imp()->inherits( InvalidImp::stype() ) )
202
PythonScripter* inst = PythonScripter::instance();
203
QByteArray errtrace = inst->lastErrorExceptionTraceback().c_str();
204
if ( inst->errorOccurred() )
206
KMessageBox::detailedSorry(
207
mwizard, i18n( "The Python interpreter caught an error during the execution of your "
208
"script. Please fix the script and click the Finish button again." ),
209
i18n( "The Python Interpreter generated the following error output:\n%1", QString( errtrace ) ) );
214
mwizard, i18n( "There seems to be an error in your script. The Python interpreter "
215
"reported no errors, but the script does not generate "
216
"a valid object. Please fix the script, and click the Finish button "
223
if ( reto->imp()->inherits( DoubleImp::stype() ) ||
224
reto->imp()->inherits( IntImp::stype() ) )
227
* if the python script returns a DoubleImp (IntImp) we need a way to let the user
228
* interact with the result. We do this by adding a text label (located at
229
* the origin) that contains the DoubleImp (IntImp) value.
231
QString s = QString("%1");
232
Coordinate coord = Coordinate( 0., 0. );
233
bool needframe = false;
234
std::vector<ObjectCalcer*> args;
235
args.push_back( reto.get() );
236
ObjectHolder* label = 0;
237
label = ObjectFactory::instance()->label( s, coord, needframe, args, mdoc.document() );
238
mdoc.addObject( label );
239
} else if ( reto->imp()->inherits( StringImp::stype() ) )
242
* if the python script returns a StringImp we need a way to let the user
243
* interact with the result, see above.
245
QString s = QString("%1");
246
Coordinate coord = Coordinate( 0., 0. );
247
bool needframe = false;
248
std::vector<ObjectCalcer*> args;
249
args.push_back( reto.get() );
250
ObjectHolder* label = 0;
251
label = ObjectFactory::instance()->label( s, coord, needframe, args, mdoc.document() );
252
mdoc.addObject( label );
253
} else mdoc.addObject( new ObjectHolder( reto.get() ) );
259
void ScriptModeBase::midClicked( const QPoint&, KigWidget& )
263
void ScriptModeBase::rightClicked( const std::vector<ObjectHolder*>&,
264
const QPoint&, KigWidget& )
268
void ScriptModeBase::setScriptType( ScriptType::Type type )
271
mwizard->setType( mtype );
274
void ScriptModeBase::addArgs( const std::vector<ObjectHolder*>& obj, KigWidget& w )
276
KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
278
std::copy( obj.begin(), obj.end(), std::inserter( margs, margs.begin() ) );
279
pter.drawObjects( obj, true );
281
w.updateCurPix( pter.overlay() );
285
void ScriptModeBase::goToCodePage()
290
ScriptCreationMode::ScriptCreationMode( KigPart& doc )
291
: ScriptModeBase( doc )
296
ScriptCreationMode::~ScriptCreationMode()
300
ScriptEditMode::ScriptEditMode( ObjectTypeCalcer* exec_calc, KigPart& doc )
301
: ScriptModeBase( doc ), mexecuted( exec_calc )
303
mwawd = EnteringCode;
305
mexecargs = mexecuted->parents();
306
assert( mexecargs.size() >= 1 );
308
mcompiledargs = mexecargs[0]->parents();
309
assert( mcompiledargs.size() == 1 );
311
const ObjectImp* imp = static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->imp();
312
assert( dynamic_cast<const StringImp*>( imp ) );
313
// save the original script text, in case the user modifies the text
314
// in the editor and aborts the editing
315
morigscript = static_cast<const StringImp*>( imp )->data();
317
mwizard->setWindowTitle( KDialog::makeStandardCaption( i18nc( "'Edit' is a verb", "Edit Script" ) ) );
318
mwizard->setText( morigscript );
321
mwizard->button( QWizard::BackButton )->setEnabled( false );
324
ScriptEditMode::~ScriptEditMode()
328
bool ScriptEditMode::queryFinish()
330
MonitorDataObjects mon( mcompiledargs );
332
static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->switchImp( new StringImp( mwizard->text() ) );
333
mexecargs[0]->calc( mpart.document() );
335
mexecuted->calc( mpart.document() );
337
mpart.redrawScreen();
339
KigCommand* comm = new KigCommand( mpart, i18n( "Edit Python Script" ) );
342
if ( mexecuted->imp()->inherits( InvalidImp::stype() ) )
344
PythonScripter* inst = PythonScripter::instance();
345
QByteArray errtrace = inst->lastErrorExceptionTraceback().c_str();
346
if ( inst->errorOccurred() )
348
KMessageBox::detailedSorry(
349
mwizard, i18n( "The Python interpreter caught an error during the execution of your "
350
"script. Please fix the script." ),
351
i18n( "The Python Interpreter generated the following error output:\n%1", QString( errtrace ) ) );
356
mwizard, i18n( "There seems to be an error in your script. The Python interpreter "
357
"reported no errors, but the script does not generate "
358
"a valid object. Please fix the script." ) );
364
mpart.history()->push( comm );
365
mpart.setModified( true );
371
bool ScriptEditMode::queryCancel()
373
// reverting the original script text
374
static_cast<ObjectConstCalcer*>( mcompiledargs[0] )->switchImp( new StringImp( morigscript ) );
375
mexecargs[0]->calc( mpart.document() );
377
mexecuted->calc( mpart.document() );
379
assert( !mexecuted->imp()->inherits( InvalidImp::stype() ) );
381
mpart.redrawScreen();
383
// no need to further checks here, as the original script text is ok