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(¶meterSystemC, 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(¶meterSystemC, 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