mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-23 18:09:25 +08:00
Integrate cvv module: Interactive Visual Debugging of Computer Vision applications
This commit is contained in:
384
modules/cvv/src/controller/view_controller.cpp
Normal file
384
modules/cvv/src/controller/view_controller.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
#include "view_controller.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
#include "../gui/call_tab.hpp"
|
||||
#include "../gui/call_window.hpp"
|
||||
#include "../gui/overview_panel.hpp"
|
||||
#include "../gui/main_call_window.hpp"
|
||||
#include "../gui/filter_call_tab.hpp"
|
||||
#include "../gui/match_call_tab.hpp"
|
||||
#include "../gui/image_call_tab.hpp"
|
||||
#include "../impl/init.hpp"
|
||||
#include "../impl/filter_call.hpp"
|
||||
#include "../impl/match_call.hpp"
|
||||
#include "../impl/single_image_call.hpp"
|
||||
#include "../impl/data_controller.hpp"
|
||||
#include "../qtutil/util.hpp"
|
||||
|
||||
namespace cvv
|
||||
{
|
||||
namespace controller
|
||||
{
|
||||
|
||||
// It's only used for instatiating a QApplication.
|
||||
// static char *emptyArray[] = {""};
|
||||
static char *parameterSystemV[] = { new char[1]{ 0 }, nullptr };
|
||||
static int parameterSystemC = 1;
|
||||
|
||||
ViewController::ViewController()
|
||||
{
|
||||
impl::initializeFilterAndViews();
|
||||
if (!QApplication::instance())
|
||||
{
|
||||
auto tmp =
|
||||
new QApplication{ parameterSystemC, parameterSystemV };
|
||||
ownsQApplication = true;
|
||||
(void)tmp;
|
||||
}
|
||||
ovPanel = new gui::OverviewPanel{ util::makeRef(*this) };
|
||||
mainWindow = new gui::MainCallWindow(util::makeRef(*this), 0, ovPanel);
|
||||
windowMap[0] = std::unique_ptr<gui::CallWindow>(mainWindow);
|
||||
max_window_id = 0;
|
||||
mainWindow->show();
|
||||
}
|
||||
|
||||
ViewController::~ViewController()
|
||||
{
|
||||
callTabMap.clear();
|
||||
windowMap.clear();
|
||||
windowMap.clear();
|
||||
if (ownsQApplication)
|
||||
{
|
||||
delete QApplication::instance();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::addCallType(const QString typeName, TabFactory constr)
|
||||
{
|
||||
ViewController::callTabType[typeName] = constr;
|
||||
}
|
||||
|
||||
std::unique_ptr<cvv::gui::FilterCallTab>
|
||||
makeFilterCallTab(cvv::util::Reference<cvv::impl::Call> call)
|
||||
{
|
||||
return cvv::util::make_unique<cvv::gui::FilterCallTab>(
|
||||
*call.castTo<cvv::impl::FilterCall>());
|
||||
}
|
||||
|
||||
std::unique_ptr<cvv::gui::MatchCallTab>
|
||||
makeMatchCallTab(cvv::util::Reference<cvv::impl::Call> call)
|
||||
{
|
||||
return cvv::util::make_unique<cvv::gui::MatchCallTab>(
|
||||
*call.castTo<cvv::impl::MatchCall>());
|
||||
}
|
||||
|
||||
std::unique_ptr<cvv::gui::ImageCallTab>
|
||||
makeImageCallTab(cvv::util::Reference<cvv::impl::Call> call)
|
||||
{
|
||||
return cvv::util::make_unique<cvv::gui::ImageCallTab>(
|
||||
*call.castTo<cvv::impl::SingleImageCall>());
|
||||
}
|
||||
|
||||
std::map<QString, TabFactory> ViewController::callTabType{
|
||||
{ "filter", makeFilterCallTab }, { "match", makeMatchCallTab },
|
||||
{ "singleImage", makeImageCallTab }
|
||||
};
|
||||
|
||||
void ViewController::addCall(util::Reference<impl::Call> data)
|
||||
{
|
||||
updateMode();
|
||||
if (mode == Mode::NORMAL)
|
||||
{
|
||||
ovPanel->addElement(*data);
|
||||
mainWindow->showOverviewTab();
|
||||
}
|
||||
else if (mode == Mode::FAST_FORWARD)
|
||||
{
|
||||
ovPanel->addElementBuffered(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::exec()
|
||||
{
|
||||
updateMode();
|
||||
if (mode == Mode::NORMAL)
|
||||
{
|
||||
QApplication::instance()->exec();
|
||||
}
|
||||
}
|
||||
|
||||
impl::Call &ViewController::getCall(size_t id)
|
||||
{
|
||||
return impl::dataController().getCall(id);
|
||||
}
|
||||
|
||||
QString ViewController::getSetting(const QString &scope, const QString &key)
|
||||
{
|
||||
return qtutil::getSetting(scope, key);
|
||||
}
|
||||
|
||||
std::vector<util::Reference<gui::CallWindow>> ViewController::getTabWindows()
|
||||
{
|
||||
std::vector<util::Reference<gui::CallWindow>> windows{};
|
||||
for (auto &it : windowMap)
|
||||
{
|
||||
windows.push_back(util::makeRef(*(it.second)));
|
||||
}
|
||||
return windows;
|
||||
}
|
||||
|
||||
util::Reference<gui::MainCallWindow> ViewController::getMainWindow()
|
||||
{
|
||||
return util::makeRef(*mainWindow);
|
||||
}
|
||||
|
||||
void ViewController::moveCallTabToNewWindow(size_t tabId)
|
||||
{
|
||||
if (!hasCall(tabId))
|
||||
return;
|
||||
auto newWindow = util::make_unique<gui::CallWindow>(
|
||||
util::makeRef<ViewController>(*this), ++max_window_id);
|
||||
removeCallTab(tabId);
|
||||
newWindow->addTab(getCallTab(tabId));
|
||||
newWindow->show();
|
||||
if (doesShowExitProgramButton)
|
||||
{
|
||||
newWindow->showExitProgramButton();
|
||||
}
|
||||
windowMap[max_window_id] = std::move(newWindow);
|
||||
removeEmptyWindowsWithDelay();
|
||||
}
|
||||
|
||||
void ViewController::moveCallTabToWindow(size_t tabId, size_t windowId)
|
||||
{
|
||||
if (!hasCall(tabId))
|
||||
return;
|
||||
removeCallTab(tabId);
|
||||
auto tab = getCallTab(tabId);
|
||||
windowMap[windowId]->addTab(tab);
|
||||
removeEmptyWindowsWithDelay();
|
||||
}
|
||||
|
||||
void ViewController::removeCallTab(size_t tabId, bool deleteIt, bool deleteCall, bool updateUI)
|
||||
{
|
||||
auto *curWindow = getCurrentWindowOfTab(tabId);
|
||||
if (curWindow->hasTab(tabId))
|
||||
{
|
||||
getCurrentWindowOfTab(tabId)->removeTab(tabId);
|
||||
if (deleteIt)
|
||||
{
|
||||
callTabMap.erase(tabId);
|
||||
}
|
||||
}
|
||||
if (deleteCall && hasCall(tabId))
|
||||
{
|
||||
if (updateUI)
|
||||
{
|
||||
ovPanel->removeElement(tabId);
|
||||
}
|
||||
impl::dataController().removeCall(tabId);
|
||||
}
|
||||
removeEmptyWindowsWithDelay();
|
||||
}
|
||||
|
||||
void ViewController::openHelpBrowser(const QString &topic)
|
||||
{
|
||||
qtutil::openHelpBrowser(topic);
|
||||
}
|
||||
|
||||
void ViewController::resumeProgramExecution()
|
||||
{
|
||||
QApplication::instance()->exit();
|
||||
}
|
||||
|
||||
void ViewController::setDefaultSetting(const QString &scope, const QString &key,
|
||||
const QString &value)
|
||||
{
|
||||
qtutil::setDefaultSetting(scope, key, value);
|
||||
}
|
||||
|
||||
void ViewController::setSetting(const QString &scope, const QString &key,
|
||||
const QString &value)
|
||||
{
|
||||
qtutil::setSetting(scope, key, value);
|
||||
}
|
||||
|
||||
void ViewController::showCallTab(size_t tabId)
|
||||
{
|
||||
auto *window = getCurrentWindowOfTab(tabId);
|
||||
window->showTab(tabId);
|
||||
window->setWindowState((window->windowState() & ~Qt::WindowMinimized) |
|
||||
Qt::WindowActive);
|
||||
window->raise();
|
||||
}
|
||||
|
||||
void ViewController::showAndOpenCallTab(size_t tabId)
|
||||
{
|
||||
auto curWindow = getCurrentWindowOfTab(tabId);
|
||||
if (!curWindow->hasTab(tabId))
|
||||
{
|
||||
moveCallTabToWindow(tabId, 0);
|
||||
curWindow = mainWindow;
|
||||
}
|
||||
curWindow->showTab(tabId);
|
||||
}
|
||||
|
||||
void ViewController::openCallTab(size_t tabId)
|
||||
{
|
||||
auto curWindow = getCurrentWindowOfTab(tabId);
|
||||
if (!curWindow->hasTab(tabId))
|
||||
{
|
||||
moveCallTabToWindow(tabId, 0);
|
||||
curWindow = mainWindow;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::showOverview()
|
||||
{
|
||||
mainWindow->setWindowState(
|
||||
(mainWindow->windowState() & ~Qt::WindowMinimized) |
|
||||
Qt::WindowActive);
|
||||
mainWindow->raise();
|
||||
mainWindow->showOverviewTab();
|
||||
}
|
||||
|
||||
gui::CallWindow *ViewController::getCurrentWindowOfTab(size_t tabId)
|
||||
{
|
||||
for (auto &elem : windowMap)
|
||||
{
|
||||
if (elem.second->hasTab(tabId))
|
||||
{
|
||||
return elem.second.get();
|
||||
}
|
||||
}
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
gui::CallTab *ViewController::getCallTab(size_t tabId)
|
||||
{
|
||||
if (callTabMap.count(tabId) == 0)
|
||||
{
|
||||
auto *call = &(getCall(tabId));
|
||||
if (callTabType.count(call->type()) == 0)
|
||||
{
|
||||
throw std::invalid_argument{
|
||||
"no such type '" + call->type().toStdString() +
|
||||
"'"
|
||||
};
|
||||
}
|
||||
callTabMap[tabId] =
|
||||
callTabType[call->type()](util::makeRef(*call));
|
||||
}
|
||||
return callTabMap[tabId].get();
|
||||
}
|
||||
|
||||
void ViewController::removeWindowFromMaps(size_t windowId)
|
||||
{
|
||||
if (windowMap.count(windowId) > 0)
|
||||
{
|
||||
windowMap[windowId].release();
|
||||
windowMap.erase(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::removeEmptyWindows()
|
||||
{
|
||||
std::vector<size_t> remIds{};
|
||||
for (auto &elem : windowMap)
|
||||
{
|
||||
if (elem.second->tabCount() == 0 && elem.second->getId() != 0)
|
||||
{
|
||||
remIds.push_back(elem.first);
|
||||
}
|
||||
}
|
||||
for (auto windowId : remIds)
|
||||
{
|
||||
auto window = windowMap[windowId].release();
|
||||
windowMap.erase(windowId);
|
||||
window->deleteLater();
|
||||
}
|
||||
shouldRunRemoveEmptyWindows_ = false;
|
||||
}
|
||||
|
||||
void ViewController::removeEmptyWindowsWithDelay()
|
||||
{
|
||||
shouldRunRemoveEmptyWindows_ = true;
|
||||
}
|
||||
|
||||
bool ViewController::shouldRunRemoveEmptyWindows()
|
||||
{
|
||||
return shouldRunRemoveEmptyWindows_;
|
||||
}
|
||||
|
||||
void ViewController::showExitProgramButton()
|
||||
{
|
||||
for (auto &elem : windowMap)
|
||||
{
|
||||
elem.second->showExitProgramButton();
|
||||
}
|
||||
doesShowExitProgramButton = true;
|
||||
}
|
||||
|
||||
bool ViewController::hasCall(size_t id)
|
||||
{
|
||||
return impl::dataController().hasCall(id);
|
||||
}
|
||||
|
||||
void ViewController::setMode(Mode newMode)
|
||||
{
|
||||
mode = newMode;
|
||||
switch (newMode)
|
||||
{
|
||||
case Mode::NORMAL:
|
||||
break;
|
||||
case Mode::HIDE:
|
||||
hideAll();
|
||||
QApplication::instance()->exit();
|
||||
break;
|
||||
case Mode::FAST_FORWARD:
|
||||
if (!doesShowExitProgramButton)
|
||||
{
|
||||
QApplication::instance()->exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = Mode::NORMAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Mode ViewController::getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void ViewController::updateMode()
|
||||
{
|
||||
if (mode == Mode::FAST_FORWARD && hasFinalCall())
|
||||
{
|
||||
mode = Mode::NORMAL;
|
||||
ovPanel->flushElementBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewController::hideAll()
|
||||
{
|
||||
for (auto &window : windowMap)
|
||||
{
|
||||
window.second->hide();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewController::hasFinalCall()
|
||||
{
|
||||
return doesShowExitProgramButton;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user