void DistViewGUI::initSignals(QObject *dvctrl) { // signals from DistviewController connect(dvctrl, SIGNAL(pixelOverlayInvalid()), vp, SLOT(removePixelOverlay())); connect(dvctrl, SIGNAL(toggleLabeled(bool)), vp, SLOT(toggleLabeled(bool))); connect(dvctrl, SIGNAL(toggleUnlabeled(bool)), vp, SLOT(toggleUnlabeled(bool))); connect(dvctrl, SIGNAL(labelSelected(int)), vp, SLOT(toggleLabelHighlight(int))); // signals to controller connect(this, SIGNAL(requestBinCount(representation::t, int)), dvctrl, SLOT(changeBinCount(representation::t, int))); // viewport action connect(vp, SIGNAL(activated(representation::t)), dvctrl, SLOT(setActiveViewer(representation::t))); connect(vp, SIGNAL(activated(representation::t)), this, SIGNAL(activated())); connect(vp, SIGNAL(bandSelected(int)), dvctrl, SLOT(propagateBandSelection(int))); connect(vp, SIGNAL(requestOverlay(int,int)), dvctrl, SLOT(drawOverlay(int,int))); connect(vp, SIGNAL(requestOverlay(std::vector<std::pair<int,int> >,int)), dvctrl, SLOT(drawOverlay(std::vector<std::pair<int,int> >,int))); connect(vp, SIGNAL(addSelectionRequested()), dvctrl, SLOT(addHighlightToLabel())); connect(vp, SIGNAL(remSelectionRequested()), dvctrl, SLOT(remHighlightFromLabel())); // illumination correction connect(this, SIGNAL(newIlluminantCurve(QVector<multi_img::Value>)), vp, SLOT(changeIlluminantCurve(QVector<multi_img::Value>))); connect(this, SIGNAL(toggleIlluminationShown(bool)), vp, SLOT(setIlluminationCurveShown(bool))); connect(this, SIGNAL(newIlluminantApplied(QVector<multi_img::Value>)), vp, SLOT(setAppliedIlluminant(QVector<multi_img::Value>))); }
Controller::Controller(const QString &filename, bool limited_mode, const QString &labelfile, QObject *parent) : QObject(parent), // initialize all pointers so we don't access them too early w/o notice im(nullptr), lm(nullptr), fm(nullptr), illumm(nullptr), gsm(nullptr), #ifdef WITH_SEG_MEANSHIFT cm(nullptr), #endif dvc(nullptr), queuethread(nullptr), subs(new Subscriptions) { // reset internal ROI state tracking resetROISpawned(); // start background task queue thread connect(&queue, SIGNAL(exception(std::exception_ptr, bool)), GerbilApplication::instance(), SLOT(handle_exception(std::exception_ptr,bool)), Qt::BlockingQueuedConnection); startQueue(); im = new ImageModel(queue, limited_mode, this); // load image cv::Rect dimensions = im->loadImage(filename); imgSize = cv::Size(dimensions.width, dimensions.height); // create gui (perform initUI before connecting signals!) window = new MainWindow(); window->initUI(filename); // initialize models initImage(); fm = new FalseColorModel(); initFalseColor(); // depends on ImageModel / initImage() // The order of connection is crucial for fm and Controller. // fm needs to get the signal first. Otherwise it will // hand out invalid cached data. connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)), fm, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool))); connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)), this, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool))); lm = new LabelingModel(this); initLabeling(dimensions); illumm = new IllumModel(&queue, this); initIlluminant(); gsm = new GraphSegmentationModel(&queue, this); initGraphSegmentation(); // depends on ImageModel / initImage() #ifdef WITH_SEG_MEANSHIFT cm = new ClusteringModel(this); #endif /* WITH_SEG_MEANSHIFT */ // initialize sub-controllers (after initializing the models...) dvc = new DistViewController(this, &queue, im); dvc->init(); // init dock widgets initDocks(); // connect slots/signals window->initSignals(this, dvc); /* TODO: better place. But do not use init model functions: * dvc are created after these are called */ connect(dvc, SIGNAL(requestOverlay(cv::Mat1b)), this, SIGNAL(requestOverlay(cv::Mat1b))); connect(lm, SIGNAL(newLabeling(const cv::Mat1s&, const QVector<QColor>&, bool)), dvc, SLOT(updateLabels(cv::Mat1s,QVector<QColor>,bool))); connect(lm, SIGNAL(partialLabelUpdate(const cv::Mat1s&,const cv::Mat1b&)), dvc, SLOT(updateLabelsPartially(const cv::Mat1s&,const cv::Mat1b&))); connect(dvc, SIGNAL(alterLabelRequested(short,cv::Mat1b,bool)), lm, SLOT(alterLabel(short,cv::Mat1b,bool))); connect(illumm, SIGNAL(newIlluminantCurve(QVector<multi_img::Value>)), dvc, SIGNAL(newIlluminantCurve(QVector<multi_img::Value>))); connect(illumm, SIGNAL(newIlluminantApplied(QVector<multi_img::Value>)), dvc, SIGNAL(newIlluminantApplied(QVector<multi_img::Value>))); #ifdef WITH_SEG_MEANSHIFT connect(cm, SIGNAL(subscribeRepresentation(QObject*,representation::t)), this, SLOT(subscribeRepresentation(QObject*,representation::t))); connect(cm, SIGNAL(unsubscribeRepresentation(QObject*,representation::t)), this, SLOT(unsubscribeRepresentation(QObject*,representation::t))); connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)), cm, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool))); #endif connect(this, SIGNAL(preROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)), dvc, SLOT(processPreROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool))); connect(this, SIGNAL(postROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)), dvc, SLOT(processPostROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool))); /* start with initial label or provided labeling * Do this after all signals are connected, and before initial ROI spawn! */ if (labelfile.isEmpty()) { lm->addLabel(); } else { lm->loadLabeling(labelfile); } /* Initial ROI images spawning. Do it before showing the window but after * all signals were connected! */ //GGDBGM("dimensions " << dimensions << endl); roi = dimensions; // initial ROI is image size, except: if (roi.area() > 262144) { // image is bigger than 512x512, start with a smaller ROI in center roi.width = std::min(roi.width, 512); roi.height = std::min(roi.height, 512); roi.x = 0.5*(dimensions.width - roi.width); roi.y = 0.5*(dimensions.height - roi.height); } GGDBGM("roi " << roi << endl); spawnROI(); // The IMG representation must always be subscribed. Otherwise all the logic // in ImageModel fails. So we subscribe the Controller forever. subscribeRepresentation(this, representation::IMG); GGDBGM("init distview subscriptions" << endl); dvc->initSubscriptions(); GGDBGM("init done, showing mainwindow" << endl); // we're done! show window window->show(); }