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