support invokation of cv windows from parallel threads to an external qt application.
This commit is contained in:
		| @@ -76,6 +76,17 @@ static const unsigned int threshold_zoom_img_region = 30; | |||||||
| static CvWinProperties* global_control_panel = NULL; | static CvWinProperties* global_control_panel = NULL; | ||||||
| //end static and global | //end static and global | ||||||
|  |  | ||||||
|  | // Declaration | ||||||
|  | Qt::ConnectionType autoBlockingConnection(); | ||||||
|  |  | ||||||
|  | // Implementation - this allows us to do blocking whilst automatically selecting the right | ||||||
|  | // behaviour for in-thread and out-of-thread launches of cv windows. Qt strangely doesn't | ||||||
|  | // cater for this, but does for strictly queued connections. | ||||||
|  | Qt::ConnectionType autoBlockingConnection() { | ||||||
|  |   return (QThread::currentThread() != QApplication::instance()->thread()) | ||||||
|  |       ? Qt::BlockingQueuedConnection | ||||||
|  |       : Qt::DirectConnection; | ||||||
|  | } | ||||||
|  |  | ||||||
| CV_IMPL CvFont cvFontQt(const char* nameFont, int pointSize,CvScalar color,int weight,int style, int spacing) | CV_IMPL CvFont cvFontQt(const char* nameFont, int pointSize,CvScalar color,int weight,int style, int spacing) | ||||||
| { | { | ||||||
| @@ -104,7 +115,7 @@ CV_IMPL void cvAddText(const CvArr* img, const char* text, CvPoint org, CvFont* | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "putText", |         "putText", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(void*, (void*) img), |         Q_ARG(void*, (void*) img), | ||||||
|         Q_ARG(QString,QString(text)), |         Q_ARG(QString,QString(text)), | ||||||
|         Q_ARG(QPoint, QPoint(org.x,org.y)), |         Q_ARG(QPoint, QPoint(org.x,org.y)), | ||||||
| @@ -120,8 +131,7 @@ double cvGetRatioWindow_QT(const char* name) | |||||||
|     double result = -1; |     double result = -1; | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "getRatioWindow", |         "getRatioWindow", | ||||||
|         //Qt::DirectConnection, |         autoBlockingConnection(), | ||||||
|         Qt::AutoConnection, |  | ||||||
|         Q_RETURN_ARG(double, result), |         Q_RETURN_ARG(double, result), | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
|  |  | ||||||
| @@ -137,7 +147,7 @@ void cvSetRatioWindow_QT(const char* name,double prop_value) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "setRatioWindow", |         "setRatioWindow", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(double, prop_value)); |         Q_ARG(double, prop_value)); | ||||||
| } | } | ||||||
| @@ -151,8 +161,7 @@ double cvGetPropWindow_QT(const char* name) | |||||||
|     double result = -1; |     double result = -1; | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "getPropWindow", |         "getPropWindow", | ||||||
|         //Qt::DirectConnection, |         autoBlockingConnection(), | ||||||
|         Qt::AutoConnection, |  | ||||||
|         Q_RETURN_ARG(double, result), |         Q_RETURN_ARG(double, result), | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
|  |  | ||||||
| @@ -167,7 +176,7 @@ void cvSetPropWindow_QT(const char* name,double prop_value) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "setPropWindow", |         "setPropWindow", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(double, prop_value)); |         Q_ARG(double, prop_value)); | ||||||
| } | } | ||||||
| @@ -180,7 +189,7 @@ void cvSetModeWindow_QT(const char* name, double prop_value) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "toggleFullScreen", |         "toggleFullScreen", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(double, prop_value)); |         Q_ARG(double, prop_value)); | ||||||
| } | } | ||||||
| @@ -195,7 +204,7 @@ double cvGetModeWindow_QT(const char* name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "isFullScreen", |         "isFullScreen", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_RETURN_ARG(double, result), |         Q_RETURN_ARG(double, result), | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
|  |  | ||||||
| @@ -210,8 +219,7 @@ CV_IMPL void cvDisplayOverlay(const char* name, const char* text, int delayms) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "displayInfo", |         "displayInfo", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         //Qt::DirectConnection, |  | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(QString, QString(text)), |         Q_ARG(QString, QString(text)), | ||||||
|         Q_ARG(int, delayms)); |         Q_ARG(int, delayms)); | ||||||
| @@ -225,7 +233,7 @@ CV_IMPL void cvSaveWindowParameters(const char* name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "saveWindowParameters", |         "saveWindowParameters", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -237,7 +245,7 @@ CV_IMPL void cvLoadWindowParameters(const char* name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "loadWindowParameters", |         "loadWindowParameters", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -249,8 +257,7 @@ CV_IMPL void cvDisplayStatusBar(const char* name, const char* text, int delayms) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "displayStatusBar", |         "displayStatusBar", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         //Qt::DirectConnection, |  | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(QString, QString(text)), |         Q_ARG(QString, QString(text)), | ||||||
|         Q_ARG(int, delayms)); |         Q_ARG(int, delayms)); | ||||||
| @@ -328,7 +335,6 @@ CV_IMPL int cvWaitKey(int delay) | |||||||
|  |  | ||||||
|         guiMainThread->bTimeOut = false; |         guiMainThread->bTimeOut = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -447,7 +453,6 @@ static int icvInitSystem(int* c, char** v) | |||||||
|     if (!QApplication::instance()) |     if (!QApplication::instance()) | ||||||
|     { |     { | ||||||
|         new QApplication(*c, v); |         new QApplication(*c, v); | ||||||
|         setlocale(LC_NUMERIC,"C"); |  | ||||||
|  |  | ||||||
|         qDebug() << "init done"; |         qDebug() << "init done"; | ||||||
|  |  | ||||||
| @@ -471,17 +476,18 @@ CV_IMPL int cvNamedWindow(const char* name, int flags) | |||||||
| { | { | ||||||
|     if (!guiMainThread) |     if (!guiMainThread) | ||||||
|         guiMainThread = new GuiReceiver; |         guiMainThread = new GuiReceiver; | ||||||
|  |     if (QThread::currentThread() != QApplication::instance()->thread()) { | ||||||
|     if (multiThreads) |         multiThreads = true; | ||||||
|         QMetaObject::invokeMethod(guiMainThread, |         QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "createWindow", |         "createWindow", | ||||||
|         Qt::BlockingQueuedConnection, |         Qt::BlockingQueuedConnection,  // block so that we can do useful stuff once we confirm it is created | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(int, flags)); |         Q_ARG(int, flags)); | ||||||
|     else |      } else { | ||||||
|         guiMainThread->createWindow(QString(name), flags); |         guiMainThread->createWindow(QString(name), flags); | ||||||
|  |      } | ||||||
|  |  | ||||||
|     return 1; //Dummy value |     return 1; //Dummy value - probably should return the result of the invocation. | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -492,8 +498,7 @@ CV_IMPL void cvDestroyWindow(const char* name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "destroyWindow", |         "destroyWindow", | ||||||
|         //Qt::BlockingQueuedConnection, |         Qt::AutoConnection,  // if another thread is controlling, let it handle it without blocking ourselves here | ||||||
|         Qt::AutoConnection, |  | ||||||
|         Q_ARG(QString, QString(name))); |         Q_ARG(QString, QString(name))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -502,11 +507,10 @@ CV_IMPL void cvDestroyAllWindows() | |||||||
| { | { | ||||||
|     if (!guiMainThread) |     if (!guiMainThread) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "destroyAllWindow", |         "destroyAllWindow", | ||||||
|         //Qt::BlockingQueuedConnection, |         Qt::AutoConnection  // if another thread is controlling, let it handle it without blocking ourselves here | ||||||
|         Qt::AutoConnection); |         ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -532,26 +536,21 @@ CV_IMPL void cvMoveWindow(const char* name, int x, int y) | |||||||
| { | { | ||||||
|     if (!guiMainThread) |     if (!guiMainThread) | ||||||
|         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" ); |         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" ); | ||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "moveWindow", |         "moveWindow", | ||||||
|         //Qt::BlockingQueuedConnection, |         autoBlockingConnection(), | ||||||
|         Qt::AutoConnection, |  | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(int, x), |         Q_ARG(int, x), | ||||||
|         Q_ARG(int, y)); |         Q_ARG(int, y)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| CV_IMPL void cvResizeWindow(const char* name, int width, int height) | CV_IMPL void cvResizeWindow(const char* name, int width, int height) | ||||||
| { | { | ||||||
|     if (!guiMainThread) |     if (!guiMainThread) | ||||||
|         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" ); |         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" ); | ||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "resizeWindow", |         "resizeWindow", | ||||||
|         //Qt::BlockingQueuedConnection, |         autoBlockingConnection(), | ||||||
|         Qt::AutoConnection, |  | ||||||
|         Q_ARG(QString, QString(name)), |         Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(int, width), |         Q_ARG(int, width), | ||||||
|         Q_ARG(int, height)); |         Q_ARG(int, height)); | ||||||
| @@ -565,7 +564,7 @@ CV_IMPL int cvCreateTrackbar2(const char* name_bar, const char* window_name, int | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "addSlider2", |         "addSlider2", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name_bar)), |         Q_ARG(QString, QString(name_bar)), | ||||||
|         Q_ARG(QString, QString(window_name)), |         Q_ARG(QString, QString(window_name)), | ||||||
|         Q_ARG(void*, (void*)val), |         Q_ARG(void*, (void*)val), | ||||||
| @@ -590,7 +589,7 @@ CV_IMPL int cvCreateTrackbar(const char* name_bar, const char* window_name, int* | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "addSlider", |         "addSlider", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(name_bar)), |         Q_ARG(QString, QString(name_bar)), | ||||||
|         Q_ARG(QString, QString(window_name)), |         Q_ARG(QString, QString(window_name)), | ||||||
|         Q_ARG(void*, (void*)value), |         Q_ARG(void*, (void*)value), | ||||||
| @@ -611,7 +610,7 @@ CV_IMPL int cvCreateButton(const char* button_name, CvButtonCallback on_change, | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "addButton", |         "addButton", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(button_name)), |         Q_ARG(QString, QString(button_name)), | ||||||
|         Q_ARG(int,  button_type), |         Q_ARG(int,  button_type), | ||||||
|         Q_ARG(int, initial_button_state), |         Q_ARG(int, initial_button_state), | ||||||
| @@ -661,13 +660,17 @@ CV_IMPL void cvShowImage(const char* name, const CvArr* arr) | |||||||
| { | { | ||||||
|     if (!guiMainThread) |     if (!guiMainThread) | ||||||
|         guiMainThread = new GuiReceiver; |         guiMainThread = new GuiReceiver; | ||||||
|  |     if (QThread::currentThread() != QApplication::instance()->thread()) { | ||||||
|  |         multiThreads = true; | ||||||
|         QMetaObject::invokeMethod(guiMainThread, |         QMetaObject::invokeMethod(guiMainThread, | ||||||
|             "showImage", |             "showImage", | ||||||
|         //Qt::BlockingQueuedConnection, |              autoBlockingConnection(), | ||||||
|         Qt::DirectConnection, |  | ||||||
|              Q_ARG(QString, QString(name)), |              Q_ARG(QString, QString(name)), | ||||||
|         Q_ARG(void*, (void*)arr)); |              Q_ARG(void*, (void*)arr) | ||||||
|  |         ); | ||||||
|  |      } else { | ||||||
|  |         guiMainThread->showImage(QString(name), (void*)arr); | ||||||
|  |      } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -680,7 +683,7 @@ CV_IMPL void cvSetOpenGlDrawCallback(const char* window_name, CvOpenGlDrawCallba | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "setOpenGlDrawCallback", |         "setOpenGlDrawCallback", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(window_name)), |         Q_ARG(QString, QString(window_name)), | ||||||
|         Q_ARG(void*, (void*)callback), |         Q_ARG(void*, (void*)callback), | ||||||
|         Q_ARG(void*, userdata)); |         Q_ARG(void*, userdata)); | ||||||
| @@ -694,7 +697,7 @@ CV_IMPL void cvSetOpenGlContext(const char* window_name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "setOpenGlContext", |         "setOpenGlContext", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(window_name))); |         Q_ARG(QString, QString(window_name))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -706,7 +709,7 @@ CV_IMPL void cvUpdateWindow(const char* window_name) | |||||||
|  |  | ||||||
|     QMetaObject::invokeMethod(guiMainThread, |     QMetaObject::invokeMethod(guiMainThread, | ||||||
|         "updateWindow", |         "updateWindow", | ||||||
|         Qt::AutoConnection, |         autoBlockingConnection(), | ||||||
|         Q_ARG(QString, QString(window_name))); |         Q_ARG(QString, QString(window_name))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -721,7 +724,7 @@ double cvGetOpenGlProp_QT(const char* name) | |||||||
|     { |     { | ||||||
|         QMetaObject::invokeMethod(guiMainThread, |         QMetaObject::invokeMethod(guiMainThread, | ||||||
|             "isOpenGl", |             "isOpenGl", | ||||||
|             Qt::AutoConnection, |             autoBlockingConnection(), | ||||||
|             Q_RETURN_ARG(double, result), |             Q_RETURN_ARG(double, result), | ||||||
|             Q_ARG(QString, QString(name))); |             Q_ARG(QString, QString(name))); | ||||||
|     } |     } | ||||||
| @@ -737,6 +740,9 @@ double cvGetOpenGlProp_QT(const char* name) | |||||||
| GuiReceiver::GuiReceiver() : bTimeOut(false), nb_windows(0) | GuiReceiver::GuiReceiver() : bTimeOut(false), nb_windows(0) | ||||||
| { | { | ||||||
|     doesExternalQAppExist = (QApplication::instance() != 0); |     doesExternalQAppExist = (QApplication::instance() != 0); | ||||||
|  |     if ( doesExternalQAppExist ) { | ||||||
|  |         moveToThread(QApplication::instance()->thread()); | ||||||
|  |     } | ||||||
|     icvInitSystem(¶meterSystemC, parameterSystemV); |     icvInitSystem(¶meterSystemC, parameterSystemV); | ||||||
|  |  | ||||||
|     timer = new QTimer(this); |     timer = new QTimer(this); | ||||||
| @@ -965,6 +971,7 @@ void GuiReceiver::showImage(QString name, void* arr) | |||||||
|  |  | ||||||
| void GuiReceiver::destroyWindow(QString name) | void GuiReceiver::destroyWindow(QString name) | ||||||
| { | { | ||||||
|  |  | ||||||
|     QPointer<CvWindow> w = icvFindWindowByName(name); |     QPointer<CvWindow> w = icvFindWindowByName(name); | ||||||
|  |  | ||||||
|     if (w) |     if (w) | ||||||
| @@ -1526,7 +1533,6 @@ CvWinProperties::~CvWinProperties() | |||||||
| CvWindow::CvWindow(QString name, int arg2) | CvWindow::CvWindow(QString name, int arg2) | ||||||
| { | { | ||||||
|     type = type_CvWindow; |     type = type_CvWindow; | ||||||
|     moveToThread(qApp->instance()->thread()); |  | ||||||
|  |  | ||||||
|     param_flags = arg2 & 0x0000000F; |     param_flags = arg2 & 0x0000000F; | ||||||
|     param_gui_mode = arg2 & 0x000000F0; |     param_gui_mode = arg2 & 0x000000F0; | ||||||
| @@ -2366,7 +2372,6 @@ void DefaultViewPort::updateImage(const CvArr* arr) | |||||||
|         //use to compute mouse coordinate, I need to update the ratio here and in resizeEvent |         //use to compute mouse coordinate, I need to update the ratio here and in resizeEvent | ||||||
|         ratioX = width() / float(image2Draw_mat->cols); |         ratioX = width() / float(image2Draw_mat->cols); | ||||||
|         ratioY = height() / float(image2Draw_mat->rows); |         ratioY = height() / float(image2Draw_mat->rows); | ||||||
|  |  | ||||||
|         updateGeometry(); |         updateGeometry(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Daniel Stonier
					Daniel Stonier