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