• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
2 
3 // By downloading, copying, installing or using the software you agree to this license.
4 // If you do not agree to this license, do not download, install,
5 // copy or use the software.
6 
7 
8 //                          License Agreement
9 //               For Open Source Computer Vision Library
10 
11 //Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
12 //Copyright (C) 2008-2010, Willow Garage Inc., all rights reserved.
13 //Third party copyrights are property of their respective owners.
14 
15 //Redistribution and use in source and binary forms, with or without modification,
16 //are permitted provided that the following conditions are met:
17 
18 //  * Redistribution's of source code must retain the above copyright notice,
19 //  this list of conditions and the following disclaimer.
20 
21 //  * Redistribution's in binary form must reproduce the above copyright notice,
22 //  this list of conditions and the following disclaimer in the documentation
23 //  and/or other materials provided with the distribution.
24 
25 //  * The name of the copyright holders may not be used to endorse or promote products
26 //  derived from this software without specific prior written permission.
27 
28 //This software is provided by the copyright holders and contributors "as is" and
29 //any express or implied warranties, including, but not limited to, the implied
30 //warranties of merchantability and fitness for a particular purpose are disclaimed.
31 //In no event shall the Intel Corporation or contributors be liable for any direct,
32 //indirect, incidental, special, exemplary, or consequential damages
33 //(including, but not limited to, procurement of substitute goods or services;
34 //loss of use, data, or profits; or business interruption) however caused
35 //and on any theory of liability, whether in contract, strict liability,
36 //or tort (including negligence or otherwise) arising in any way out of
37 //the use of this software, even if advised of the possibility of such damage.
38 
39 //--------------------Google Code 2010 -- Yannick Verdie--------------------//
40 
41 #include "precomp.hpp"
42 
43 #if defined(HAVE_QT)
44 
45 #include <memory>
46 
47 #include <window_QT.h>
48 
49 #include <math.h>
50 
51 #ifdef _WIN32
52 #include <windows.h>
53 #else
54 #include <unistd.h>
55 #endif
56 
57 #ifdef HAVE_QT_OPENGL
58     #ifdef Q_WS_X11
59         #include <GL/glx.h>
60     #endif
61 #endif
62 
63 
64 //Static and global first
65 static GuiReceiver *guiMainThread = NULL;
66 static int parameterSystemC = 1;
67 static char* parameterSystemV[] = {(char*)""};
68 static bool multiThreads = false;
69 static int last_key = -1;
70 QWaitCondition key_pressed;
71 QMutex mutexKey;
72 static const unsigned int threshold_zoom_img_region = 30;
73 //the minimum zoom value to start displaying the values in the grid
74 //that is also the number of pixel per grid
75 
76 static CvWinProperties* global_control_panel = NULL;
77 //end static and global
78 
79 // Declaration
80 Qt::ConnectionType autoBlockingConnection();
81 
82 // Implementation - this allows us to do blocking whilst automatically selecting the right
83 // behaviour for in-thread and out-of-thread launches of cv windows. Qt strangely doesn't
84 // cater for this, but does for strictly queued connections.
autoBlockingConnection()85 Qt::ConnectionType autoBlockingConnection() {
86   return (QThread::currentThread() != QApplication::instance()->thread())
87       ? Qt::BlockingQueuedConnection
88       : Qt::DirectConnection;
89 }
90 
cvFontQt(const char * nameFont,int pointSize,CvScalar color,int weight,int style,int spacing)91 CV_IMPL CvFont cvFontQt(const char* nameFont, int pointSize,CvScalar color,int weight,int style, int spacing)
92 {
93     /*
94     //nameFont   <- only Qt
95     //CvScalar color   <- only Qt (blue_component, green_component, red\_component[, alpha_component])
96     int         font_face;//<- style in Qt
97     const int*  ascii;
98     const int*  greek;
99     const int*  cyrillic;
100     float       hscale, vscale;
101     float       shear;
102     int         thickness;//<- weight in Qt
103     float       dx;//spacing letter in Qt (0 default) in pixel
104     int         line_type;//<- pointSize in Qt
105     */
106     CvFont f = {nameFont,color,style,NULL,NULL,NULL,0,0,0,weight,spacing,pointSize};
107     return f;
108 }
109 
110 
cvAddText(const CvArr * img,const char * text,CvPoint org,CvFont * font)111 CV_IMPL void cvAddText(const CvArr* img, const char* text, CvPoint org, CvFont* font)
112 {
113     if (!guiMainThread)
114         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
115 
116     QMetaObject::invokeMethod(guiMainThread,
117         "putText",
118         autoBlockingConnection(),
119         Q_ARG(void*, (void*) img),
120         Q_ARG(QString,QString::fromUtf8(text)),
121         Q_ARG(QPoint, QPoint(org.x,org.y)),
122         Q_ARG(void*,(void*) font));
123 }
124 
125 
cvGetRatioWindow_QT(const char * name)126 double cvGetRatioWindow_QT(const char* name)
127 {
128     if (!guiMainThread)
129         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
130 
131     double result = -1;
132     QMetaObject::invokeMethod(guiMainThread,
133         "getRatioWindow",
134         autoBlockingConnection(),
135         Q_RETURN_ARG(double, result),
136         Q_ARG(QString, QString(name)));
137 
138     return result;
139 }
140 
141 
cvSetRatioWindow_QT(const char * name,double prop_value)142 void cvSetRatioWindow_QT(const char* name,double prop_value)
143 {
144 
145     if (!guiMainThread)
146         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
147 
148     QMetaObject::invokeMethod(guiMainThread,
149         "setRatioWindow",
150         autoBlockingConnection(),
151         Q_ARG(QString, QString(name)),
152         Q_ARG(double, prop_value));
153 }
154 
155 
cvGetPropWindow_QT(const char * name)156 double cvGetPropWindow_QT(const char* name)
157 {
158     if (!guiMainThread)
159         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
160 
161     double result = -1;
162     QMetaObject::invokeMethod(guiMainThread,
163         "getPropWindow",
164         autoBlockingConnection(),
165         Q_RETURN_ARG(double, result),
166         Q_ARG(QString, QString(name)));
167 
168     return result;
169 }
170 
171 
cvSetPropWindow_QT(const char * name,double prop_value)172 void cvSetPropWindow_QT(const char* name,double prop_value)
173 {
174     if (!guiMainThread)
175         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
176 
177     QMetaObject::invokeMethod(guiMainThread,
178         "setPropWindow",
179         autoBlockingConnection(),
180         Q_ARG(QString, QString(name)),
181         Q_ARG(double, prop_value));
182 }
183 
setWindowTitle(const String & winname,const String & title)184 void cv::setWindowTitle(const String& winname, const String& title)
185 {
186     if (!guiMainThread)
187         CV_Error(Error::StsNullPtr, "NULL guiReceiver (please create a window)");
188 
189     QMetaObject::invokeMethod(guiMainThread,
190         "setWindowTitle",
191         autoBlockingConnection(),
192         Q_ARG(QString, QString(winname.c_str())),
193         Q_ARG(QString, QString(title.c_str())));
194 }
195 
196 
cvSetModeWindow_QT(const char * name,double prop_value)197 void cvSetModeWindow_QT(const char* name, double prop_value)
198 {
199     if (!guiMainThread)
200         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
201 
202     QMetaObject::invokeMethod(guiMainThread,
203         "toggleFullScreen",
204         autoBlockingConnection(),
205         Q_ARG(QString, QString(name)),
206         Q_ARG(double, prop_value));
207 }
208 
209 
cvGetModeWindow_QT(const char * name)210 double cvGetModeWindow_QT(const char* name)
211 {
212     if (!guiMainThread)
213         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
214 
215     double result = -1;
216 
217     QMetaObject::invokeMethod(guiMainThread,
218         "isFullScreen",
219         autoBlockingConnection(),
220         Q_RETURN_ARG(double, result),
221         Q_ARG(QString, QString(name)));
222 
223     return result;
224 }
225 
226 
cvDisplayOverlay(const char * name,const char * text,int delayms)227 CV_IMPL void cvDisplayOverlay(const char* name, const char* text, int delayms)
228 {
229     if (!guiMainThread)
230         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
231 
232     QMetaObject::invokeMethod(guiMainThread,
233         "displayInfo",
234         autoBlockingConnection(),
235         Q_ARG(QString, QString(name)),
236         Q_ARG(QString, QString(text)),
237         Q_ARG(int, delayms));
238 }
239 
240 
cvSaveWindowParameters(const char * name)241 CV_IMPL void cvSaveWindowParameters(const char* name)
242 {
243     if (!guiMainThread)
244         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
245 
246     QMetaObject::invokeMethod(guiMainThread,
247         "saveWindowParameters",
248         autoBlockingConnection(),
249         Q_ARG(QString, QString(name)));
250 }
251 
252 
cvLoadWindowParameters(const char * name)253 CV_IMPL void cvLoadWindowParameters(const char* name)
254 {
255     if (!guiMainThread)
256         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
257 
258     QMetaObject::invokeMethod(guiMainThread,
259         "loadWindowParameters",
260         autoBlockingConnection(),
261         Q_ARG(QString, QString(name)));
262 }
263 
264 
cvDisplayStatusBar(const char * name,const char * text,int delayms)265 CV_IMPL void cvDisplayStatusBar(const char* name, const char* text, int delayms)
266 {
267     if (!guiMainThread)
268         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
269 
270     QMetaObject::invokeMethod(guiMainThread,
271         "displayStatusBar",
272         autoBlockingConnection(),
273         Q_ARG(QString, QString(name)),
274         Q_ARG(QString, QString(text)),
275         Q_ARG(int, delayms));
276 }
277 
278 
cvWaitKey(int delay)279 CV_IMPL int cvWaitKey(int delay)
280 {
281     int result = -1;
282 
283     if (!guiMainThread)
284         return result;
285 
286     unsigned long delayms = delay <= 0 ? ULONG_MAX : delay; //in milliseconds
287 
288     if (multiThreads)
289     {
290         mutexKey.lock();
291         if (key_pressed.wait(&mutexKey, delayms)) //false if timeout
292         {
293             result = last_key;
294         }
295         last_key = -1;
296         mutexKey.unlock();
297     }
298     else
299     {
300         //cannot use wait here because events will not be distributed before processEvents (the main eventLoop is broken)
301         //so I create a Thread for the QTimer
302 
303         if (delay > 0)
304             guiMainThread->timer->start(delay);
305 
306         //QMutex dummy;
307 
308         while (!guiMainThread->bTimeOut)
309         {
310             qApp->processEvents(QEventLoop::AllEvents);
311 
312             if (!guiMainThread)//when all the windows are deleted
313                 return result;
314 
315             mutexKey.lock();
316             if (last_key != -1)
317             {
318                 result = last_key;
319                 last_key = -1;
320                 guiMainThread->timer->stop();
321                 //printf("keypressed\n");
322             }
323             mutexKey.unlock();
324 
325             if (result!=-1)
326             {
327                 break;
328             }
329             else
330             {
331                 /*
332     * //will not work, I broke the event loop !!!!
333     dummy.lock();
334     QWaitCondition waitCondition;
335     waitCondition.wait(&dummy, 2);
336     */
337 
338                 //to decrease CPU usage
339                 //sleep 1 millisecond
340 #if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
341                 Sleep(1);
342 #else
343                 usleep(1000);
344 #endif
345             }
346         }
347 
348         guiMainThread->bTimeOut = false;
349     }
350     return result;
351 }
352 
353 
354 //Yannick Verdie
355 //This function is experimental and some functions (such as cvSet/getWindowProperty will not work)
356 //We recommend not using this function for now
cvStartLoop(int (* pt2Func)(int argc,char * argv[]),int argc,char * argv[])357 CV_IMPL int cvStartLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[])
358 {
359     multiThreads = true;
360     QFuture<int> future = QtConcurrent::run(pt2Func, argc, argv);
361     return guiMainThread->start();
362 }
363 
364 
cvStopLoop()365 CV_IMPL void cvStopLoop()
366 {
367     qApp->exit();
368 }
369 
370 
icvFindWindowByName(QString name)371 static CvWindow* icvFindWindowByName(QString name)
372 {
373     CvWindow* window = 0;
374 
375     //This is not a very clean way to do the stuff. Indeed, QAction automatically generate toolTil (QLabel)
376     //that can be grabbed here and crash the code at 'w->param_name==name'.
377     foreach (QWidget* widget, QApplication::topLevelWidgets())
378     {
379         if (widget->isWindow() && !widget->parentWidget())//is a window without parent
380         {
381             CvWinModel* temp = (CvWinModel*) widget;
382 
383             if (temp->type == type_CvWindow)
384             {
385                 CvWindow* w = (CvWindow*) temp;
386                 if (w->objectName() == name)
387                 {
388                     window = w;
389                     break;
390                 }
391             }
392         }
393     }
394 
395     return window;
396 }
397 
398 
icvFindBarByName(QBoxLayout * layout,QString name_bar,typeBar type)399 static CvBar* icvFindBarByName(QBoxLayout* layout, QString name_bar, typeBar type)
400 {
401     if (!layout)
402         return NULL;
403 
404     int stop_index = layout->layout()->count();
405 
406     for (int i = 0; i < stop_index; ++i)
407     {
408         CvBar* t = (CvBar*) layout->layout()->itemAt(i);
409 
410         if (t->type == type && t->name_bar == name_bar)
411             return t;
412     }
413 
414     return NULL;
415 }
416 
417 
icvFindTrackBarByName(const char * name_trackbar,const char * name_window,QBoxLayout * layout=NULL)418 static CvTrackbar* icvFindTrackBarByName(const char* name_trackbar, const char* name_window, QBoxLayout* layout = NULL)
419 {
420     QString nameQt(name_trackbar);
421     QString nameWinQt(name_window);
422 
423     if (nameWinQt.isEmpty() && global_control_panel) //window name is null and we have a control panel
424         layout = global_control_panel->myLayout;
425 
426     if (!layout)
427     {
428         QPointer<CvWindow> w = icvFindWindowByName(nameWinQt);
429 
430         if (!w)
431             CV_Error(CV_StsNullPtr, "NULL window handler");
432 
433         if (w->param_gui_mode == CV_GUI_NORMAL)
434             return (CvTrackbar*) icvFindBarByName(w->myBarLayout, nameQt, type_CvTrackbar);
435 
436         if (w->param_gui_mode == CV_GUI_EXPANDED)
437         {
438             CvBar* result = icvFindBarByName(w->myBarLayout, nameQt, type_CvTrackbar);
439 
440             if (result)
441                 return (CvTrackbar*) result;
442 
443             return (CvTrackbar*) icvFindBarByName(global_control_panel->myLayout, nameQt, type_CvTrackbar);
444         }
445 
446         return NULL;
447     }
448     else
449     {
450         //layout was specified
451         return (CvTrackbar*) icvFindBarByName(layout, nameQt, type_CvTrackbar);
452     }
453 }
454 
455 /*
456 static CvButtonbar* icvFindButtonBarByName(const char* button_name, QBoxLayout* layout)
457 {
458     QString nameQt(button_name);
459     return (CvButtonbar*) icvFindBarByName(layout, nameQt, type_CvButtonbar);
460 }
461 */
462 
icvInitSystem(int * c,char ** v)463 static int icvInitSystem(int* c, char** v)
464 {
465     //"For any GUI application using Qt, there is precisely one QApplication object"
466     if (!QApplication::instance())
467     {
468         new QApplication(*c, v);
469         setlocale(LC_NUMERIC,"C");
470 
471         qDebug() << "init done";
472 
473 #ifdef HAVE_QT_OPENGL
474         qDebug() << "opengl support available";
475 #endif
476     }
477 
478     return 0;
479 }
480 
481 
cvInitSystem(int,char **)482 CV_IMPL int cvInitSystem(int, char**)
483 {
484     icvInitSystem(&parameterSystemC, parameterSystemV);
485     return 0;
486 }
487 
488 
cvNamedWindow(const char * name,int flags)489 CV_IMPL int cvNamedWindow(const char* name, int flags)
490 {
491     if (!guiMainThread)
492         guiMainThread = new GuiReceiver;
493     if (QThread::currentThread() != QApplication::instance()->thread()) {
494         multiThreads = true;
495         QMetaObject::invokeMethod(guiMainThread,
496         "createWindow",
497         Qt::BlockingQueuedConnection,  // block so that we can do useful stuff once we confirm it is created
498         Q_ARG(QString, QString(name)),
499         Q_ARG(int, flags));
500      } else {
501         guiMainThread->createWindow(QString(name), flags);
502      }
503 
504     return 1; //Dummy value - probably should return the result of the invocation.
505 }
506 
507 
cvDestroyWindow(const char * name)508 CV_IMPL void cvDestroyWindow(const char* name)
509 {
510     if (!guiMainThread)
511         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
512 
513     QMetaObject::invokeMethod(guiMainThread,
514         "destroyWindow",
515         Qt::AutoConnection,  // if another thread is controlling, let it handle it without blocking ourselves here
516         Q_ARG(QString, QString(name)));
517 }
518 
519 
cvDestroyAllWindows()520 CV_IMPL void cvDestroyAllWindows()
521 {
522     if (!guiMainThread)
523         return;
524     QMetaObject::invokeMethod(guiMainThread,
525         "destroyAllWindow",
526         Qt::AutoConnection  // if another thread is controlling, let it handle it without blocking ourselves here
527         );
528 }
529 
530 
cvGetWindowHandle(const char * name)531 CV_IMPL void* cvGetWindowHandle(const char* name)
532 {
533     if (!name)
534         CV_Error( CV_StsNullPtr, "NULL name string" );
535 
536     return (void*) icvFindWindowByName(QLatin1String(name));
537 }
538 
539 
cvGetWindowName(void * window_handle)540 CV_IMPL const char* cvGetWindowName(void* window_handle)
541 {
542     if( !window_handle )
543         CV_Error( CV_StsNullPtr, "NULL window handler" );
544 
545     return ((CvWindow*)window_handle)->objectName().toLatin1().data();
546 }
547 
548 
cvMoveWindow(const char * name,int x,int y)549 CV_IMPL void cvMoveWindow(const char* name, int x, int y)
550 {
551     if (!guiMainThread)
552         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
553     QMetaObject::invokeMethod(guiMainThread,
554         "moveWindow",
555         autoBlockingConnection(),
556         Q_ARG(QString, QString(name)),
557         Q_ARG(int, x),
558         Q_ARG(int, y));
559 }
560 
cvResizeWindow(const char * name,int width,int height)561 CV_IMPL void cvResizeWindow(const char* name, int width, int height)
562 {
563     if (!guiMainThread)
564         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
565     QMetaObject::invokeMethod(guiMainThread,
566         "resizeWindow",
567         autoBlockingConnection(),
568         Q_ARG(QString, QString(name)),
569         Q_ARG(int, width),
570         Q_ARG(int, height));
571 }
572 
573 
cvCreateTrackbar2(const char * name_bar,const char * window_name,int * val,int count,CvTrackbarCallback2 on_notify,void * userdata)574 CV_IMPL int cvCreateTrackbar2(const char* name_bar, const char* window_name, int* val, int count, CvTrackbarCallback2 on_notify, void* userdata)
575 {
576     if (!guiMainThread)
577         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
578 
579     QMetaObject::invokeMethod(guiMainThread,
580         "addSlider2",
581         autoBlockingConnection(),
582         Q_ARG(QString, QString(name_bar)),
583         Q_ARG(QString, QString(window_name)),
584         Q_ARG(void*, (void*)val),
585         Q_ARG(int, count),
586         Q_ARG(void*, (void*)on_notify),
587         Q_ARG(void*, (void*)userdata));
588 
589     return 1; //dummy value
590 }
591 
592 
cvStartWindowThread()593 CV_IMPL int cvStartWindowThread()
594 {
595     return 0;
596 }
597 
598 
cvCreateTrackbar(const char * name_bar,const char * window_name,int * value,int count,CvTrackbarCallback on_change)599 CV_IMPL int cvCreateTrackbar(const char* name_bar, const char* window_name, int* value, int count, CvTrackbarCallback on_change)
600 {
601     if (!guiMainThread)
602         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
603 
604     QMetaObject::invokeMethod(guiMainThread,
605         "addSlider",
606         autoBlockingConnection(),
607         Q_ARG(QString, QString(name_bar)),
608         Q_ARG(QString, QString(window_name)),
609         Q_ARG(void*, (void*)value),
610         Q_ARG(int, count),
611         Q_ARG(void*, (void*)on_change));
612 
613     return 1; //dummy value
614 }
615 
616 
cvCreateButton(const char * button_name,CvButtonCallback on_change,void * userdata,int button_type,int initial_button_state)617 CV_IMPL int cvCreateButton(const char* button_name, CvButtonCallback on_change, void* userdata, int button_type, int initial_button_state)
618 {
619     if (!guiMainThread)
620         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
621 
622     if (initial_button_state < 0 || initial_button_state > 1)
623         return 0;
624 
625     QMetaObject::invokeMethod(guiMainThread,
626         "addButton",
627         autoBlockingConnection(),
628         Q_ARG(QString, QString(button_name)),
629         Q_ARG(int,  button_type),
630         Q_ARG(int, initial_button_state),
631         Q_ARG(void*, (void*)on_change),
632         Q_ARG(void*, userdata));
633 
634     return 1;//dummy value
635 }
636 
637 
cvGetTrackbarPos(const char * name_bar,const char * window_name)638 CV_IMPL int cvGetTrackbarPos(const char* name_bar, const char* window_name)
639 {
640     int result = -1;
641 
642     QPointer<CvTrackbar> t = icvFindTrackBarByName(name_bar, window_name);
643 
644     if (t)
645         result = t->slider->value();
646 
647     return result;
648 }
649 
650 
cvSetTrackbarPos(const char * name_bar,const char * window_name,int pos)651 CV_IMPL void cvSetTrackbarPos(const char* name_bar, const char* window_name, int pos)
652 {
653     QPointer<CvTrackbar> t = icvFindTrackBarByName(name_bar, window_name);
654 
655     if (t)
656         t->slider->setValue(pos);
657 }
658 
659 
cvSetTrackbarMax(const char * name_bar,const char * window_name,int maxval)660 CV_IMPL void cvSetTrackbarMax(const char* name_bar, const char* window_name, int maxval)
661 {
662     if (maxval >= 0)
663     {
664         QPointer<CvTrackbar> t = icvFindTrackBarByName(name_bar, window_name);
665         if (t)
666         {
667             t->slider->setMaximum(maxval);
668         }
669     }
670 }
671 
672 
673 /* assign callback for mouse events */
cvSetMouseCallback(const char * window_name,CvMouseCallback on_mouse,void * param)674 CV_IMPL void cvSetMouseCallback(const char* window_name, CvMouseCallback on_mouse, void* param)
675 {
676     QPointer<CvWindow> w = icvFindWindowByName(QLatin1String(window_name));
677 
678     if (!w)
679         CV_Error(CV_StsNullPtr, "NULL window handler");
680 
681     w->setMouseCallBack(on_mouse, param);
682 
683 }
684 
685 
cvShowImage(const char * name,const CvArr * arr)686 CV_IMPL void cvShowImage(const char* name, const CvArr* arr)
687 {
688     if (!guiMainThread)
689         guiMainThread = new GuiReceiver;
690     if (QThread::currentThread() != QApplication::instance()->thread()) {
691         multiThreads = true;
692         QMetaObject::invokeMethod(guiMainThread,
693             "showImage",
694              autoBlockingConnection(),
695              Q_ARG(QString, QString(name)),
696              Q_ARG(void*, (void*)arr)
697         );
698      } else {
699         guiMainThread->showImage(QString(name), (void*)arr);
700      }
701 }
702 
703 
704 #ifdef HAVE_QT_OPENGL
705 
cvSetOpenGlDrawCallback(const char * window_name,CvOpenGlDrawCallback callback,void * userdata)706 CV_IMPL void cvSetOpenGlDrawCallback(const char* window_name, CvOpenGlDrawCallback callback, void* userdata)
707 {
708     if (!guiMainThread)
709         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
710 
711     QMetaObject::invokeMethod(guiMainThread,
712         "setOpenGlDrawCallback",
713         autoBlockingConnection(),
714         Q_ARG(QString, QString(window_name)),
715         Q_ARG(void*, (void*)callback),
716         Q_ARG(void*, userdata));
717 }
718 
719 
cvSetOpenGlContext(const char * window_name)720 CV_IMPL void cvSetOpenGlContext(const char* window_name)
721 {
722     if (!guiMainThread)
723         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
724 
725     QMetaObject::invokeMethod(guiMainThread,
726         "setOpenGlContext",
727         autoBlockingConnection(),
728         Q_ARG(QString, QString(window_name)));
729 }
730 
731 
cvUpdateWindow(const char * window_name)732 CV_IMPL void cvUpdateWindow(const char* window_name)
733 {
734     if (!guiMainThread)
735         CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
736 
737     QMetaObject::invokeMethod(guiMainThread,
738         "updateWindow",
739         autoBlockingConnection(),
740         Q_ARG(QString, QString(window_name)));
741 }
742 
743 #endif
744 
745 
cvGetOpenGlProp_QT(const char * name)746 double cvGetOpenGlProp_QT(const char* name)
747 {
748     double result = -1;
749 
750     if (guiMainThread)
751     {
752         QMetaObject::invokeMethod(guiMainThread,
753             "isOpenGl",
754             autoBlockingConnection(),
755             Q_RETURN_ARG(double, result),
756             Q_ARG(QString, QString(name)));
757     }
758 
759     return result;
760 }
761 
762 
763 //////////////////////////////////////////////////////
764 // GuiReceiver
765 
766 
GuiReceiver()767 GuiReceiver::GuiReceiver() : bTimeOut(false), nb_windows(0)
768 {
769     doesExternalQAppExist = (QApplication::instance() != 0);
770     icvInitSystem(&parameterSystemC, parameterSystemV);
771 
772     timer = new QTimer(this);
773     QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timeOut()));
774     timer->setSingleShot(true);
775     if ( doesExternalQAppExist ) {
776         moveToThread(QApplication::instance()->thread());
777     }
778 }
779 
780 
isLastWindow()781 void GuiReceiver::isLastWindow()
782 {
783     if (--nb_windows <= 0)
784     {
785         delete guiMainThread;//delete global_control_panel too
786         guiMainThread = NULL;
787 
788         if (!doesExternalQAppExist)
789         {
790             qApp->quit();
791         }
792     }
793 }
794 
795 
~GuiReceiver()796 GuiReceiver::~GuiReceiver()
797 {
798     if (global_control_panel)
799     {
800         delete global_control_panel;
801         global_control_panel = NULL;
802     }
803 }
804 
805 
putText(void * arr,QString text,QPoint org,void * arg2)806 void GuiReceiver::putText(void* arr, QString text, QPoint org, void* arg2)
807 {
808     CV_Assert(arr);
809 
810     CvMat* mat, stub;
811     mat = cvGetMat(arr, &stub);
812 
813     int nbChannelOriginImage = cvGetElemType(mat);
814     if (nbChannelOriginImage != CV_8UC3) return; //for now, font works only with 8UC3
815 
816     QImage qimg(mat->data.ptr, mat->cols, mat->rows, mat->step, QImage::Format_RGB888);
817 
818     CvFont* font = (CvFont*)arg2;
819 
820     QPainter qp(&qimg);
821     if (font)
822     {
823         QFont f(font->nameFont, font->line_type/*PointSize*/, font->thickness/*weight*/);
824         f.setStyle((QFont::Style) font->font_face/*style*/);
825         f.setLetterSpacing(QFont::AbsoluteSpacing, font->dx/*spacing*/);
826         //cvScalar(blue_component, green_component, red_component[, alpha_component])
827         //Qt map non-transparent to 0xFF and transparent to 0
828         //OpenCV scalar is the reverse, so 255-font->color.val[3]
829         qp.setPen(QColor(font->color.val[2], font->color.val[1], font->color.val[0], 255 - font->color.val[3]));
830         qp.setFont(f);
831     }
832     qp.drawText(org, text);
833     qp.end();
834 }
835 
836 
saveWindowParameters(QString name)837 void GuiReceiver::saveWindowParameters(QString name)
838 {
839     QPointer<CvWindow> w = icvFindWindowByName(name);
840 
841     if (w)
842         w->writeSettings();
843 }
844 
845 
loadWindowParameters(QString name)846 void GuiReceiver::loadWindowParameters(QString name)
847 {
848     QPointer<CvWindow> w = icvFindWindowByName(name);
849 
850     if (w)
851         w->readSettings();
852 }
853 
854 
getRatioWindow(QString name)855 double GuiReceiver::getRatioWindow(QString name)
856 {
857     QPointer<CvWindow> w = icvFindWindowByName(name);
858 
859     if (!w)
860         return -1;
861 
862     return w->getRatio();
863 }
864 
865 
setRatioWindow(QString name,double arg2)866 void GuiReceiver::setRatioWindow(QString name, double arg2)
867 {
868     QPointer<CvWindow> w = icvFindWindowByName( name.toLatin1().data() );
869 
870     if (!w)
871         return;
872 
873     int flags = (int) arg2;
874 
875     w->setRatio(flags);
876 }
877 
878 
getPropWindow(QString name)879 double GuiReceiver::getPropWindow(QString name)
880 {
881     QPointer<CvWindow> w = icvFindWindowByName(name);
882 
883     if (!w)
884         return -1;
885 
886     return (double) w->getPropWindow();
887 }
888 
889 
setPropWindow(QString name,double arg2)890 void GuiReceiver::setPropWindow(QString name, double arg2)
891 {
892     QPointer<CvWindow> w = icvFindWindowByName(name);
893 
894     if (!w)
895         return;
896 
897     int flags = (int) arg2;
898 
899     w->setPropWindow(flags);
900 }
901 
setWindowTitle(QString name,QString title)902 void GuiReceiver::setWindowTitle(QString name, QString title)
903 {
904     QPointer<CvWindow> w = icvFindWindowByName(name);
905 
906     if (!w)
907     {
908         cvNamedWindow(name.toLatin1().data());
909         w = icvFindWindowByName(name);
910     }
911 
912     if (!w)
913         return;
914 
915     w->setWindowTitle(title);
916 }
917 
918 
isFullScreen(QString name)919 double GuiReceiver::isFullScreen(QString name)
920 {
921     QPointer<CvWindow> w = icvFindWindowByName(name);
922 
923     if (!w)
924         return -1;
925 
926     return w->isFullScreen() ? CV_WINDOW_FULLSCREEN : CV_WINDOW_NORMAL;
927 }
928 
929 
toggleFullScreen(QString name,double arg2)930 void GuiReceiver::toggleFullScreen(QString name, double arg2)
931 {
932     QPointer<CvWindow> w = icvFindWindowByName(name);
933 
934     if (!w)
935         return;
936 
937     int flags = (int) arg2;
938 
939     w->toggleFullScreen(flags);
940 }
941 
942 
createWindow(QString name,int flags)943 void GuiReceiver::createWindow(QString name, int flags)
944 {
945     if (!qApp)
946         CV_Error(CV_StsNullPtr, "NULL session handler" );
947 
948     // Check the name in the storage
949     if (icvFindWindowByName(name.toLatin1().data()))
950     {
951         return;
952     }
953 
954     nb_windows++;
955     new CvWindow(name, flags);
956 }
957 
958 
timeOut()959 void GuiReceiver::timeOut()
960 {
961     bTimeOut = true;
962 }
963 
964 
displayInfo(QString name,QString text,int delayms)965 void GuiReceiver::displayInfo(QString name, QString text, int delayms)
966 {
967     QPointer<CvWindow> w = icvFindWindowByName(name);
968 
969     if (w)
970         w->displayInfo(text, delayms);
971 }
972 
973 
displayStatusBar(QString name,QString text,int delayms)974 void GuiReceiver::displayStatusBar(QString name, QString text, int delayms)
975 {
976     QPointer<CvWindow> w = icvFindWindowByName(name);
977 
978     if (w)
979         w->displayStatusBar(text, delayms);
980 }
981 
982 
showImage(QString name,void * arr)983 void GuiReceiver::showImage(QString name, void* arr)
984 {
985     QPointer<CvWindow> w = icvFindWindowByName(name);
986 
987     if (!w) //as observed in the previous implementation (W32, GTK or Carbon), create a new window is the pointer returned is null
988     {
989         cvNamedWindow(name.toLatin1().data());
990         w = icvFindWindowByName(name);
991     }
992 
993     if (!w || !arr)
994         return; // keep silence here.
995 
996     if (w->isOpenGl())
997     {
998         CvMat* mat, stub;
999 
1000         mat = cvGetMat(arr, &stub);
1001 
1002         cv::Mat im = cv::cvarrToMat(mat);
1003         cv::imshow(name.toUtf8().data(), im);
1004     }
1005     else
1006     {
1007         w->updateImage(arr);
1008     }
1009 
1010     if (w->isHidden())
1011         w->show();
1012 }
1013 
1014 
destroyWindow(QString name)1015 void GuiReceiver::destroyWindow(QString name)
1016 {
1017 
1018     QPointer<CvWindow> w = icvFindWindowByName(name);
1019 
1020     if (w)
1021     {
1022         w->close();
1023 
1024         //in not-multiThreads mode, looks like the window is hidden but not deleted
1025         //so I do it manually
1026         //otherwise QApplication do it for me if the exec command was executed (in multiThread mode)
1027         if (!multiThreads)
1028             delete w;
1029     }
1030 }
1031 
1032 
destroyAllWindow()1033 void GuiReceiver::destroyAllWindow()
1034 {
1035     if (!qApp)
1036         CV_Error(CV_StsNullPtr, "NULL session handler" );
1037 
1038     if (multiThreads)
1039     {
1040         // WARNING: this could even close windows from an external parent app
1041         //#TODO check externalQAppExists and in case it does, close windows carefully,
1042         //      i.e. apply the className-check from below...
1043         qApp->closeAllWindows();
1044     }
1045     else
1046     {
1047         bool isWidgetDeleted = true;
1048         while(isWidgetDeleted)
1049         {
1050             isWidgetDeleted = false;
1051             QWidgetList list = QApplication::topLevelWidgets();
1052             for (int i = 0; i < list.count(); i++)
1053             {
1054                 QObject *obj = list.at(i);
1055                 if (obj->metaObject()->className() == QString("CvWindow"))
1056                 {
1057                     delete obj;
1058                     isWidgetDeleted = true;
1059                     break;
1060                 }
1061             }
1062         }
1063     }
1064 }
1065 
1066 
moveWindow(QString name,int x,int y)1067 void GuiReceiver::moveWindow(QString name, int x, int y)
1068 {
1069     QPointer<CvWindow> w = icvFindWindowByName(name);
1070 
1071     if (w)
1072         w->move(x, y);
1073 }
1074 
1075 
resizeWindow(QString name,int width,int height)1076 void GuiReceiver::resizeWindow(QString name, int width, int height)
1077 {
1078     QPointer<CvWindow> w = icvFindWindowByName(name);
1079 
1080     if (w)
1081     {
1082         w->showNormal();
1083         w->setViewportSize(QSize(width, height));
1084     }
1085 }
1086 
1087 
enablePropertiesButtonEachWindow()1088 void GuiReceiver::enablePropertiesButtonEachWindow()
1089 {
1090     //For each window, enable window property button
1091     foreach (QWidget* widget, QApplication::topLevelWidgets())
1092     {
1093         if (widget->isWindow() && !widget->parentWidget()) //is a window without parent
1094         {
1095             CvWinModel* temp = (CvWinModel*) widget;
1096             if (temp->type == type_CvWindow)
1097             {
1098                 CvWindow* w = (CvWindow*) widget;
1099 
1100                 //active window properties button
1101                 w->enablePropertiesButton();
1102             }
1103         }
1104     }
1105 }
1106 
1107 
addButton(QString button_name,int button_type,int initial_button_state,void * on_change,void * userdata)1108 void GuiReceiver::addButton(QString button_name, int button_type, int initial_button_state, void* on_change, void* userdata)
1109 {
1110     if (!global_control_panel)
1111         return;
1112 
1113     QPointer<CvButtonbar> b;
1114 
1115     if (global_control_panel->myLayout->count() == 0) //if that is the first button attach to the control panel, create a new button bar
1116     {
1117         b = CvWindow::createButtonBar(button_name); //the bar has the name of the first button attached to it
1118         enablePropertiesButtonEachWindow();
1119 
1120     }
1121     else
1122     {
1123         CvBar* lastbar = (CvBar*) global_control_panel->myLayout->itemAt(global_control_panel->myLayout->count() - 1);
1124 
1125         if (lastbar->type == type_CvTrackbar) //if last bar is a trackbar, create a new buttonbar, else, attach to the current bar
1126             b = CvWindow::createButtonBar(button_name); //the bar has the name of the first button attached to it
1127         else
1128             b = (CvButtonbar*) lastbar;
1129 
1130     }
1131 
1132     b->addButton(button_name, (CvButtonCallback) on_change, userdata, button_type, initial_button_state);
1133 }
1134 
1135 
addSlider2(QString bar_name,QString window_name,void * value,int count,void * on_change,void * userdata)1136 void GuiReceiver::addSlider2(QString bar_name, QString window_name, void* value, int count, void* on_change, void *userdata)
1137 {
1138     QBoxLayout *layout = NULL;
1139     QPointer<CvWindow> w;
1140 
1141     if (!window_name.isEmpty())
1142     {
1143         w = icvFindWindowByName(window_name);
1144 
1145         if (!w)
1146             return;
1147     }
1148     else
1149     {
1150         if (global_control_panel)
1151             layout = global_control_panel->myLayout;
1152     }
1153 
1154     QPointer<CvTrackbar> t = icvFindTrackBarByName(bar_name.toLatin1().data(), window_name.toLatin1().data(), layout);
1155 
1156     if (t) //trackbar exists
1157         return;
1158 
1159     if (!value)
1160         CV_Error(CV_StsNullPtr, "NULL value pointer" );
1161 
1162     if (count <= 0) //count is the max value of the slider, so must be bigger than 0
1163         CV_Error(CV_StsNullPtr, "Max value of the slider must be bigger than 0" );
1164 
1165     CvWindow::addSlider2(w, bar_name, (int*)value, count, (CvTrackbarCallback2) on_change, userdata);
1166 }
1167 
1168 
addSlider(QString bar_name,QString window_name,void * value,int count,void * on_change)1169 void GuiReceiver::addSlider(QString bar_name, QString window_name, void* value, int count, void* on_change)
1170 {
1171     QBoxLayout *layout = NULL;
1172     QPointer<CvWindow> w;
1173 
1174     if (!window_name.isEmpty())
1175     {
1176         w = icvFindWindowByName(window_name);
1177 
1178         if (!w)
1179             return;
1180     }
1181     else
1182     {
1183         if (global_control_panel)
1184             layout = global_control_panel->myLayout;
1185     }
1186 
1187     QPointer<CvTrackbar> t = icvFindTrackBarByName(bar_name.toLatin1().data(), window_name.toLatin1().data(), layout);
1188 
1189     if (t) //trackbar exists
1190         return;
1191 
1192     if (!value)
1193         CV_Error(CV_StsNullPtr, "NULL value pointer" );
1194 
1195     if (count <= 0) //count is the max value of the slider, so must be bigger than 0
1196         CV_Error(CV_StsNullPtr, "Max value of the slider must be bigger than 0" );
1197 
1198     CvWindow::addSlider(w, bar_name, (int*)value, count, (CvTrackbarCallback) on_change);
1199 }
1200 
1201 
start()1202 int GuiReceiver::start()
1203 {
1204     return qApp->exec();
1205 }
1206 
1207 
setOpenGlDrawCallback(QString name,void * callback,void * userdata)1208 void GuiReceiver::setOpenGlDrawCallback(QString name, void* callback, void* userdata)
1209 {
1210     QPointer<CvWindow> w = icvFindWindowByName(name);
1211 
1212     if (w)
1213         w->setOpenGlDrawCallback((CvOpenGlDrawCallback) callback, userdata);
1214 }
1215 
setOpenGlContext(QString name)1216 void GuiReceiver::setOpenGlContext(QString name)
1217 {
1218     QPointer<CvWindow> w = icvFindWindowByName(name);
1219 
1220     if (w)
1221         w->makeCurrentOpenGlContext();
1222 }
1223 
updateWindow(QString name)1224 void GuiReceiver::updateWindow(QString name)
1225 {
1226     QPointer<CvWindow> w = icvFindWindowByName(name);
1227 
1228     if (w)
1229         w->updateGl();
1230 }
1231 
isOpenGl(QString name)1232 double GuiReceiver::isOpenGl(QString name)
1233 {
1234     double result = -1;
1235 
1236     QPointer<CvWindow> w = icvFindWindowByName(name);
1237 
1238     if (w)
1239         result = (double) w->isOpenGl();
1240 
1241     return result;
1242 }
1243 
1244 
1245 //////////////////////////////////////////////////////
1246 // CvTrackbar
1247 
1248 
CvTrackbar(CvWindow * arg,QString name,int * value,int _count,CvTrackbarCallback2 on_change,void * data)1249 CvTrackbar::CvTrackbar(CvWindow* arg, QString name, int* value, int _count, CvTrackbarCallback2 on_change, void* data)
1250 {
1251     callback = NULL;
1252     callback2 = on_change;
1253     userdata = data;
1254 
1255     create(arg, name, value, _count);
1256 }
1257 
1258 
CvTrackbar(CvWindow * arg,QString name,int * value,int _count,CvTrackbarCallback on_change)1259 CvTrackbar::CvTrackbar(CvWindow* arg, QString name, int* value, int _count, CvTrackbarCallback on_change)
1260 {
1261     callback = on_change;
1262     callback2 = NULL;
1263     userdata = NULL;
1264 
1265     create(arg, name, value, _count);
1266 }
1267 
1268 
create(CvWindow * arg,QString name,int * value,int _count)1269 void CvTrackbar::create(CvWindow* arg, QString name, int* value, int _count)
1270 {
1271     type = type_CvTrackbar;
1272     myparent = arg;
1273     name_bar = name;
1274     setObjectName(name_bar);
1275     dataSlider = value;
1276 
1277     slider = new QSlider(Qt::Horizontal);
1278     slider->setFocusPolicy(Qt::StrongFocus);
1279     slider->setMinimum(0);
1280     slider->setMaximum(_count);
1281     slider->setPageStep(5);
1282     slider->setValue(*value);
1283     slider->setTickPosition(QSlider::TicksBelow);
1284 
1285 
1286     //Change style of the Slider
1287     //slider->setStyleSheet(str_Trackbar_css);
1288 
1289     QFile qss(":/stylesheet-trackbar");
1290     if (qss.open(QFile::ReadOnly))
1291     {
1292         slider->setStyleSheet(QLatin1String(qss.readAll()));
1293         qss.close();
1294     }
1295 
1296 
1297     //this next line does not work if we change the style with a stylesheet, why ? (bug in QT ?)
1298     //slider->setTickPosition(QSlider::TicksBelow);
1299     label = new QPushButton;
1300     label->setFlat(true);
1301     setLabel(slider->value());
1302 
1303 
1304     QObject::connect(slider, SIGNAL(valueChanged(int)), this, SLOT(update(int)));
1305 
1306     QObject::connect(label, SIGNAL(clicked()), this, SLOT(createDialog()));
1307 
1308     //label->setStyleSheet("QPushButton:disabled {color: black}");
1309 
1310     addWidget(label, Qt::AlignLeft);//name + value
1311     addWidget(slider, Qt::AlignCenter);//slider
1312 }
1313 
1314 
createDialog()1315 void CvTrackbar::createDialog()
1316 {
1317     bool ok = false;
1318 
1319     //crash if I access the values directly and give them to QInputDialog, so do a copy first.
1320     int value = slider->value();
1321     int step = slider->singleStep();
1322     int min = slider->minimum();
1323     int max = slider->maximum();
1324 
1325     int i =
1326 #if QT_VERSION >= 0x040500
1327         QInputDialog::getInt
1328 #else
1329         QInputDialog::getInteger
1330 #endif
1331         (this->parentWidget(),
1332         tr("Slider %1").arg(name_bar),
1333         tr("New value:"),
1334         value,
1335         min,
1336         max,
1337         step,
1338         &ok);
1339 
1340     if (ok)
1341         slider->setValue(i);
1342 }
1343 
1344 
update(int myvalue)1345 void CvTrackbar::update(int myvalue)
1346 {
1347     setLabel(myvalue);
1348 
1349     *dataSlider = myvalue;
1350     if (callback)
1351     {
1352         callback(myvalue);
1353         return;
1354     }
1355 
1356     if (callback2)
1357     {
1358         callback2(myvalue, userdata);
1359         return;
1360     }
1361 }
1362 
1363 
setLabel(int myvalue)1364 void CvTrackbar::setLabel(int myvalue)
1365 {
1366     QString nameNormalized = name_bar.leftJustified( 10, ' ', true );
1367     QString valueMaximum = QString("%1").arg(slider->maximum());
1368     QString str = QString("%1 (%2/%3)").arg(nameNormalized).arg(myvalue,valueMaximum.length(),10,QChar('0')).arg(valueMaximum);
1369     label->setText(str);
1370 }
1371 
1372 
1373 //////////////////////////////////////////////////////
1374 // CvButtonbar
1375 
1376 
1377 //here CvButtonbar class
CvButtonbar(QWidget * arg,QString arg2)1378 CvButtonbar::CvButtonbar(QWidget* arg,  QString arg2)
1379 {
1380     type = type_CvButtonbar;
1381     myparent = arg;
1382     name_bar = arg2;
1383     setObjectName(name_bar);
1384 
1385     group_button = new QButtonGroup(this);
1386 }
1387 
1388 
setLabel()1389 void CvButtonbar::setLabel()
1390 {
1391     QString nameNormalized = name_bar.leftJustified(10, ' ', true);
1392     label->setText(nameNormalized);
1393 }
1394 
1395 
addButton(QString name,CvButtonCallback call,void * userdata,int button_type,int initial_button_state)1396 void CvButtonbar::addButton(QString name, CvButtonCallback call, void* userdata,  int button_type, int initial_button_state)
1397 {
1398     QString button_name = name;
1399 
1400     if (button_name == "")
1401         button_name = tr("button %1").arg(this->count());
1402 
1403     QPointer<QAbstractButton> button;
1404 
1405     if (button_type == CV_PUSH_BUTTON)
1406         button = (QAbstractButton*) new CvPushButton(this, button_name,call, userdata);
1407 
1408     if (button_type == CV_CHECKBOX)
1409         button = (QAbstractButton*) new CvCheckBox(this, button_name,call, userdata, initial_button_state);
1410 
1411     if (button_type == CV_RADIOBOX)
1412     {
1413         button = (QAbstractButton*) new CvRadioButton(this, button_name,call, userdata, initial_button_state);
1414         group_button->addButton(button);
1415     }
1416 
1417     if (button)
1418     {
1419         if (button_type == CV_PUSH_BUTTON)
1420             QObject::connect(button, SIGNAL(clicked(bool)), button, SLOT(callCallBack(bool)));
1421         else
1422             QObject::connect(button, SIGNAL(toggled(bool)), button, SLOT(callCallBack(bool)));
1423 
1424         addWidget(button, Qt::AlignCenter);
1425     }
1426 }
1427 
1428 
1429 //////////////////////////////////////////////////////
1430 // Buttons
1431 
1432 
1433 //buttons here
CvPushButton(CvButtonbar * arg1,QString arg2,CvButtonCallback arg3,void * arg4)1434 CvPushButton::CvPushButton(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, void* arg4)
1435 {
1436     myparent = arg1;
1437     button_name = arg2;
1438     callback = arg3;
1439     userdata = arg4;
1440 
1441     setObjectName(button_name);
1442     setText(button_name);
1443 
1444     if (isChecked())
1445         callCallBack(true);
1446 }
1447 
1448 
callCallBack(bool checked)1449 void CvPushButton::callCallBack(bool checked)
1450 {
1451     if (callback)
1452         callback(checked, userdata);
1453 }
1454 
1455 
CvCheckBox(CvButtonbar * arg1,QString arg2,CvButtonCallback arg3,void * arg4,int initial_button_state)1456 CvCheckBox::CvCheckBox(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, void* arg4, int initial_button_state)
1457 {
1458     myparent = arg1;
1459     button_name = arg2;
1460     callback = arg3;
1461     userdata = arg4;
1462 
1463     setObjectName(button_name);
1464     setCheckState((initial_button_state == 1 ? Qt::Checked : Qt::Unchecked));
1465     setText(button_name);
1466 
1467     if (isChecked())
1468         callCallBack(true);
1469 }
1470 
1471 
callCallBack(bool checked)1472 void CvCheckBox::callCallBack(bool checked)
1473 {
1474     if (callback)
1475         callback(checked, userdata);
1476 }
1477 
1478 
CvRadioButton(CvButtonbar * arg1,QString arg2,CvButtonCallback arg3,void * arg4,int initial_button_state)1479 CvRadioButton::CvRadioButton(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, void* arg4, int initial_button_state)
1480 {
1481     myparent = arg1;
1482     button_name = arg2;
1483     callback = arg3;
1484     userdata = arg4;
1485 
1486     setObjectName(button_name);
1487     setChecked(initial_button_state);
1488     setText(button_name);
1489 
1490     if (isChecked())
1491         callCallBack(true);
1492 }
1493 
callCallBack(bool checked)1494 void CvRadioButton::callCallBack(bool checked)
1495 {
1496     if (callback)
1497         callback(checked, userdata);
1498 }
1499 
1500 
1501 //////////////////////////////////////////////////////
1502 // CvWinProperties
1503 
1504 
1505 //here CvWinProperties class
CvWinProperties(QString name_paraWindow,QObject *)1506 CvWinProperties::CvWinProperties(QString name_paraWindow, QObject* /*parent*/)
1507 {
1508     //setParent(parent);
1509     type = type_CvWinProperties;
1510     setWindowFlags(Qt::Tool);
1511     setContentsMargins(0, 0, 0, 0);
1512     setWindowTitle(name_paraWindow);
1513     setObjectName(name_paraWindow);
1514     resize(100, 50);
1515 
1516     myLayout = new QBoxLayout(QBoxLayout::TopToBottom);
1517     myLayout->setObjectName(QString::fromUtf8("boxLayout"));
1518     myLayout->setContentsMargins(0, 0, 0, 0);
1519     myLayout->setSpacing(0);
1520     myLayout->setMargin(0);
1521     myLayout->setSizeConstraint(QLayout::SetFixedSize);
1522     setLayout(myLayout);
1523 
1524     hide();
1525 }
1526 
1527 
closeEvent(QCloseEvent * e)1528 void CvWinProperties::closeEvent(QCloseEvent* e)
1529 {
1530     e->accept(); //intersept the close event (not sure I really need it)
1531     //an hide event is also sent. I will intercept it and do some processing
1532 }
1533 
1534 
showEvent(QShowEvent * evnt)1535 void CvWinProperties::showEvent(QShowEvent* evnt)
1536 {
1537     //why -1,-1 ?: do this trick because the first time the code is run,
1538     //no value pos was saved so we let Qt move the window in the middle of its parent (event ignored).
1539     //then hide will save the last position and thus, we want to retreive it (event accepted).
1540     QPoint mypos(-1, -1);
1541     QSettings settings("OpenCV2", objectName());
1542     mypos = settings.value("pos", mypos).toPoint();
1543 
1544     if (mypos.x() >= 0)
1545     {
1546         move(mypos);
1547         evnt->accept();
1548     }
1549     else
1550     {
1551         evnt->ignore();
1552     }
1553 }
1554 
1555 
hideEvent(QHideEvent * evnt)1556 void CvWinProperties::hideEvent(QHideEvent* evnt)
1557 {
1558     QSettings settings("OpenCV2", objectName());
1559     settings.setValue("pos", pos()); //there is an offset of 6 pixels (so the window's position is wrong -- why ?)
1560     evnt->accept();
1561 }
1562 
1563 
~CvWinProperties()1564 CvWinProperties::~CvWinProperties()
1565 {
1566     //clear the setting pos
1567     QSettings settings("OpenCV2", objectName());
1568     settings.remove("pos");
1569 }
1570 
1571 
1572 //////////////////////////////////////////////////////
1573 // CvWindow
1574 
1575 
CvWindow(QString name,int arg2)1576 CvWindow::CvWindow(QString name, int arg2)
1577 {
1578     type = type_CvWindow;
1579 
1580     param_flags = arg2 & 0x0000000F;
1581     param_gui_mode = arg2 & 0x000000F0;
1582     param_ratio_mode =  arg2 & 0x00000F00;
1583 
1584     //setAttribute(Qt::WA_DeleteOnClose); //in other case, does not release memory
1585     setContentsMargins(0, 0, 0, 0);
1586     setWindowTitle(name);
1587     setObjectName(name);
1588 
1589     setFocus( Qt::PopupFocusReason ); //#1695 arrow keys are not received without the explicit focus
1590 
1591     resize(400, 300);
1592     setMinimumSize(1, 1);
1593 
1594     //1: create control panel
1595     if (!global_control_panel)
1596         global_control_panel = createParameterWindow();
1597 
1598     //2: Layouts
1599     createBarLayout();
1600     createGlobalLayout();
1601 
1602     //3: my view
1603 #ifndef HAVE_QT_OPENGL
1604     if (arg2 & CV_WINDOW_OPENGL)
1605         CV_Error( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
1606     mode_display = CV_MODE_NORMAL;
1607 #else
1608     mode_display = arg2 & CV_WINDOW_OPENGL ? CV_MODE_OPENGL : CV_MODE_NORMAL;
1609     if (mode_display == CV_MODE_OPENGL)
1610         param_gui_mode = CV_GUI_NORMAL;
1611 #endif
1612     createView();
1613 
1614     //4: shortcuts and actions
1615     //5: toolBar and statusbar
1616     if (param_gui_mode == CV_GUI_EXPANDED)
1617     {
1618         createActions();
1619         createShortcuts();
1620 
1621         createToolBar();
1622         createStatusBar();
1623     }
1624 
1625     //Now attach everything
1626     if (myToolBar)
1627         myGlobalLayout->addWidget(myToolBar, Qt::AlignCenter);
1628 
1629     myGlobalLayout->addWidget(myView->getWidget(), Qt::AlignCenter);
1630 
1631     myGlobalLayout->addLayout(myBarLayout, Qt::AlignCenter);
1632 
1633     if (myStatusBar)
1634         myGlobalLayout->addWidget(myStatusBar, Qt::AlignCenter);
1635 
1636     setLayout(myGlobalLayout);
1637     show();
1638 }
1639 
1640 
~CvWindow()1641 CvWindow::~CvWindow()
1642 {
1643     if (guiMainThread)
1644         guiMainThread->isLastWindow();
1645 }
1646 
1647 
setMouseCallBack(CvMouseCallback callback,void * param)1648 void CvWindow::setMouseCallBack(CvMouseCallback callback, void* param)
1649 {
1650     myView->setMouseCallBack(callback, param);
1651 }
1652 
1653 
writeSettings()1654 void CvWindow::writeSettings()
1655 {
1656     //organisation and application's name
1657     QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName());
1658 
1659     settings.setValue("pos", pos());
1660     settings.setValue("size", size());
1661     settings.setValue("mode_resize" ,param_flags);
1662     settings.setValue("mode_gui", param_gui_mode);
1663 
1664     myView->writeSettings(settings);
1665 
1666     icvSaveTrackbars(&settings);
1667 
1668     if (global_control_panel)
1669     {
1670         icvSaveControlPanel();
1671         settings.setValue("posPanel", global_control_panel->pos());
1672     }
1673 }
1674 
1675 
1676 
1677 //TODO: load CV_GUI flag (done) and act accordingly (create win property if needed and attach trackbars)
readSettings()1678 void CvWindow::readSettings()
1679 {
1680     //organisation and application's name
1681     QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName());
1682 
1683     QPoint _pos = settings.value("pos", QPoint(200, 200)).toPoint();
1684     QSize _size = settings.value("size", QSize(400, 400)).toSize();
1685 
1686     param_flags = settings.value("mode_resize", param_flags).toInt();
1687     param_gui_mode = settings.value("mode_gui", param_gui_mode).toInt();
1688 
1689     param_flags = settings.value("mode_resize", param_flags).toInt();
1690 
1691     myView->readSettings(settings);
1692 
1693     //trackbar here
1694     icvLoadTrackbars(&settings);
1695 
1696     resize(_size);
1697     move(_pos);
1698 
1699     if (global_control_panel)
1700     {
1701         icvLoadControlPanel();
1702         global_control_panel->move(settings.value("posPanel", global_control_panel->pos()).toPoint());
1703     }
1704 }
1705 
1706 
getRatio()1707 double CvWindow::getRatio()
1708 {
1709     return myView->getRatio();
1710 }
1711 
1712 
setRatio(int flags)1713 void CvWindow::setRatio(int flags)
1714 {
1715     myView->setRatio(flags);
1716 }
1717 
1718 
getPropWindow()1719 int CvWindow::getPropWindow()
1720 {
1721     return param_flags;
1722 }
1723 
1724 
setPropWindow(int flags)1725 void CvWindow::setPropWindow(int flags)
1726 {
1727     if (param_flags == flags) //nothing to do
1728         return;
1729 
1730     switch(flags)
1731     {
1732     case CV_WINDOW_NORMAL:
1733         myGlobalLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
1734         param_flags = flags;
1735 
1736         break;
1737 
1738     case CV_WINDOW_AUTOSIZE:
1739         myGlobalLayout->setSizeConstraint(QLayout::SetFixedSize);
1740         param_flags = flags;
1741 
1742         break;
1743 
1744     default:
1745         ;
1746     }
1747 }
1748 
toggleFullScreen(int flags)1749 void CvWindow::toggleFullScreen(int flags)
1750 {
1751     if (isFullScreen() && flags == CV_WINDOW_NORMAL)
1752     {
1753         showTools();
1754         showNormal();
1755         return;
1756     }
1757 
1758     if (!isFullScreen() && flags == CV_WINDOW_FULLSCREEN)
1759     {
1760         hideTools();
1761         showFullScreen();
1762         return;
1763     }
1764 }
1765 
1766 
updateImage(void * arr)1767 void CvWindow::updateImage(void* arr)
1768 {
1769     myView->updateImage(arr);
1770 }
1771 
1772 
displayInfo(QString text,int delayms)1773 void CvWindow::displayInfo(QString text, int delayms)
1774 {
1775     myView->startDisplayInfo(text, delayms);
1776 }
1777 
1778 
displayStatusBar(QString text,int delayms)1779 void CvWindow::displayStatusBar(QString text, int delayms)
1780 {
1781     if (myStatusBar)
1782         myStatusBar->showMessage(text, delayms);
1783 }
1784 
1785 
enablePropertiesButton()1786 void CvWindow::enablePropertiesButton()
1787 {
1788     if (!vect_QActions.empty())
1789         vect_QActions[9]->setDisabled(false);
1790 }
1791 
1792 
createButtonBar(QString name_bar)1793 CvButtonbar* CvWindow::createButtonBar(QString name_bar)
1794 {
1795     QPointer<CvButtonbar> t = new CvButtonbar(global_control_panel, name_bar);
1796     t->setAlignment(Qt::AlignHCenter);
1797 
1798     QPointer<QBoxLayout> myLayout = global_control_panel->myLayout;
1799 
1800     myLayout->insertLayout(myLayout->count(), t);
1801 
1802     return t;
1803 }
1804 
1805 
addSlider(CvWindow * w,QString name,int * value,int count,CvTrackbarCallback on_change)1806 void CvWindow::addSlider(CvWindow* w, QString name, int* value, int count, CvTrackbarCallback on_change)
1807 {
1808     QPointer<CvTrackbar> t = new CvTrackbar(w, name, value, count, on_change);
1809     t->setAlignment(Qt::AlignHCenter);
1810 
1811     QPointer<QBoxLayout> myLayout;
1812 
1813     if (w)
1814     {
1815         myLayout = w->myBarLayout;
1816     }
1817     else
1818     {
1819         myLayout = global_control_panel->myLayout;
1820 
1821         //if first one, enable control panel
1822         if (myLayout->count() == 0)
1823             guiMainThread->enablePropertiesButtonEachWindow();
1824     }
1825 
1826     myLayout->insertLayout(myLayout->count(), t);
1827 }
1828 
1829 
addSlider2(CvWindow * w,QString name,int * value,int count,CvTrackbarCallback2 on_change,void * userdata)1830 void CvWindow::addSlider2(CvWindow* w, QString name, int* value, int count, CvTrackbarCallback2 on_change, void* userdata)
1831 {
1832     QPointer<CvTrackbar> t = new CvTrackbar(w, name, value, count, on_change, userdata);
1833     t->setAlignment(Qt::AlignHCenter);
1834 
1835     QPointer<QBoxLayout> myLayout;
1836 
1837     if (w)
1838     {
1839         myLayout = w->myBarLayout;
1840     }
1841     else
1842     {
1843         myLayout = global_control_panel->myLayout;
1844 
1845         //if first one, enable control panel
1846         if (myLayout->count() == 0)
1847             guiMainThread->enablePropertiesButtonEachWindow();
1848     }
1849 
1850     myLayout->insertLayout(myLayout->count(), t);
1851 }
1852 
1853 
setOpenGlDrawCallback(CvOpenGlDrawCallback callback,void * userdata)1854 void CvWindow::setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata)
1855 {
1856     myView->setOpenGlDrawCallback(callback, userdata);
1857 }
1858 
1859 
makeCurrentOpenGlContext()1860 void CvWindow::makeCurrentOpenGlContext()
1861 {
1862     myView->makeCurrentOpenGlContext();
1863 }
1864 
1865 
updateGl()1866 void CvWindow::updateGl()
1867 {
1868     myView->updateGl();
1869 }
1870 
1871 
isOpenGl()1872 bool CvWindow::isOpenGl()
1873 {
1874     return mode_display == CV_MODE_OPENGL;
1875 }
1876 
1877 
setViewportSize(QSize _size)1878 void CvWindow::setViewportSize(QSize _size)
1879 {
1880     resize(_size);
1881     myView->setSize(_size);
1882 }
1883 
1884 
createBarLayout()1885 void CvWindow::createBarLayout()
1886 {
1887     myBarLayout = new QBoxLayout(QBoxLayout::TopToBottom);
1888     myBarLayout->setObjectName(QString::fromUtf8("barLayout"));
1889     myBarLayout->setContentsMargins(0, 0, 0, 0);
1890     myBarLayout->setSpacing(0);
1891     myBarLayout->setMargin(0);
1892 }
1893 
1894 
createGlobalLayout()1895 void CvWindow::createGlobalLayout()
1896 {
1897     myGlobalLayout = new QBoxLayout(QBoxLayout::TopToBottom);
1898     myGlobalLayout->setObjectName(QString::fromUtf8("boxLayout"));
1899     myGlobalLayout->setContentsMargins(0, 0, 0, 0);
1900     myGlobalLayout->setSpacing(0);
1901     myGlobalLayout->setMargin(0);
1902     setMinimumSize(1, 1);
1903 
1904     if (param_flags == CV_WINDOW_AUTOSIZE)
1905         myGlobalLayout->setSizeConstraint(QLayout::SetFixedSize);
1906     else if (param_flags == CV_WINDOW_NORMAL)
1907         myGlobalLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
1908 }
1909 
1910 
createView()1911 void CvWindow::createView()
1912 {
1913 #ifdef HAVE_QT_OPENGL
1914     if (isOpenGl())
1915         myView = new OpenGlViewPort(this);
1916     else
1917 #endif
1918         myView = new DefaultViewPort(this, param_ratio_mode);
1919 }
1920 
1921 
createActions()1922 void CvWindow::createActions()
1923 {
1924     vect_QActions.resize(10);
1925 
1926     QWidget* view = myView->getWidget();
1927 
1928     //if the shortcuts are changed in window_QT.h, we need to update the tooltip manually
1929     vect_QActions[0] = new QAction(QIcon(":/left-icon"), "Panning left (CTRL+arrowLEFT)", this);
1930     vect_QActions[0]->setIconVisibleInMenu(true);
1931     QObject::connect(vect_QActions[0], SIGNAL(triggered()), view, SLOT(siftWindowOnLeft()));
1932 
1933     vect_QActions[1] = new QAction(QIcon(":/right-icon"), "Panning right (CTRL+arrowRIGHT)", this);
1934     vect_QActions[1]->setIconVisibleInMenu(true);
1935     QObject::connect(vect_QActions[1], SIGNAL(triggered()), view, SLOT(siftWindowOnRight()));
1936 
1937     vect_QActions[2] = new QAction(QIcon(":/up-icon"), "Panning up (CTRL+arrowUP)", this);
1938     vect_QActions[2]->setIconVisibleInMenu(true);
1939     QObject::connect(vect_QActions[2], SIGNAL(triggered()), view, SLOT(siftWindowOnUp()));
1940 
1941     vect_QActions[3] = new QAction(QIcon(":/down-icon"), "Panning down (CTRL+arrowDOWN)", this);
1942     vect_QActions[3]->setIconVisibleInMenu(true);
1943     QObject::connect(vect_QActions[3], SIGNAL(triggered()), view, SLOT(siftWindowOnDown()) );
1944 
1945     vect_QActions[4] = new QAction(QIcon(":/zoom_x1-icon"), "Zoom x1 (CTRL+P)", this);
1946     vect_QActions[4]->setIconVisibleInMenu(true);
1947     QObject::connect(vect_QActions[4], SIGNAL(triggered()), view, SLOT(resetZoom()));
1948 
1949     vect_QActions[5] = new QAction(QIcon(":/imgRegion-icon"), tr("Zoom x%1 (see label) (CTRL+X)").arg(threshold_zoom_img_region), this);
1950     vect_QActions[5]->setIconVisibleInMenu(true);
1951     QObject::connect(vect_QActions[5], SIGNAL(triggered()), view, SLOT(imgRegion()));
1952 
1953     vect_QActions[6] = new QAction(QIcon(":/zoom_in-icon"), "Zoom in (CTRL++)", this);
1954     vect_QActions[6]->setIconVisibleInMenu(true);
1955     QObject::connect(vect_QActions[6], SIGNAL(triggered()), view, SLOT(ZoomIn()));
1956 
1957     vect_QActions[7] = new QAction(QIcon(":/zoom_out-icon"), "Zoom out (CTRL+-)", this);
1958     vect_QActions[7]->setIconVisibleInMenu(true);
1959     QObject::connect(vect_QActions[7], SIGNAL(triggered()), view, SLOT(ZoomOut()));
1960 
1961     vect_QActions[8] = new QAction(QIcon(":/save-icon"), "Save current image (CTRL+S)", this);
1962     vect_QActions[8]->setIconVisibleInMenu(true);
1963     QObject::connect(vect_QActions[8], SIGNAL(triggered()), view, SLOT(saveView()));
1964 
1965     vect_QActions[9] = new QAction(QIcon(":/properties-icon"), "Display properties window (CTRL+P)", this);
1966     vect_QActions[9]->setIconVisibleInMenu(true);
1967     QObject::connect(vect_QActions[9], SIGNAL(triggered()), this, SLOT(displayPropertiesWin()));
1968 
1969     if (global_control_panel->myLayout->count() == 0)
1970         vect_QActions[9]->setDisabled(true);
1971 }
1972 
1973 
createShortcuts()1974 void CvWindow::createShortcuts()
1975 {
1976     vect_QShortcuts.resize(10);
1977 
1978     QWidget* view = myView->getWidget();
1979 
1980     vect_QShortcuts[0] = new QShortcut(shortcut_panning_left, this);
1981     QObject::connect(vect_QShortcuts[0], SIGNAL(activated()), view, SLOT(siftWindowOnLeft()));
1982 
1983     vect_QShortcuts[1] = new QShortcut(shortcut_panning_right, this);
1984     QObject::connect(vect_QShortcuts[1], SIGNAL(activated()), view, SLOT(siftWindowOnRight()));
1985 
1986     vect_QShortcuts[2] = new QShortcut(shortcut_panning_up, this);
1987     QObject::connect(vect_QShortcuts[2], SIGNAL(activated()), view, SLOT(siftWindowOnUp()));
1988 
1989     vect_QShortcuts[3] = new QShortcut(shortcut_panning_down, this);
1990     QObject::connect(vect_QShortcuts[3], SIGNAL(activated()), view, SLOT(siftWindowOnDown()));
1991 
1992     vect_QShortcuts[4] = new QShortcut(shortcut_zoom_normal, this);
1993     QObject::connect(vect_QShortcuts[4], SIGNAL(activated()), view, SLOT(resetZoom()));
1994 
1995     vect_QShortcuts[5] = new QShortcut(shortcut_zoom_imgRegion, this);
1996     QObject::connect(vect_QShortcuts[5], SIGNAL(activated()), view, SLOT(imgRegion()));
1997 
1998     vect_QShortcuts[6] = new QShortcut(shortcut_zoom_in, this);
1999     QObject::connect(vect_QShortcuts[6], SIGNAL(activated()), view, SLOT(ZoomIn()));
2000 
2001     vect_QShortcuts[7] = new QShortcut(shortcut_zoom_out, this);
2002     QObject::connect(vect_QShortcuts[7], SIGNAL(activated()), view, SLOT(ZoomOut()));
2003 
2004     vect_QShortcuts[8] = new QShortcut(shortcut_save_img, this);
2005     QObject::connect(vect_QShortcuts[8], SIGNAL(activated()), view, SLOT(saveView()));
2006 
2007     vect_QShortcuts[9] = new QShortcut(shortcut_properties_win, this);
2008     QObject::connect(vect_QShortcuts[9], SIGNAL(activated()), this, SLOT(displayPropertiesWin()));
2009 }
2010 
2011 
createToolBar()2012 void CvWindow::createToolBar()
2013 {
2014     myToolBar = new QToolBar(this);
2015     myToolBar->setFloatable(false); //is not a window
2016     myToolBar->setFixedHeight(28);
2017     myToolBar->setMinimumWidth(1);
2018 
2019     foreach (QAction *a, vect_QActions)
2020         myToolBar->addAction(a);
2021 }
2022 
2023 
createStatusBar()2024 void CvWindow::createStatusBar()
2025 {
2026     myStatusBar = new QStatusBar(this);
2027     myStatusBar->setSizeGripEnabled(false);
2028     myStatusBar->setFixedHeight(20);
2029     myStatusBar->setMinimumWidth(1);
2030     myStatusBar_msg = new QLabel;
2031 
2032     //I comment this because if we change the style, myview (the picture)
2033     //will not be the correct size anymore (will lost 2 pixel because of the borders)
2034 
2035     //myStatusBar_msg->setFrameStyle(QFrame::Raised);
2036 
2037     myStatusBar_msg->setAlignment(Qt::AlignHCenter);
2038     myStatusBar->addWidget(myStatusBar_msg);
2039 }
2040 
2041 
hideTools()2042 void CvWindow::hideTools()
2043 {
2044     if (myToolBar)
2045         myToolBar->hide();
2046 
2047     if (myStatusBar)
2048         myStatusBar->hide();
2049 
2050     if (global_control_panel)
2051         global_control_panel->hide();
2052 }
2053 
2054 
showTools()2055 void CvWindow::showTools()
2056 {
2057     if (myToolBar)
2058         myToolBar->show();
2059 
2060     if (myStatusBar)
2061         myStatusBar->show();
2062 }
2063 
2064 
createParameterWindow()2065 CvWinProperties* CvWindow::createParameterWindow()
2066 {
2067     QString name_paraWindow = QFileInfo(QApplication::applicationFilePath()).fileName() + " settings";
2068 
2069     CvWinProperties* result = new CvWinProperties(name_paraWindow, guiMainThread);
2070 
2071     return result;
2072 }
2073 
2074 
displayPropertiesWin()2075 void CvWindow::displayPropertiesWin()
2076 {
2077     if (global_control_panel->isHidden())
2078         global_control_panel->show();
2079     else
2080         global_control_panel->hide();
2081 }
2082 
2083 
2084 //Need more test here !
keyPressEvent(QKeyEvent * evnt)2085 void CvWindow::keyPressEvent(QKeyEvent *evnt)
2086 {
2087     //see http://doc.trolltech.com/4.6/qt.html#Key-enum
2088     int key = evnt->key();
2089 
2090         Qt::Key qtkey = static_cast<Qt::Key>(key);
2091         char asciiCode = QTest::keyToAscii(qtkey);
2092         if (asciiCode != 0)
2093             key = static_cast<int>(asciiCode);
2094         else
2095             key = evnt->nativeVirtualKey(); //same codes as returned by GTK-based backend
2096 
2097     //control plus (Z, +, -, up, down, left, right) are used for zoom/panning functions
2098         if (evnt->modifiers() != Qt::ControlModifier)
2099         {
2100         mutexKey.lock();
2101         last_key = key;
2102         mutexKey.unlock();
2103         key_pressed.wakeAll();
2104         //evnt->accept();
2105     }
2106 
2107     QWidget::keyPressEvent(evnt);
2108 }
2109 
2110 
icvLoadControlPanel()2111 void CvWindow::icvLoadControlPanel()
2112 {
2113     QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName() + " control panel");
2114 
2115     int bsize = settings.beginReadArray("bars");
2116 
2117     if (bsize == global_control_panel->myLayout->layout()->count())
2118     {
2119         for (int i = 0; i < bsize; ++i)
2120         {
2121             CvBar* t = (CvBar*) global_control_panel->myLayout->layout()->itemAt(i);
2122             settings.setArrayIndex(i);
2123             if (t->type == type_CvTrackbar)
2124             {
2125                 if (t->name_bar == settings.value("namebar").toString())
2126                 {
2127                     ((CvTrackbar*)t)->slider->setValue(settings.value("valuebar").toInt());
2128                 }
2129             }
2130             if (t->type == type_CvButtonbar)
2131             {
2132                 int subsize = settings.beginReadArray(QString("buttonbar")+i);
2133 
2134                 if ( subsize == ((CvButtonbar*)t)->layout()->count() )
2135                     icvLoadButtonbar((CvButtonbar*)t,&settings);
2136 
2137                 settings.endArray();
2138             }
2139         }
2140     }
2141 
2142     settings.endArray();
2143 }
2144 
2145 
icvSaveControlPanel()2146 void CvWindow::icvSaveControlPanel()
2147 {
2148     QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName()+" control panel");
2149 
2150     settings.beginWriteArray("bars");
2151 
2152     for (int i = 0; i < global_control_panel->myLayout->layout()->count(); ++i)
2153     {
2154         CvBar* t = (CvBar*) global_control_panel->myLayout->layout()->itemAt(i);
2155         settings.setArrayIndex(i);
2156         if (t->type == type_CvTrackbar)
2157         {
2158             settings.setValue("namebar", QString(t->name_bar));
2159             settings.setValue("valuebar",((CvTrackbar*)t)->slider->value());
2160         }
2161         if (t->type == type_CvButtonbar)
2162         {
2163             settings.beginWriteArray(QString("buttonbar")+i);
2164             icvSaveButtonbar((CvButtonbar*)t,&settings);
2165             settings.endArray();
2166         }
2167     }
2168 
2169     settings.endArray();
2170 }
2171 
2172 
icvSaveButtonbar(CvButtonbar * b,QSettings * settings)2173 void CvWindow::icvSaveButtonbar(CvButtonbar* b, QSettings* settings)
2174 {
2175     for (int i = 0, count = b->layout()->count(); i < count; ++i)
2176     {
2177         settings->setArrayIndex(i);
2178 
2179         QWidget* temp = (QWidget*) b->layout()->itemAt(i)->widget();
2180         QString myclass(QLatin1String(temp->metaObject()->className()));
2181 
2182         if (myclass == "CvPushButton")
2183         {
2184             CvPushButton* button = (CvPushButton*) temp;
2185             settings->setValue("namebutton", button->text());
2186             settings->setValue("valuebutton", int(button->isChecked()));
2187         }
2188         else if (myclass == "CvCheckBox")
2189         {
2190             CvCheckBox* button = (CvCheckBox*) temp;
2191             settings->setValue("namebutton", button->text());
2192             settings->setValue("valuebutton", int(button->isChecked()));
2193         }
2194         else if (myclass == "CvRadioButton")
2195         {
2196             CvRadioButton* button = (CvRadioButton*) temp;
2197             settings->setValue("namebutton", button->text());
2198             settings->setValue("valuebutton", int(button->isChecked()));
2199         }
2200     }
2201 }
2202 
2203 
icvLoadButtonbar(CvButtonbar * b,QSettings * settings)2204 void CvWindow::icvLoadButtonbar(CvButtonbar* b, QSettings* settings)
2205 {
2206     for (int i = 0, count = b->layout()->count(); i < count; ++i)
2207     {
2208         settings->setArrayIndex(i);
2209 
2210         QWidget* temp = (QWidget*) b->layout()->itemAt(i)->widget();
2211         QString myclass(QLatin1String(temp->metaObject()->className()));
2212 
2213         if (myclass == "CvPushButton")
2214         {
2215             CvPushButton* button = (CvPushButton*) temp;
2216 
2217             if (button->text() == settings->value("namebutton").toString())
2218                 button->setChecked(settings->value("valuebutton").toInt());
2219         }
2220         else if (myclass == "CvCheckBox")
2221         {
2222             CvCheckBox* button = (CvCheckBox*) temp;
2223 
2224             if (button->text() == settings->value("namebutton").toString())
2225                 button->setChecked(settings->value("valuebutton").toInt());
2226         }
2227         else if (myclass == "CvRadioButton")
2228         {
2229             CvRadioButton* button = (CvRadioButton*) temp;
2230 
2231             if (button->text() == settings->value("namebutton").toString())
2232                 button->setChecked(settings->value("valuebutton").toInt());
2233         }
2234 
2235     }
2236 }
2237 
2238 
icvLoadTrackbars(QSettings * settings)2239 void CvWindow::icvLoadTrackbars(QSettings* settings)
2240 {
2241     int bsize = settings->beginReadArray("trackbars");
2242 
2243     //trackbar are saved in the same order, so no need to use icvFindTrackbarByName
2244 
2245     if (myBarLayout->layout()->count() == bsize) //if not the same number, the window saved and loaded is not the same (nb trackbar not equal)
2246     {
2247         for (int i = 0; i < bsize; ++i)
2248         {
2249             settings->setArrayIndex(i);
2250 
2251             CvTrackbar* t = (CvTrackbar*) myBarLayout->layout()->itemAt(i);
2252 
2253             if (t->name_bar == settings->value("name").toString())
2254                 t->slider->setValue(settings->value("value").toInt());
2255 
2256         }
2257     }
2258 
2259     settings->endArray();
2260 }
2261 
2262 
icvSaveTrackbars(QSettings * settings)2263 void CvWindow::icvSaveTrackbars(QSettings* settings)
2264 {
2265     settings->beginWriteArray("trackbars");
2266 
2267     for (int i = 0; i < myBarLayout->layout()->count(); ++i)
2268     {
2269         settings->setArrayIndex(i);
2270 
2271         CvTrackbar* t = (CvTrackbar*) myBarLayout->layout()->itemAt(i);
2272 
2273         settings->setValue("name", t->name_bar);
2274         settings->setValue("value", t->slider->value());
2275     }
2276 
2277     settings->endArray();
2278 }
2279 
2280 
2281 //////////////////////////////////////////////////////
2282 // DefaultViewPort
2283 
2284 
DefaultViewPort(CvWindow * arg,int arg2)2285 DefaultViewPort::DefaultViewPort(CvWindow* arg, int arg2) : QGraphicsView(arg), image2Draw_mat(0)
2286 {
2287     centralWidget = arg;
2288     param_keepRatio = arg2;
2289 
2290     setContentsMargins(0, 0, 0, 0);
2291     setMinimumSize(1, 1);
2292     setAlignment(Qt::AlignHCenter);
2293 
2294     setObjectName(QString::fromUtf8("graphicsView"));
2295 
2296     timerDisplay = new QTimer(this);
2297     timerDisplay->setSingleShot(true);
2298     connect(timerDisplay, SIGNAL(timeout()), this, SLOT(stopDisplayInfo()));
2299 
2300     drawInfo = false;
2301     positionGrabbing = QPointF(0, 0);
2302     positionCorners = QRect(0, 0, size().width(), size().height());
2303 
2304     on_mouse = 0;
2305     on_mouse_param = 0;
2306     mouseCoordinate = QPoint(-1, -1);
2307 
2308     //no border
2309     setStyleSheet( "QGraphicsView { border-style: none; }" );
2310 
2311     image2Draw_mat = cvCreateMat(viewport()->height(), viewport()->width(), CV_8UC3);
2312     cvZero(image2Draw_mat);
2313 
2314     nbChannelOriginImage = 0;
2315 
2316     setInteractive(false);
2317     setMouseTracking(true); //receive mouse event everytime
2318 }
2319 
2320 
~DefaultViewPort()2321 DefaultViewPort::~DefaultViewPort()
2322 {
2323     if (image2Draw_mat)
2324         cvReleaseMat(&image2Draw_mat);
2325 }
2326 
2327 
getWidget()2328 QWidget* DefaultViewPort::getWidget()
2329 {
2330     return this;
2331 }
2332 
2333 
setMouseCallBack(CvMouseCallback m,void * param)2334 void DefaultViewPort::setMouseCallBack(CvMouseCallback m, void* param)
2335 {
2336     on_mouse = m;
2337 
2338     on_mouse_param = param;
2339 }
2340 
writeSettings(QSettings & settings)2341 void DefaultViewPort::writeSettings(QSettings& settings)
2342 {
2343     settings.setValue("matrix_view.m11", param_matrixWorld.m11());
2344     settings.setValue("matrix_view.m12", param_matrixWorld.m12());
2345     settings.setValue("matrix_view.m13", param_matrixWorld.m13());
2346     settings.setValue("matrix_view.m21", param_matrixWorld.m21());
2347     settings.setValue("matrix_view.m22", param_matrixWorld.m22());
2348     settings.setValue("matrix_view.m23", param_matrixWorld.m23());
2349     settings.setValue("matrix_view.m31", param_matrixWorld.m31());
2350     settings.setValue("matrix_view.m32", param_matrixWorld.m32());
2351     settings.setValue("matrix_view.m33", param_matrixWorld.m33());
2352 }
2353 
2354 
readSettings(QSettings & settings)2355 void DefaultViewPort::readSettings(QSettings& settings)
2356 {
2357     qreal m11 = settings.value("matrix_view.m11", param_matrixWorld.m11()).toDouble();
2358     qreal m12 = settings.value("matrix_view.m12", param_matrixWorld.m12()).toDouble();
2359     qreal m13 = settings.value("matrix_view.m13", param_matrixWorld.m13()).toDouble();
2360     qreal m21 = settings.value("matrix_view.m21", param_matrixWorld.m21()).toDouble();
2361     qreal m22 = settings.value("matrix_view.m22", param_matrixWorld.m22()).toDouble();
2362     qreal m23 = settings.value("matrix_view.m23", param_matrixWorld.m23()).toDouble();
2363     qreal m31 = settings.value("matrix_view.m31", param_matrixWorld.m31()).toDouble();
2364     qreal m32 = settings.value("matrix_view.m32", param_matrixWorld.m32()).toDouble();
2365     qreal m33 = settings.value("matrix_view.m33", param_matrixWorld.m33()).toDouble();
2366 
2367     param_matrixWorld = QTransform(m11, m12, m13, m21, m22, m23, m31, m32, m33);
2368 }
2369 
2370 
getRatio()2371 double DefaultViewPort::getRatio()
2372 {
2373     return param_keepRatio;
2374 }
2375 
2376 
setRatio(int flags)2377 void DefaultViewPort::setRatio(int flags)
2378 {
2379     if (getRatio() == flags) //nothing to do
2380         return;
2381 
2382     //if valid flags
2383     if (flags == CV_WINDOW_FREERATIO || flags == CV_WINDOW_KEEPRATIO)
2384     {
2385         centralWidget->param_ratio_mode = flags;
2386         param_keepRatio = flags;
2387         updateGeometry();
2388         viewport()->update();
2389     }
2390 }
2391 
2392 
updateImage(const CvArr * arr)2393 void DefaultViewPort::updateImage(const CvArr* arr)
2394 {
2395     CV_Assert(arr);
2396 
2397     CvMat* mat, stub;
2398     int origin = 0;
2399 
2400     if (CV_IS_IMAGE_HDR(arr))
2401         origin = ((IplImage*)arr)->origin;
2402 
2403     mat = cvGetMat(arr, &stub);
2404 
2405     if (!image2Draw_mat || !CV_ARE_SIZES_EQ(image2Draw_mat, mat))
2406     {
2407         if (image2Draw_mat)
2408             cvReleaseMat(&image2Draw_mat);
2409 
2410         //the image in ipl (to do a deep copy with cvCvtColor)
2411         image2Draw_mat = cvCreateMat(mat->rows, mat->cols, CV_8UC3);
2412         image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows, image2Draw_mat->step, QImage::Format_RGB888);
2413 
2414         //use to compute mouse coordinate, I need to update the ratio here and in resizeEvent
2415         ratioX = width() / float(image2Draw_mat->cols);
2416         ratioY = height() / float(image2Draw_mat->rows);
2417         updateGeometry();
2418     }
2419 
2420     nbChannelOriginImage = cvGetElemType(mat);
2421 
2422     cvConvertImage(mat, image2Draw_mat, (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB);
2423 
2424     viewport()->update();
2425 }
2426 
2427 
startDisplayInfo(QString text,int delayms)2428 void DefaultViewPort::startDisplayInfo(QString text, int delayms)
2429 {
2430     if (timerDisplay->isActive())
2431         stopDisplayInfo();
2432 
2433     infoText = text;
2434     if (delayms > 0) timerDisplay->start(delayms);
2435     drawInfo = true;
2436 }
2437 
2438 
setOpenGlDrawCallback(CvOpenGlDrawCallback,void *)2439 void DefaultViewPort::setOpenGlDrawCallback(CvOpenGlDrawCallback /*callback*/, void* /*userdata*/)
2440 {
2441     CV_Error(CV_OpenGlNotSupported, "Window doesn't support OpenGL");
2442 }
2443 
2444 
makeCurrentOpenGlContext()2445 void DefaultViewPort::makeCurrentOpenGlContext()
2446 {
2447     CV_Error(CV_OpenGlNotSupported, "Window doesn't support OpenGL");
2448 }
2449 
2450 
updateGl()2451 void DefaultViewPort::updateGl()
2452 {
2453     CV_Error(CV_OpenGlNotSupported, "Window doesn't support OpenGL");
2454 }
2455 
2456 
2457 //Note: move 2 percent of the window
siftWindowOnLeft()2458 void DefaultViewPort::siftWindowOnLeft()
2459 {
2460     float delta = 2 * width() / (100.0 * param_matrixWorld.m11());
2461     moveView(QPointF(delta, 0));
2462 }
2463 
2464 
2465 //Note: move 2 percent of the window
siftWindowOnRight()2466 void DefaultViewPort::siftWindowOnRight()
2467 {
2468     float delta = -2 * width() / (100.0 * param_matrixWorld.m11());
2469     moveView(QPointF(delta, 0));
2470 }
2471 
2472 
2473 //Note: move 2 percent of the window
siftWindowOnUp()2474 void DefaultViewPort::siftWindowOnUp()
2475 {
2476     float delta = 2 * height() / (100.0 * param_matrixWorld.m11());
2477     moveView(QPointF(0, delta));
2478 }
2479 
2480 
2481 //Note: move 2 percent of the window
siftWindowOnDown()2482 void DefaultViewPort::siftWindowOnDown()
2483 {
2484     float delta = -2 * height() / (100.0 * param_matrixWorld.m11());
2485     moveView(QPointF(0, delta));
2486 }
2487 
2488 
imgRegion()2489 void DefaultViewPort::imgRegion()
2490 {
2491     scaleView((threshold_zoom_img_region / param_matrixWorld.m11() - 1) * 5, QPointF(size().width() / 2, size().height() / 2));
2492 }
2493 
2494 
resetZoom()2495 void DefaultViewPort::resetZoom()
2496 {
2497     param_matrixWorld.reset();
2498     controlImagePosition();
2499 }
2500 
2501 
ZoomIn()2502 void DefaultViewPort::ZoomIn()
2503 {
2504     scaleView(0.5, QPointF(size().width() / 2, size().height() / 2));
2505 }
2506 
2507 
ZoomOut()2508 void DefaultViewPort::ZoomOut()
2509 {
2510     scaleView(-0.5, QPointF(size().width() / 2, size().height() / 2));
2511 }
2512 
2513 
2514 //can save as JPG, JPEG, BMP, PNG
saveView()2515 void DefaultViewPort::saveView()
2516 {
2517     QDate date_d = QDate::currentDate();
2518     QString date_s = date_d.toString("dd.MM.yyyy");
2519     QString name_s = centralWidget->windowTitle() + "_screenshot_" + date_s;
2520 
2521     QString fileName = QFileDialog::getSaveFileName(this, tr("Save File %1").arg(name_s), name_s + ".png", tr("Images (*.png *.jpg *.bmp *.jpeg)"));
2522 
2523     if (!fileName.isEmpty()) //save the picture
2524     {
2525         QString extension = fileName.right(3);
2526 
2527         // Create a new pixmap to render the viewport into
2528         QPixmap viewportPixmap(viewport()->size());
2529         viewport()->render(&viewportPixmap);
2530 
2531         // Save it..
2532         if (QString::compare(extension, "png", Qt::CaseInsensitive) == 0)
2533         {
2534             viewportPixmap.save(fileName, "PNG");
2535             return;
2536         }
2537 
2538         if (QString::compare(extension, "jpg", Qt::CaseInsensitive) == 0)
2539         {
2540             viewportPixmap.save(fileName, "JPG");
2541             return;
2542         }
2543 
2544         if (QString::compare(extension, "bmp", Qt::CaseInsensitive) == 0)
2545         {
2546             viewportPixmap.save(fileName, "BMP");
2547             return;
2548         }
2549 
2550         if (QString::compare(extension, "jpeg", Qt::CaseInsensitive) == 0)
2551         {
2552             viewportPixmap.save(fileName, "JPEG");
2553             return;
2554         }
2555 
2556         CV_Error(CV_StsNullPtr, "file extension not recognized, please choose between JPG, JPEG, BMP or PNG");
2557     }
2558 }
2559 
2560 
contextMenuEvent(QContextMenuEvent * evnt)2561 void DefaultViewPort::contextMenuEvent(QContextMenuEvent* evnt)
2562 {
2563     if (centralWidget->vect_QActions.size() > 0)
2564     {
2565         QMenu menu(this);
2566 
2567         foreach (QAction *a, centralWidget->vect_QActions)
2568             menu.addAction(a);
2569 
2570         menu.exec(evnt->globalPos());
2571     }
2572 }
2573 
2574 
resizeEvent(QResizeEvent * evnt)2575 void DefaultViewPort::resizeEvent(QResizeEvent* evnt)
2576 {
2577     controlImagePosition();
2578 
2579     //use to compute mouse coordinate, I need to update the ratio here and in resizeEvent
2580     ratioX = width() / float(image2Draw_mat->cols);
2581     ratioY = height() / float(image2Draw_mat->rows);
2582 
2583     if (param_keepRatio == CV_WINDOW_KEEPRATIO)//to keep the same aspect ratio
2584     {
2585         QSize newSize = QSize(image2Draw_mat->cols, image2Draw_mat->rows);
2586         newSize.scale(evnt->size(), Qt::KeepAspectRatio);
2587 
2588         //imageWidth/imageHeight = newWidth/newHeight +/- epsilon
2589         //ratioX = ratioY +/- epsilon
2590         //||ratioX - ratioY|| = epsilon
2591         if (fabs(ratioX - ratioY) * 100 > ratioX) //avoid infinity loop / epsilon = 1% of ratioX
2592         {
2593             resize(newSize);
2594 
2595             //move to the middle
2596             //newSize get the delta offset to place the picture in the middle of its parent
2597             newSize = (evnt->size() - newSize) / 2;
2598 
2599             //if the toolbar is displayed, avoid drawing myview on top of it
2600             if (centralWidget->myToolBar)
2601                 if(!centralWidget->myToolBar->isHidden())
2602                     newSize += QSize(0, centralWidget->myToolBar->height());
2603 
2604             move(newSize.width(), newSize.height());
2605         }
2606     }
2607 
2608     return QGraphicsView::resizeEvent(evnt);
2609 }
2610 
2611 
wheelEvent(QWheelEvent * evnt)2612 void DefaultViewPort::wheelEvent(QWheelEvent* evnt)
2613 {
2614     scaleView(evnt->delta() / 240.0, evnt->pos());
2615     viewport()->update();
2616 }
2617 
2618 
mousePressEvent(QMouseEvent * evnt)2619 void DefaultViewPort::mousePressEvent(QMouseEvent* evnt)
2620 {
2621     int cv_event = -1, flags = 0;
2622     QPoint pt = evnt->pos();
2623 
2624     //icvmouseHandler: pass parameters for cv_event, flags
2625     icvmouseHandler(evnt, mouse_down, cv_event, flags);
2626     icvmouseProcessing(QPointF(pt), cv_event, flags);
2627 
2628     if (param_matrixWorld.m11()>1)
2629     {
2630         setCursor(Qt::ClosedHandCursor);
2631         positionGrabbing = evnt->pos();
2632     }
2633 
2634     QWidget::mousePressEvent(evnt);
2635 }
2636 
2637 
mouseReleaseEvent(QMouseEvent * evnt)2638 void DefaultViewPort::mouseReleaseEvent(QMouseEvent* evnt)
2639 {
2640     int cv_event = -1, flags = 0;
2641     QPoint pt = evnt->pos();
2642 
2643     //icvmouseHandler: pass parameters for cv_event, flags
2644     icvmouseHandler(evnt, mouse_up, cv_event, flags);
2645     icvmouseProcessing(QPointF(pt), cv_event, flags);
2646 
2647     if (param_matrixWorld.m11()>1)
2648         setCursor(Qt::OpenHandCursor);
2649 
2650     QWidget::mouseReleaseEvent(evnt);
2651 }
2652 
2653 
mouseDoubleClickEvent(QMouseEvent * evnt)2654 void DefaultViewPort::mouseDoubleClickEvent(QMouseEvent* evnt)
2655 {
2656     int cv_event = -1, flags = 0;
2657     QPoint pt = evnt->pos();
2658 
2659     //icvmouseHandler: pass parameters for cv_event, flags
2660     icvmouseHandler(evnt, mouse_dbclick, cv_event, flags);
2661     icvmouseProcessing(QPointF(pt), cv_event, flags);
2662 
2663     QWidget::mouseDoubleClickEvent(evnt);
2664 }
2665 
2666 
mouseMoveEvent(QMouseEvent * evnt)2667 void DefaultViewPort::mouseMoveEvent(QMouseEvent* evnt)
2668 {
2669     int cv_event = CV_EVENT_MOUSEMOVE, flags = 0;
2670     QPoint pt = evnt->pos();
2671 
2672     //icvmouseHandler: pass parameters for cv_event, flags
2673     icvmouseHandler(evnt, mouse_move, cv_event, flags);
2674     icvmouseProcessing(QPointF(pt), cv_event, flags);
2675 
2676     if (param_matrixWorld.m11() > 1 && evnt->buttons() == Qt::LeftButton)
2677     {
2678         QPointF dxy = (pt - positionGrabbing)/param_matrixWorld.m11();
2679         positionGrabbing = evnt->pos();
2680         moveView(dxy);
2681     }
2682 
2683     //I update the statusbar here because if the user does a cvWaitkey(0) (like with inpaint.cpp)
2684     //the status bar will only be repaint when a click occurs.
2685     if (centralWidget->myStatusBar)
2686         viewport()->update();
2687 
2688     QWidget::mouseMoveEvent(evnt);
2689 }
2690 
2691 
paintEvent(QPaintEvent * evnt)2692 void DefaultViewPort::paintEvent(QPaintEvent* evnt)
2693 {
2694     QPainter myPainter(viewport());
2695     myPainter.setWorldTransform(param_matrixWorld);
2696 
2697     draw2D(&myPainter);
2698 
2699     //Now disable matrixWorld for overlay display
2700     myPainter.setWorldMatrixEnabled(false);
2701 
2702     //overlay pixel values if zoomed in far enough
2703     if (param_matrixWorld.m11()*ratioX >= threshold_zoom_img_region &&
2704         param_matrixWorld.m11()*ratioY >= threshold_zoom_img_region)
2705     {
2706         drawImgRegion(&myPainter);
2707     }
2708 
2709     //in mode zoom/panning
2710     if (param_matrixWorld.m11() > 1)
2711     {
2712         drawViewOverview(&myPainter);
2713     }
2714 
2715     //for information overlay
2716     if (drawInfo)
2717         drawInstructions(&myPainter);
2718 
2719     //for statusbar
2720     if (centralWidget->myStatusBar)
2721         drawStatusBar();
2722 
2723     QGraphicsView::paintEvent(evnt);
2724 }
2725 
2726 
stopDisplayInfo()2727 void DefaultViewPort::stopDisplayInfo()
2728 {
2729     timerDisplay->stop();
2730     drawInfo = false;
2731 }
2732 
2733 
isSameSize(IplImage * img1,IplImage * img2)2734 inline bool DefaultViewPort::isSameSize(IplImage* img1, IplImage* img2)
2735 {
2736     return img1->width == img2->width && img1->height == img2->height;
2737 }
2738 
2739 
controlImagePosition()2740 void DefaultViewPort::controlImagePosition()
2741 {
2742     qreal left, top, right, bottom;
2743 
2744     //after check top-left, bottom right corner to avoid getting "out" during zoom/panning
2745     param_matrixWorld.map(0,0,&left,&top);
2746 
2747     if (left > 0)
2748     {
2749         param_matrixWorld.translate(-left,0);
2750         left = 0;
2751     }
2752     if (top > 0)
2753     {
2754         param_matrixWorld.translate(0,-top);
2755         top = 0;
2756     }
2757     //-------
2758 
2759     QSize sizeImage = size();
2760     param_matrixWorld.map(sizeImage.width(),sizeImage.height(),&right,&bottom);
2761     if (right < sizeImage.width())
2762     {
2763         param_matrixWorld.translate(sizeImage.width()-right,0);
2764         right = sizeImage.width();
2765     }
2766     if (bottom < sizeImage.height())
2767     {
2768         param_matrixWorld.translate(0,sizeImage.height()-bottom);
2769         bottom = sizeImage.height();
2770     }
2771 
2772     //save corner position
2773     positionCorners.setTopLeft(QPoint(left,top));
2774     positionCorners.setBottomRight(QPoint(right,bottom));
2775     //save also the inv matrix
2776     matrixWorld_inv = param_matrixWorld.inverted();
2777 
2778     //viewport()->update();
2779 }
2780 
moveView(QPointF delta)2781 void DefaultViewPort::moveView(QPointF delta)
2782 {
2783     param_matrixWorld.translate(delta.x(),delta.y());
2784     controlImagePosition();
2785     viewport()->update();
2786 }
2787 
2788 //factor is -0.5 (zoom out) or 0.5 (zoom in)
scaleView(qreal factor,QPointF center)2789 void DefaultViewPort::scaleView(qreal factor,QPointF center)
2790 {
2791     factor/=5;//-0.1 <-> 0.1
2792     factor+=1;//0.9 <-> 1.1
2793 
2794     //limit zoom out ---
2795     if (param_matrixWorld.m11()==1 && factor < 1)
2796         return;
2797 
2798     if (param_matrixWorld.m11()*factor<1)
2799         factor = 1/param_matrixWorld.m11();
2800 
2801 
2802     //limit zoom int ---
2803     if (param_matrixWorld.m11()>100 && factor > 1)
2804         return;
2805 
2806     //inverse the transform
2807     int a, b;
2808     matrixWorld_inv.map(center.x(),center.y(),&a,&b);
2809 
2810     param_matrixWorld.translate(a-factor*a,b-factor*b);
2811     param_matrixWorld.scale(factor,factor);
2812 
2813     controlImagePosition();
2814 
2815     //display new zoom
2816     if (centralWidget->myStatusBar)
2817         centralWidget->displayStatusBar(tr("Zoom: %1%").arg(param_matrixWorld.m11()*100),1000);
2818 
2819     if (param_matrixWorld.m11()>1)
2820         setCursor(Qt::OpenHandCursor);
2821     else
2822         unsetCursor();
2823 }
2824 
2825 
2826 //up, down, dclick, move
icvmouseHandler(QMouseEvent * evnt,type_mouse_event category,int & cv_event,int & flags)2827 void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event category, int &cv_event, int &flags)
2828 {
2829     Qt::KeyboardModifiers modifiers = evnt->modifiers();
2830     Qt::MouseButtons buttons = evnt->buttons();
2831 
2832     flags = 0;
2833     if(modifiers & Qt::ShiftModifier)
2834         flags |= CV_EVENT_FLAG_SHIFTKEY;
2835     if(modifiers & Qt::ControlModifier)
2836         flags |= CV_EVENT_FLAG_CTRLKEY;
2837     if(modifiers & Qt::AltModifier)
2838         flags |= CV_EVENT_FLAG_ALTKEY;
2839 
2840     if(buttons & Qt::LeftButton)
2841         flags |= CV_EVENT_FLAG_LBUTTON;
2842     if(buttons & Qt::RightButton)
2843         flags |= CV_EVENT_FLAG_RBUTTON;
2844     if(buttons & Qt::MidButton)
2845         flags |= CV_EVENT_FLAG_MBUTTON;
2846 
2847     cv_event = CV_EVENT_MOUSEMOVE;
2848     switch(evnt->button())
2849     {
2850     case Qt::LeftButton:
2851         cv_event = tableMouseButtons[category][0];
2852         flags |= CV_EVENT_FLAG_LBUTTON;
2853         break;
2854     case Qt::RightButton:
2855         cv_event = tableMouseButtons[category][1];
2856         flags |= CV_EVENT_FLAG_RBUTTON;
2857         break;
2858     case Qt::MidButton:
2859         cv_event = tableMouseButtons[category][2];
2860         flags |= CV_EVENT_FLAG_MBUTTON;
2861         break;
2862     default:;
2863     }
2864 }
2865 
2866 
icvmouseProcessing(QPointF pt,int cv_event,int flags)2867 void DefaultViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags)
2868 {
2869     //to convert mouse coordinate
2870     qreal pfx, pfy;
2871     matrixWorld_inv.map(pt.x(),pt.y(),&pfx,&pfy);
2872 
2873     mouseCoordinate.rx()=floor(pfx/ratioX);
2874     mouseCoordinate.ry()=floor(pfy/ratioY);
2875 
2876     if (on_mouse)
2877         on_mouse( cv_event, mouseCoordinate.x(),
2878             mouseCoordinate.y(), flags, on_mouse_param );
2879 }
2880 
2881 
sizeHint() const2882 QSize DefaultViewPort::sizeHint() const
2883 {
2884     if(image2Draw_mat)
2885         return QSize(image2Draw_mat->cols, image2Draw_mat->rows);
2886     else
2887         return QGraphicsView::sizeHint();
2888 }
2889 
2890 
draw2D(QPainter * painter)2891 void DefaultViewPort::draw2D(QPainter *painter)
2892 {
2893     image2Draw_qt = QImage(image2Draw_mat->data.ptr, image2Draw_mat->cols, image2Draw_mat->rows,image2Draw_mat->step,QImage::Format_RGB888);
2894     painter->drawImage(QRect(0,0,viewport()->width(),viewport()->height()), image2Draw_qt, QRect(0,0, image2Draw_qt.width(), image2Draw_qt.height()) );
2895 }
2896 
2897 //only if CV_8UC1 or CV_8UC3
drawStatusBar()2898 void DefaultViewPort::drawStatusBar()
2899 {
2900     if (nbChannelOriginImage!=CV_8UC1 && nbChannelOriginImage!=CV_8UC3)
2901         return;
2902 
2903     if (mouseCoordinate.x()>=0 &&
2904         mouseCoordinate.y()>=0 &&
2905         mouseCoordinate.x()<image2Draw_qt.width() &&
2906         mouseCoordinate.y()<image2Draw_qt.height())
2907 //  if (mouseCoordinate.x()>=0 && mouseCoordinate.y()>=0)
2908     {
2909         QRgb rgbValue = image2Draw_qt.pixel(mouseCoordinate);
2910 
2911         if (nbChannelOriginImage==CV_8UC3 )
2912         {
2913             centralWidget->myStatusBar_msg->setText(tr("<font color='black'>(x=%1, y=%2) ~ </font>")
2914                 .arg(mouseCoordinate.x())
2915                 .arg(mouseCoordinate.y())+
2916                 tr("<font color='red'>R:%3 </font>").arg(qRed(rgbValue))+//.arg(value.val[0])+
2917                 tr("<font color='green'>G:%4 </font>").arg(qGreen(rgbValue))+//.arg(value.val[1])+
2918                 tr("<font color='blue'>B:%5</font>").arg(qBlue(rgbValue))//.arg(value.val[2])
2919                 );
2920         }
2921 
2922         if (nbChannelOriginImage==CV_8UC1)
2923         {
2924             //all the channel have the same value (because of cvconvertimage), so only the r channel is dsplayed
2925             centralWidget->myStatusBar_msg->setText(tr("<font color='black'>(x=%1, y=%2) ~ </font>")
2926                 .arg(mouseCoordinate.x())
2927                 .arg(mouseCoordinate.y())+
2928                 tr("<font color='grey'>L:%3 </font>").arg(qRed(rgbValue))
2929                 );
2930         }
2931     }
2932 }
2933 
2934 //accept only CV_8UC1 and CV_8UC8 image for now
drawImgRegion(QPainter * painter)2935 void DefaultViewPort::drawImgRegion(QPainter *painter)
2936 {
2937     if (nbChannelOriginImage!=CV_8UC1 && nbChannelOriginImage!=CV_8UC3)
2938         return;
2939 
2940     double pixel_width = param_matrixWorld.m11()*ratioX;
2941     double pixel_height = param_matrixWorld.m11()*ratioY;
2942 
2943     qreal offsetX = param_matrixWorld.dx()/pixel_width;
2944     offsetX = offsetX - floor(offsetX);
2945     qreal offsetY = param_matrixWorld.dy()/pixel_height;
2946     offsetY = offsetY - floor(offsetY);
2947 
2948     QSize view = size();
2949     QVarLengthArray<QLineF, 30> linesX;
2950     for (qreal _x = offsetX*pixel_width; _x < view.width(); _x += pixel_width )
2951         linesX.append(QLineF(_x, 0, _x, view.height()));
2952 
2953     QVarLengthArray<QLineF, 30> linesY;
2954     for (qreal _y = offsetY*pixel_height; _y < view.height(); _y += pixel_height )
2955         linesY.append(QLineF(0, _y, view.width(), _y));
2956 
2957 
2958     QFont f = painter->font();
2959     int original_font_size = f.pointSize();
2960     //change font size
2961     //f.setPointSize(4+(param_matrixWorld.m11()-threshold_zoom_img_region)/5);
2962     f.setPixelSize(10+(pixel_height-threshold_zoom_img_region)/5);
2963     painter->setFont(f);
2964 
2965 
2966     for (int j=-1;j<height()/pixel_height;j++)//-1 because display the pixels top rows left columns
2967         for (int i=-1;i<width()/pixel_width;i++)//-1
2968         {
2969             // Calculate top left of the pixel's position in the viewport (screen space)
2970             QPointF pos_in_view((i+offsetX)*pixel_width, (j+offsetY)*pixel_height);
2971 
2972             // Calculate top left of the pixel's position in the image (image space)
2973             QPointF pos_in_image = matrixWorld_inv.map(pos_in_view);// Top left of pixel in view
2974             pos_in_image.rx() = pos_in_image.x()/ratioX;
2975             pos_in_image.ry() = pos_in_image.y()/ratioY;
2976             QPoint point_in_image(pos_in_image.x() + 0.5f,pos_in_image.y() + 0.5f);// Add 0.5 for rounding
2977 
2978             QRgb rgbValue;
2979             if (image2Draw_qt.valid(point_in_image))
2980                 rgbValue = image2Draw_qt.pixel(point_in_image);
2981             else
2982                 rgbValue = qRgb(0,0,0);
2983 
2984             if (nbChannelOriginImage==CV_8UC3)
2985             {
2986                 //for debug
2987                 /*
2988                 val = tr("%1 %2").arg(point2.x()).arg(point2.y());
2989                 painter->setPen(QPen(Qt::black, 1));
2990                 painter->drawText(QRect(point1.x(),point1.y(),param_matrixWorld.m11(),param_matrixWorld.m11()/2),
2991                     Qt::AlignCenter, val);
2992                 */
2993                 QString val;
2994 
2995                 val = tr("%1").arg(qRed(rgbValue));
2996                 painter->setPen(QPen(Qt::red, 1));
2997                 painter->drawText(QRect(pos_in_view.x(),pos_in_view.y(),pixel_width,pixel_height/3),
2998                     Qt::AlignCenter, val);
2999 
3000                 val = tr("%1").arg(qGreen(rgbValue));
3001                 painter->setPen(QPen(Qt::green, 1));
3002                 painter->drawText(QRect(pos_in_view.x(),pos_in_view.y()+pixel_height/3,pixel_width,pixel_height/3),
3003                     Qt::AlignCenter, val);
3004 
3005                 val = tr("%1").arg(qBlue(rgbValue));
3006                 painter->setPen(QPen(Qt::blue, 1));
3007                 painter->drawText(QRect(pos_in_view.x(),pos_in_view.y()+2*pixel_height/3,pixel_width,pixel_height/3),
3008                     Qt::AlignCenter, val);
3009 
3010             }
3011 
3012             if (nbChannelOriginImage==CV_8UC1)
3013             {
3014                 QString val = tr("%1").arg(qRed(rgbValue));
3015                 painter->drawText(QRect(pos_in_view.x(),pos_in_view.y(),pixel_width,pixel_height),
3016                     Qt::AlignCenter, val);
3017             }
3018         }
3019 
3020         painter->setPen(QPen(Qt::black, 1));
3021         painter->drawLines(linesX.data(), linesX.size());
3022         painter->drawLines(linesY.data(), linesY.size());
3023 
3024         //restore font size
3025         f.setPointSize(original_font_size);
3026         painter->setFont(f);
3027 
3028 }
3029 
drawViewOverview(QPainter * painter)3030 void DefaultViewPort::drawViewOverview(QPainter *painter)
3031 {
3032     QSize viewSize = size();
3033     viewSize.scale ( 100, 100,Qt::KeepAspectRatio );
3034 
3035     const int margin = 5;
3036 
3037     //draw the image's location
3038     painter->setBrush(QColor(0, 0, 0, 127));
3039     painter->setPen(Qt::darkGreen);
3040     painter->drawRect(QRect(width()-viewSize.width()-margin, 0,viewSize.width(),viewSize.height()));
3041 
3042     //daw the view's location inside the image
3043     qreal ratioSize = 1/param_matrixWorld.m11();
3044     qreal ratioWindow = (qreal)(viewSize.height())/(qreal)(size().height());
3045     painter->setPen(Qt::darkBlue);
3046     painter->drawRect(QRectF(width()-viewSize.width()-positionCorners.left()*ratioSize*ratioWindow-margin,
3047         -positionCorners.top()*ratioSize*ratioWindow,
3048         (viewSize.width()-1)*ratioSize,
3049         (viewSize.height()-1)*ratioSize)
3050         );
3051 }
3052 
drawInstructions(QPainter * painter)3053 void DefaultViewPort::drawInstructions(QPainter *painter)
3054 {
3055     QFontMetrics metrics = QFontMetrics(font());
3056     int border = qMax(4, metrics.leading());
3057 
3058     QRect qrect = metrics.boundingRect(0, 0, width() - 2*border, int(height()*0.125),
3059         Qt::AlignCenter | Qt::TextWordWrap, infoText);
3060     painter->setRenderHint(QPainter::TextAntialiasing);
3061     painter->fillRect(QRect(0, 0, width(), qrect.height() + 2*border),
3062         QColor(0, 0, 0, 127));
3063     painter->setPen(Qt::white);
3064     painter->fillRect(QRect(0, 0, width(), qrect.height() + 2*border),
3065         QColor(0, 0, 0, 127));
3066 
3067     painter->drawText((width() - qrect.width())/2, border,
3068         qrect.width(), qrect.height(),
3069         Qt::AlignCenter | Qt::TextWordWrap, infoText);
3070 }
3071 
3072 
setSize(QSize)3073 void DefaultViewPort::setSize(QSize /*size_*/)
3074 {
3075 }
3076 
3077 
3078 //////////////////////////////////////////////////////
3079 // OpenGlViewPort
3080 
3081 #ifdef HAVE_QT_OPENGL
3082 
OpenGlViewPort(QWidget * _parent)3083 OpenGlViewPort::OpenGlViewPort(QWidget* _parent) : QGLWidget(_parent), size(-1, -1)
3084 {
3085     mouseCallback = 0;
3086     mouseData = 0;
3087 
3088     glDrawCallback = 0;
3089     glDrawData = 0;
3090 }
3091 
~OpenGlViewPort()3092 OpenGlViewPort::~OpenGlViewPort()
3093 {
3094 }
3095 
getWidget()3096 QWidget* OpenGlViewPort::getWidget()
3097 {
3098     return this;
3099 }
3100 
setMouseCallBack(CvMouseCallback callback,void * param)3101 void OpenGlViewPort::setMouseCallBack(CvMouseCallback callback, void* param)
3102 {
3103     mouseCallback = callback;
3104     mouseData = param;
3105 }
3106 
writeSettings(QSettings &)3107 void OpenGlViewPort::writeSettings(QSettings& /*settings*/)
3108 {
3109 }
3110 
readSettings(QSettings &)3111 void OpenGlViewPort::readSettings(QSettings& /*settings*/)
3112 {
3113 }
3114 
getRatio()3115 double OpenGlViewPort::getRatio()
3116 {
3117     return (double)width() / height();
3118 }
3119 
setRatio(int)3120 void OpenGlViewPort::setRatio(int /*flags*/)
3121 {
3122 }
3123 
updateImage(const CvArr *)3124 void OpenGlViewPort::updateImage(const CvArr* /*arr*/)
3125 {
3126 }
3127 
startDisplayInfo(QString,int)3128 void OpenGlViewPort::startDisplayInfo(QString /*text*/, int /*delayms*/)
3129 {
3130 }
3131 
setOpenGlDrawCallback(CvOpenGlDrawCallback callback,void * userdata)3132 void OpenGlViewPort::setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata)
3133 {
3134     glDrawCallback = callback;
3135     glDrawData = userdata;
3136 }
3137 
makeCurrentOpenGlContext()3138 void OpenGlViewPort::makeCurrentOpenGlContext()
3139 {
3140     makeCurrent();
3141 }
3142 
updateGl()3143 void OpenGlViewPort::updateGl()
3144 {
3145     QGLWidget::updateGL();
3146 }
3147 
initializeGL()3148 void OpenGlViewPort::initializeGL()
3149 {
3150     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
3151 }
3152 
resizeGL(int w,int h)3153 void OpenGlViewPort::resizeGL(int w, int h)
3154 {
3155     glViewport(0, 0, w, h);
3156 }
3157 
paintGL()3158 void OpenGlViewPort::paintGL()
3159 {
3160     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3161 
3162     if (glDrawCallback)
3163         glDrawCallback(glDrawData);
3164 }
3165 
mousePressEvent(QMouseEvent * evnt)3166 void OpenGlViewPort::mousePressEvent(QMouseEvent* evnt)
3167 {
3168     int cv_event = -1, flags = 0;
3169     QPoint pt = evnt->pos();
3170 
3171     icvmouseHandler(evnt, mouse_down, cv_event, flags);
3172     icvmouseProcessing(QPointF(pt), cv_event, flags);
3173 
3174     QGLWidget::mousePressEvent(evnt);
3175 }
3176 
3177 
mouseReleaseEvent(QMouseEvent * evnt)3178 void OpenGlViewPort::mouseReleaseEvent(QMouseEvent* evnt)
3179 {
3180     int cv_event = -1, flags = 0;
3181     QPoint pt = evnt->pos();
3182 
3183     icvmouseHandler(evnt, mouse_up, cv_event, flags);
3184     icvmouseProcessing(QPointF(pt), cv_event, flags);
3185 
3186     QGLWidget::mouseReleaseEvent(evnt);
3187 }
3188 
3189 
mouseDoubleClickEvent(QMouseEvent * evnt)3190 void OpenGlViewPort::mouseDoubleClickEvent(QMouseEvent* evnt)
3191 {
3192     int cv_event = -1, flags = 0;
3193     QPoint pt = evnt->pos();
3194 
3195     icvmouseHandler(evnt, mouse_dbclick, cv_event, flags);
3196     icvmouseProcessing(QPointF(pt), cv_event, flags);
3197 
3198     QGLWidget::mouseDoubleClickEvent(evnt);
3199 }
3200 
3201 
mouseMoveEvent(QMouseEvent * evnt)3202 void OpenGlViewPort::mouseMoveEvent(QMouseEvent* evnt)
3203 {
3204     int cv_event = CV_EVENT_MOUSEMOVE, flags = 0;
3205     QPoint pt = evnt->pos();
3206 
3207     //icvmouseHandler: pass parameters for cv_event, flags
3208     icvmouseHandler(evnt, mouse_move, cv_event, flags);
3209     icvmouseProcessing(QPointF(pt), cv_event, flags);
3210 
3211     QGLWidget::mouseMoveEvent(evnt);
3212 }
3213 
icvmouseHandler(QMouseEvent * evnt,type_mouse_event category,int & cv_event,int & flags)3214 void OpenGlViewPort::icvmouseHandler(QMouseEvent* evnt, type_mouse_event category, int& cv_event, int& flags)
3215 {
3216     Qt::KeyboardModifiers modifiers = evnt->modifiers();
3217     Qt::MouseButtons buttons = evnt->buttons();
3218 
3219     flags = 0;
3220     if (modifiers & Qt::ShiftModifier)
3221         flags |= CV_EVENT_FLAG_SHIFTKEY;
3222     if (modifiers & Qt::ControlModifier)
3223         flags |= CV_EVENT_FLAG_CTRLKEY;
3224     if (modifiers & Qt::AltModifier)
3225         flags |= CV_EVENT_FLAG_ALTKEY;
3226 
3227     if (buttons & Qt::LeftButton)
3228         flags |= CV_EVENT_FLAG_LBUTTON;
3229     if (buttons & Qt::RightButton)
3230         flags |= CV_EVENT_FLAG_RBUTTON;
3231     if (buttons & Qt::MidButton)
3232         flags |= CV_EVENT_FLAG_MBUTTON;
3233 
3234     cv_event = CV_EVENT_MOUSEMOVE;
3235     switch (evnt->button())
3236     {
3237     case Qt::LeftButton:
3238         cv_event = tableMouseButtons[category][0];
3239         flags |= CV_EVENT_FLAG_LBUTTON;
3240         break;
3241 
3242     case Qt::RightButton:
3243         cv_event = tableMouseButtons[category][1];
3244         flags |= CV_EVENT_FLAG_RBUTTON;
3245         break;
3246 
3247     case Qt::MidButton:
3248         cv_event = tableMouseButtons[category][2];
3249         flags |= CV_EVENT_FLAG_MBUTTON;
3250         break;
3251 
3252     default:
3253         ;
3254     }
3255 }
3256 
3257 
icvmouseProcessing(QPointF pt,int cv_event,int flags)3258 void OpenGlViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags)
3259 {
3260     if (mouseCallback)
3261         mouseCallback(cv_event, pt.x(), pt.y(), flags, mouseData);
3262 }
3263 
3264 
sizeHint() const3265 QSize OpenGlViewPort::sizeHint() const
3266 {
3267     if (size.width() > 0 && size.height() > 0)
3268         return size;
3269 
3270     return QGLWidget::sizeHint();
3271 }
3272 
setSize(QSize size_)3273 void OpenGlViewPort::setSize(QSize size_)
3274 {
3275     size = size_;
3276     updateGeometry();
3277 }
3278 
3279 #endif
3280 
3281 #endif // HAVE_QT
3282