00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kexiscriptdesignview.h"
00024 #include "kexiscripteditor.h"
00025
00026 #include <kross/main/manager.h>
00027 #include <kross/main/scriptcontainer.h>
00028 #include <kross/main/scriptaction.h>
00029 #include <kross/api/interpreter.h>
00030
00031 #include <qlayout.h>
00032 #include <qsplitter.h>
00033 #include <qtimer.h>
00034 #include <qdatetime.h>
00035 #include <qdom.h>
00036 #include <qstylesheet.h>
00037 #include <ktextbrowser.h>
00038 #include <kdebug.h>
00039
00040 #include <kexidialogbase.h>
00041 #include <kexidb/connection.h>
00042
00044 class KexiScriptDesignViewPrivate
00045 {
00046 public:
00047
00052 Kross::Api::ScriptAction* scriptaction;
00053
00055 KexiScriptEditor* editor;
00056
00058 KoProperty::Set* properties;
00059
00061 KTextBrowser* statusbrowser;
00062 };
00063
00064 KexiScriptDesignView::KexiScriptDesignView(KexiMainWindow *mainWin, QWidget *parent, Kross::Api::ScriptAction* scriptaction)
00065 : KexiViewBase(mainWin, parent, "KexiScriptDesignView")
00066 , d( new KexiScriptDesignViewPrivate() )
00067 {
00068 d->scriptaction = scriptaction;
00069
00070 QSplitter* splitter = new QSplitter(this);
00071 splitter->setOrientation(Vertical);
00072 QHBoxLayout* layout = new QHBoxLayout(this);
00073 layout->addWidget(splitter);
00074
00075 d->editor = new KexiScriptEditor(mainWin, splitter, "ScriptEditor");
00076 splitter->setFocusProxy(d->editor);
00077 addChildView(d->editor);
00078 setViewWidget(d->editor);
00079
00080 d->statusbrowser = new KTextBrowser(splitter, "ScriptStatusBrowser");
00081 d->statusbrowser->setReadOnly(true);
00082 d->statusbrowser->setTextFormat(QTextBrowser::RichText);
00083
00084 d->statusbrowser->installEventFilter(this);
00085 splitter->setResizeMode(d->statusbrowser, QSplitter::KeepSize);
00086
00087 plugSharedAction( "script_execute", this, SLOT(execute()) );
00088 if(KexiEditor::isAdvancedEditor())
00089 plugSharedAction( "script_config_editor", d->editor, SLOT(slotConfigureEditor()) );
00090
00091 loadData();
00092
00093 d->properties = new KoProperty::Set(this, "KexiScripting");
00094 updateProperties();
00095
00096 d->editor->initialize( d->scriptaction );
00097 }
00098
00099 KexiScriptDesignView::~KexiScriptDesignView()
00100 {
00101 delete d;
00102 }
00103
00104 Kross::Api::ScriptAction* KexiScriptDesignView::scriptAction() const
00105 {
00106 return d->scriptaction;
00107 }
00108
00109 void KexiScriptDesignView::updateProperties()
00110 {
00111 Kross::Api::Manager* manager = Kross::Api::Manager::scriptManager();
00112
00113 QString interpretername = d->scriptaction->getInterpreterName();
00114 Kross::Api::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->getInterpreterInfo(interpretername);
00115
00116 {
00117
00118 QStringList list;
00119 list << "python" << "ruby";
00120 QStringList::Iterator it( list.begin() );
00121 while( (! info) && (it != list.end()) ) {
00122 interpretername = (*it);
00123 info = manager->getInterpreterInfo(interpretername);
00124 if(info)
00125 d->scriptaction->setInterpreterName(interpretername);
00126 ++it;
00127 }
00128 }
00129
00130 if(info) {
00131 disconnect(d->properties, SIGNAL( propertyChanged(KoProperty::Set&, KoProperty::Property&) ),
00132 this, SLOT( slotPropertyChanged(KoProperty::Set&, KoProperty::Property&) ));
00133
00134 d->properties->clear();
00135
00136 QStringList interpreters = manager->getInterpreters();
00137 KoProperty::Property::ListData* proplist = new KoProperty::Property::ListData(interpreters, interpreters);
00138 KoProperty::Property* prop = new KoProperty::Property(
00139 "language",
00140 proplist,
00141 d->scriptaction->getInterpreterName(),
00142 i18n("Interpreter"),
00143 i18n("The used scripting interpreter."),
00144 KoProperty::List
00145 );
00146 d->properties->addProperty(prop);
00147
00148 Kross::Api::InterpreterInfo::Option::Map options = info->getOptions();
00149 Kross::Api::InterpreterInfo::Option::Map::Iterator it( options.begin() );
00150 for(; it != options.end(); ++it) {
00151 Kross::Api::InterpreterInfo::Option* option = it.data();
00152 KoProperty::Property* prop = new KoProperty::Property(
00153 it.key().latin1(),
00154 d->scriptaction->getOption(it.key(), option->value),
00155 option->name,
00156 option->comment,
00157 KoProperty::Auto
00158 );
00159 d->properties->addProperty(prop);
00160 }
00161
00162 connect(d->properties, SIGNAL( propertyChanged(KoProperty::Set&, KoProperty::Property&) ),
00163 this, SLOT( slotPropertyChanged(KoProperty::Set&, KoProperty::Property&) ));
00164 }
00165
00166
00167 propertySetReloaded(true);
00168 }
00169
00170 KoProperty::Set* KexiScriptDesignView::propertySet()
00171 {
00172 return d->properties;
00173 }
00174
00175 void KexiScriptDesignView::slotPropertyChanged(KoProperty::Set& , KoProperty::Property& property)
00176 {
00177 if(property.isNull())
00178 return;
00179
00180 if(property.name() == "language") {
00181 QString language = property.value().toString();
00182 kdDebug() << QString("KexiScriptDesignView::slotPropertyChanged() language=%1").arg(language) << endl;
00183 d->scriptaction->setInterpreterName( language );
00184
00185
00186 d->editor->setHighlightMode( language );
00187
00188
00189
00190 QTimer::singleShot(150, this, SLOT( updateProperties() ));
00191 }
00192 else {
00193 bool ok = d->scriptaction->setOption( property.name(), property.value() );
00194 if(! ok) {
00195 kdWarning() << QString("KexiScriptDesignView::slotPropertyChanged() unknown property '%1'.").arg(property.name()) << endl;
00196 return;
00197 }
00198 }
00199
00200 setDirty(true);
00201 }
00202
00203 void KexiScriptDesignView::execute()
00204 {
00205 d->statusbrowser->clear();
00206 QTime time;
00207 time.start();
00208 d->statusbrowser->append( i18n("Execution of the script \"%1\" started.").arg(d->scriptaction->name()) );
00209
00210 d->scriptaction->activate();
00211 if( d->scriptaction->hadException() ) {
00212 QString errormessage = d->scriptaction->getException()->getError();
00213 d->statusbrowser->append(QString("<b>%2</b><br>").arg(QStyleSheet::escape(errormessage)) );
00214
00215 QString tracedetails = d->scriptaction->getException()->getTrace();
00216 d->statusbrowser->append( QStyleSheet::escape(tracedetails) );
00217
00218 long lineno = d->scriptaction->getException()->getLineNo();
00219 if(lineno >= 0)
00220 d->editor->setLineNo(lineno);
00221 }
00222 else {
00223 d->statusbrowser->append( i18n("Successfully executed. Time elapsed: %1ms").arg(time.elapsed()) );
00224 }
00225 }
00226
00227 bool KexiScriptDesignView::loadData()
00228 {
00229 QString data;
00230 if(! loadDataBlock(data)) {
00231 kexipluginsdbg << "KexiScriptDesignView::loadData(): no DataBlock" << endl;
00232 return false;
00233 }
00234
00235 QString errMsg;
00236 int errLine;
00237 int errCol;
00238
00239 QDomDocument domdoc;
00240 bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol);
00241
00242 if(! parsed) {
00243 kexipluginsdbg << "KexiScriptDesignView::loadData() XML parsing error line: " << errLine << " col: " << errCol << " message: " << errMsg << endl;
00244 return false;
00245 }
00246
00247 QDomElement scriptelem = domdoc.namedItem("script").toElement();
00248 if(scriptelem.isNull()) {
00249 kexipluginsdbg << "KexiScriptDesignView::loadData(): script domelement is null" << endl;
00250 return false;
00251 }
00252
00253 QString interpretername = scriptelem.attribute("language");
00254 Kross::Api::Manager* manager = Kross::Api::Manager::scriptManager();
00255 Kross::Api::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->getInterpreterInfo(interpretername);
00256 if(info) {
00257 d->scriptaction->setInterpreterName(interpretername);
00258
00259 Kross::Api::InterpreterInfo::Option::Map options = info->getOptions();
00260 Kross::Api::InterpreterInfo::Option::Map::Iterator it = options.begin();
00261 for(; it != options.end(); ++it) {
00262 QString value = scriptelem.attribute( it.data()->name );
00263 if(! value.isNull()) {
00264 QVariant v(value);
00265 if( v.cast( it.data()->value.type() ) )
00266 d->scriptaction->setOption(it.data()->name, v);
00267 }
00268 }
00269 }
00270
00271 d->scriptaction->setCode( scriptelem.text() );
00272
00273 return true;
00274 }
00275
00276 KexiDB::SchemaData* KexiScriptDesignView::storeNewData(const KexiDB::SchemaData& sdata, bool &cancel)
00277 {
00278 KexiDB::SchemaData *s = KexiViewBase::storeNewData(sdata, cancel);
00279 kexipluginsdbg << "KexiScriptDesignView::storeNewData(): new id:" << s->id() << endl;
00280
00281 if(!s || cancel) {
00282 delete s;
00283 return 0;
00284 }
00285
00286 if(! storeData()) {
00287 kdWarning() << "KexiScriptDesignView::storeNewData Failed to store the data." << endl;
00288
00289 KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00290 conn->removeObject( s->id() );
00291 delete s;
00292 return 0;
00293 }
00294
00295 return s;
00296 }
00297
00298 tristate KexiScriptDesignView::storeData(bool )
00299 {
00300 kexipluginsdbg << "KexiScriptDesignView::storeData(): " << parentDialog()->partItem()->name() << " [" << parentDialog()->id() << "]" << endl;
00301
00302 QDomDocument domdoc("script");
00303 QDomElement scriptelem = domdoc.createElement("script");
00304 domdoc.appendChild(scriptelem);
00305
00306 QString language = d->scriptaction->getInterpreterName();
00307 scriptelem.setAttribute("language", language);
00308
00309 Kross::Api::InterpreterInfo* info = Kross::Api::Manager::scriptManager()->getInterpreterInfo(language);
00310 if(info) {
00311 Kross::Api::InterpreterInfo::Option::Map defoptions = info->getOptions();
00312 QMap<QString, QVariant>& options = d->scriptaction->getOptions();
00313 for(QMap<QString, QVariant>::Iterator it = options.begin(); it != options.end(); ++it) {
00314 if( defoptions.contains(it.key()) ) {
00315 scriptelem.setAttribute(it.key(), it.data().toString());
00316 }
00317 }
00318 }
00319
00320 QDomText scriptcode = domdoc.createTextNode(d->scriptaction->getCode());
00321 scriptelem.appendChild(scriptcode);
00322
00323 return storeDataBlock( domdoc.toString() );
00324 }
00325
00326 #include "kexiscriptdesignview.moc"
00327