22
22
23
23
#include " qgsapplication.h"
24
24
#include " qgslogger.h"
25
+ #include " qgsmessageoutput.h"
25
26
26
27
#include < QMessageBox>
27
28
#include < QStringList>
@@ -51,32 +52,25 @@ void QgsPythonUtils::initPython(QgisInterface* interface)
51
52
runString (" sys.path = [\" " + homePluginsPath () + " \" , \" " + pythonPath () + " \" , \" " + pluginsPath () + " \" ] + sys.path" );
52
53
53
54
// import SIP
54
- if (!runString (" from sip import wrapinstance, unwrapinstance" ))
55
+ if (!runString (" from sip import wrapinstance, unwrapinstance" ,
56
+ QObject::tr (" Couldn't load SIP module." ) + " \n " + QObject::tr (" Python support will be disabled." )))
55
57
{
56
- QMessageBox::warning (0 , QObject::tr (" Python error" ),
57
- QObject::tr (" Couldn't load SIP module.\n Python support will be disabled." ));
58
- PyErr_Clear ();
59
58
exitPython ();
60
59
return ;
61
60
}
62
61
63
62
// import Qt bindings
64
- if (!runString (" from PyQt4 import QtCore, QtGui" ))
63
+ if (!runString (" from PyQt4 import QtCore, QtGui" ,
64
+ QObject::tr (" Couldn't load PyQt4." ) + " \n " + QObject::tr (" Python support will be disabled." )))
65
65
{
66
- QMessageBox::warning (0 , QObject::tr (" Python error" ),
67
- QObject::tr (" Couldn't load PyQt bindings.\n Python support will be disabled." ));
68
- PyErr_Clear ();
69
66
exitPython ();
70
67
return ;
71
68
}
72
69
73
70
// import QGIS bindings
74
- if (! runString ( " from qgis.core import * " ) ||
75
- !runString (" from qgis.gui import *" ))
71
+ QString error_msg = QObject::tr ( " Couldn't load PyQGIS. " ) + " \n " + QObject::tr ( " Python support will be disabled. " );
72
+ if (! runString ( " from qgis.core import * " , error_msg) || !runString (" from qgis.gui import *" , error_msg ))
76
73
{
77
- QMessageBox::warning (0 , QObject::tr (" Python error" ),
78
- QObject::tr (" Couldn't load QGIS bindings.\n Python support will be disabled." ));
79
- PyErr_Clear ();
80
74
exitPython ();
81
75
return ;
82
76
}
@@ -162,13 +156,43 @@ void QgsPythonUtils::uninstallConsoleHooks()
162
156
}
163
157
164
158
165
- bool QgsPythonUtils::runString (const QString& command)
159
+ bool QgsPythonUtils::runStringUnsafe (const QString& command)
166
160
{
167
161
PyRun_String (command.toLocal8Bit ().data (), Py_single_input, mMainDict , mMainDict );
168
-
169
162
return (PyErr_Occurred () == 0 );
170
163
}
171
164
165
+ bool QgsPythonUtils::runString (const QString& command, QString msgOnError)
166
+ {
167
+ bool res = runStringUnsafe (command);
168
+ if (res)
169
+ return true ;
170
+
171
+ // an error occured
172
+ // fetch error details and show it
173
+ QString err_type, err_value;
174
+ getError (err_type, err_value);
175
+
176
+ if (msgOnError.isEmpty ())
177
+ {
178
+ // use some default message if custom hasn't been specified
179
+ msgOnError = QObject::tr (" An error occured during execution of following code:" ) + " \n <tt>" + command + " </tt>" ;
180
+ }
181
+ msgOnError.replace (" \n " , " <br>" );
182
+ QString str = msgOnError + " <br><br>" + QObject::tr (" Error details:" ) + " <br>"
183
+ + QObject::tr (" Type:" ) + " <b>" + err_type + " </b><br>"
184
+ + QObject::tr (" Value:" ) + " <b>" + err_value + " </b>" ;
185
+
186
+ // TODO: show sys.path, local variables, traceback
187
+
188
+ QgsMessageOutput* msg = QgsMessageOutput::createMessageOutput ();
189
+ msg->setTitle (QObject::tr (" Python error" ));
190
+ msg->setMessage (str, QgsMessageOutput::MessageHtml);
191
+ msg->showMessage ();
192
+
193
+ return res;
194
+ }
195
+
172
196
173
197
QString QgsPythonUtils::getTypeAsString (PyObject* obj)
174
198
{
@@ -207,7 +231,7 @@ bool QgsPythonUtils::getError(QString& errorClassName, QString& errorText)
207
231
PyObject* err_value;
208
232
PyObject* err_tb;
209
233
210
- // get the exception information
234
+ // get the exception information and clear error
211
235
PyErr_Fetch (&err_type, &err_value, &err_tb);
212
236
213
237
// get exception's class name
@@ -223,8 +247,10 @@ bool QgsPythonUtils::getError(QString& errorClassName, QString& errorText)
223
247
else
224
248
errorText.clear ();
225
249
226
- // clear exception
227
- PyErr_Clear ();
250
+ // cleanup
251
+ Py_XDECREF (err_type);
252
+ Py_XDECREF (err_value);
253
+ Py_XDECREF (err_tb);
228
254
229
255
return true ;
230
256
}
@@ -373,29 +399,16 @@ bool QgsPythonUtils::startPlugin(QString packageName)
373
399
{
374
400
QString pluginPythonVar = " plugins['" + packageName + " ']" ;
375
401
376
- // create an instance of the plugin
377
- if (!runString (pluginPythonVar + " = " + packageName + " .classFactory(iface)" ))
378
- {
379
- PyErr_Print (); // just print to console
380
- PyErr_Clear ();
402
+ QString errMsg = QObject::tr (" Couldn't load plugin " ) + packageName;
381
403
382
- QMessageBox::warning ( 0 , QObject::tr ( " Python error " ),
383
- QObject::tr ( " Couldn't load plugin " ) + packageName +
384
- QObject::tr (" due an error when calling its classFactory() method" ));
404
+ // create an instance of the plugin
405
+ if (! runString (pluginPythonVar + " = " + packageName + " .classFactory(iface) " ,
406
+ errMsg + QObject::tr (" due an error when calling its classFactory() method" )))
385
407
return false ;
386
- }
387
408
388
409
// initGui
389
- if (!runString (pluginPythonVar + " .initGui()" ))
390
- {
391
- PyErr_Print (); // just print to console
392
- PyErr_Clear ();
393
-
394
- QMessageBox::warning (0 , QObject::tr (" Python error" ),
395
- QObject::tr (" Couldn't load plugin " ) + packageName +
396
- QObject::tr (" due an error when calling its initGui() method" ));
410
+ if (!runString (pluginPythonVar + " .initGui()" , errMsg + QObject::tr (" due an error when calling its initGui() method" )))
397
411
return false ;
398
- }
399
412
400
413
return true ;
401
414
}
@@ -406,16 +419,12 @@ bool QgsPythonUtils::unloadPlugin(QString packageName)
406
419
// unload and delete plugin!
407
420
QString varName = " plugins['" + packageName + " ']" ;
408
421
409
- if (!runString (varName + " .unload()" ) ||
410
- !runString (" del " + varName))
411
- {
412
- PyErr_Print (); // just print to console
413
- PyErr_Clear ();
414
-
415
- QMessageBox::warning (0 , QObject::tr (" Python error" ),
416
- QObject::tr (" Error while unloading plugin " ) + packageName);
422
+ QString errMsg = QObject::tr (" Error while unloading plugin " ) + packageName;
423
+
424
+ if (!runString (varName + " .unload()" , errMsg))
425
+ return false ;
426
+ if (!runString (" del " + varName, errMsg))
417
427
return false ;
418
- }
419
428
420
429
return true ;
421
430
}
0 commit comments