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