2222
2323#include " qgsapplication.h"
2424
25-
2625#include < QMessageBox>
2726
2827QString QgsPythonUtils::mPluginsPath ;
@@ -84,9 +83,10 @@ void QgsPythonUtils::initPython(QgisInterface* interface)
8483
8584 // hook that will show information and traceback in message box
8685 runString (
87- " def qgis_except_hook (type, value, tb):\n "
86+ " def qgis_except_hook_msg (type, value, tb, msg ):\n "
8887 " lst = traceback.format_exception(type, value, tb)\n "
89- " str = '<font color=\" red\" >An error has occured while executing Python code:</font><br><br>'\n "
88+ " if msg == None: msg = 'An error has occured while executing Python code:'\n "
89+ " str = '<font color=\" red\" >'+msg+'</font><br><br>'\n "
9090 " for s in lst:\n "
9191 " str += s\n "
9292 " str = str.replace('\\ n', '<br>')\n "
@@ -96,6 +96,9 @@ void QgsPythonUtils::initPython(QgisInterface* interface)
9696 " msg.setTitle('Error')\n "
9797 " msg.setMessage(str, QgsMessageOutput.MessageHtml)\n "
9898 " msg.showMessage()\n " );
99+ runString (
100+ " def qgis_except_hook(type, value, tb):\n "
101+ " qgis_except_hook_msg(type, value, tb, None)\n " );
99102
100103 // hook for python console so all output will be redirected
101104 // and then shown in console
@@ -132,17 +135,31 @@ void QgsPythonUtils::installErrorHook()
132135
133136void QgsPythonUtils::installConsoleHooks ()
134137{
135- runString (" sys.displayhook = console_display_hook" );
138+ runString (" sys.displayhook = console_display_hook\n " );
139+
140+ runString (
141+ " class MyOutputCatcher:\n "
142+ " def __init__(self):\n "
143+ " self.data = ''\n "
144+ " def write(self, stuff):\n "
145+ " self.data += stuff\n " );
146+ runString (" _old_stdout = sys.stdout\n " );
147+ runString (" sys.stdout = MyOutputCatcher()\n " );
148+
136149}
137150
138151void QgsPythonUtils::uninstallConsoleHooks ()
139152{
140153 runString (" sys.displayhook = sys.__displayhook__" );
154+ runString (" sys.stdout = _old_stdout" );
155+
156+ // TODO: uninstalling stdout redirection doesn't work
157+
141158 // installErrorHook();
142159}
143160
144161
145- bool QgsPythonUtils::runString (QString command)
162+ bool QgsPythonUtils::runString (const QString& command)
146163{
147164 PyRun_String (command.toLocal8Bit ().data (), Py_single_input, mMainDict , mMainDict );
148165
@@ -183,15 +200,20 @@ bool QgsPythonUtils::getError(QString& errorClassName, QString& errorText)
183200}
184201
185202QString QgsPythonUtils::getResult ()
203+ {
204+ return getVariableFromMain (" __result" );
205+ }
206+
207+ QString QgsPythonUtils::getVariableFromMain (QString name)
186208{
187209 PyObject* obj;
188210 PyObject* obj_str;
189211
190212 QString output;
191213
192214 // get the result
193- obj = PyDict_GetItemString (mMainDict , " __result " ); // obj is borrowed reference
194-
215+ obj = PyDict_GetItemString (mMainDict , name ); // obj is borrowed reference
216+
195217 if (obj != NULL && obj != Py_None)
196218 {
197219 obj_str = PyObject_Str (obj); // obj_str is new reference
@@ -203,11 +225,25 @@ QString QgsPythonUtils::getResult()
203225 }
204226
205227 // erase result
206- PyDict_SetItemString (mMainDict , " __result " , Py_None);
207-
228+ PyDict_SetItemString (mMainDict , name , Py_None);
229+
208230 return output;
209231}
210232
233+ bool QgsPythonUtils::evalString (const QString& command, QString& result)
234+ {
235+ PyObject* res = PyRun_String (command.toLocal8Bit ().data (), Py_eval_input, mMainDict , mMainDict );
236+
237+ if (res != NULL && PyString_Check (res))
238+ {
239+ result = PyString_AsString (res);
240+ Py_XDECREF (res);
241+ return true ;
242+ }
243+ Py_XDECREF (res);
244+ return false ;
245+ }
246+
211247
212248QString QgsPythonUtils::pythonPath ()
213249{
@@ -248,19 +284,17 @@ QString QgsPythonUtils::getPluginMetadata(QString pluginName, QString function)
248284bool QgsPythonUtils::loadPlugin (QString packageName)
249285{
250286 // load plugin's package and ensure that plugin is reloaded when changed
251- if (!runString (" import " + packageName) ||
252- !runString (" reload(" + packageName + " )" ))
253- {
254- QString className, errorText;
255- getError (className, errorText);
256- QString str = className + " : " + errorText;
257-
258- QMessageBox::warning (0 , QObject::tr (" Python error" ),
259- QObject::tr (" Couldn't load plugin due this error:\n " ) + str);
260- return false ;
261- }
262-
263- return true ;
287+ runString (
288+ " try:\n "
289+ " import " + packageName + " \n "
290+ " reload(" + packageName + " )\n "
291+ " __main__.__plugin_result = 'OK'\n "
292+ " except:\n "
293+ " qgis_except_hook_msg(sys.exc_type, sys.exc_value, sys.exc_traceback, "
294+ " 'Couldn\\ 't load plugin \" " + packageName + " \" ')\n "
295+ " __main__.__plugin_result = 'ERROR'\n " );
296+
297+ return (getVariableFromMain (" __plugin_result" ) == " OK" );
264298}
265299
266300
0 commit comments