1 #include "view_controller.hpp"
2 
3 #include <stdexcept>
4 #include <iostream>
5 
6 #include <QApplication>
7 #include <QDesktopServices>
8 #include <QUrl>
9 
10 #include "../gui/call_tab.hpp"
11 #include "../gui/call_window.hpp"
12 #include "../gui/overview_panel.hpp"
13 #include "../gui/main_call_window.hpp"
14 #include "../gui/filter_call_tab.hpp"
15 #include "../gui/match_call_tab.hpp"
16 #include "../gui/image_call_tab.hpp"
17 #include "../impl/init.hpp"
18 #include "../impl/filter_call.hpp"
19 #include "../impl/match_call.hpp"
20 #include "../impl/single_image_call.hpp"
21 #include "../impl/data_controller.hpp"
22 #include "../qtutil/util.hpp"
23 
24 namespace cvv
25 {
26 namespace controller
27 {
28 
29 // It's only used for instatiating a QApplication.
30 // static char *emptyArray[] = {""};
__anon658048c20102null31 static char *parameterSystemV[] = { new char[1]{ 0 }, nullptr };
32 static int parameterSystemC = 1;
33 
ViewController()34 ViewController::ViewController()
35 {
36 	impl::initializeFilterAndViews();
37 	if (!QApplication::instance())
38 	{
39 		auto tmp =
40 		    new QApplication{ parameterSystemC, parameterSystemV };
41 		ownsQApplication = true;
42 		(void)tmp;
43 	}
44 	ovPanel = new gui::OverviewPanel{ util::makeRef(*this) };
45 	mainWindow = new gui::MainCallWindow(util::makeRef(*this), 0, ovPanel);
46 	windowMap[0] = std::unique_ptr<gui::CallWindow>(mainWindow);
47 	max_window_id = 0;
48 	mainWindow->show();
49 }
50 
~ViewController()51 ViewController::~ViewController()
52 {
53 	callTabMap.clear();
54 	windowMap.clear();
55 	windowMap.clear();
56 	if (ownsQApplication)
57 	{
58 		delete QApplication::instance();
59 	}
60 }
61 
addCallType(const QString typeName,TabFactory constr)62 void ViewController::addCallType(const QString typeName, TabFactory constr)
63 {
64 	ViewController::callTabType[typeName] = constr;
65 }
66 
67 static std::unique_ptr<cvv::gui::FilterCallTab>
makeFilterCallTab(cvv::util::Reference<cvv::impl::Call> call)68 makeFilterCallTab(cvv::util::Reference<cvv::impl::Call> call)
69 {
70 	return cvv::util::make_unique<cvv::gui::FilterCallTab>(
71 	    *call.castTo<cvv::impl::FilterCall>());
72 }
73 
74 static std::unique_ptr<cvv::gui::MatchCallTab>
makeMatchCallTab(cvv::util::Reference<cvv::impl::Call> call)75 makeMatchCallTab(cvv::util::Reference<cvv::impl::Call> call)
76 {
77 	return cvv::util::make_unique<cvv::gui::MatchCallTab>(
78 	    *call.castTo<cvv::impl::MatchCall>());
79 }
80 
81 static std::unique_ptr<cvv::gui::ImageCallTab>
makeImageCallTab(cvv::util::Reference<cvv::impl::Call> call)82 makeImageCallTab(cvv::util::Reference<cvv::impl::Call> call)
83 {
84 	return cvv::util::make_unique<cvv::gui::ImageCallTab>(
85 	    *call.castTo<cvv::impl::SingleImageCall>());
86 }
87 
88 std::map<QString, TabFactory> ViewController::callTabType{
89 	{ "filter", makeFilterCallTab }, { "match", makeMatchCallTab },
90 	{ "singleImage", makeImageCallTab }
91 };
92 
addCall(util::Reference<impl::Call> data)93 void ViewController::addCall(util::Reference<impl::Call> data)
94 {
95 	updateMode();
96 	if (mode == Mode::NORMAL)
97 	{
98 		ovPanel->addElement(*data);
99 		mainWindow->showOverviewTab();
100 	}
101 	else if (mode == Mode::FAST_FORWARD)
102 	{
103 		ovPanel->addElementBuffered(*data);
104 	}
105 }
106 
exec()107 void ViewController::exec()
108 {
109 	updateMode();
110 	if (mode == Mode::NORMAL)
111 	{
112 		QApplication::instance()->exec();
113 	}
114 }
115 
getCall(size_t id)116 impl::Call &ViewController::getCall(size_t id)
117 {
118 	return impl::dataController().getCall(id);
119 }
120 
getSetting(const QString & scope,const QString & key)121 QString ViewController::getSetting(const QString &scope, const QString &key)
122 {
123 	return qtutil::getSetting(scope, key);
124 }
125 
getTabWindows()126 std::vector<util::Reference<gui::CallWindow>> ViewController::getTabWindows()
127 {
128 	std::vector<util::Reference<gui::CallWindow>> windows{};
129 	for (auto &it : windowMap)
130 	{
131 		windows.push_back(util::makeRef(*(it.second)));
132 	}
133 	return windows;
134 }
135 
getMainWindow()136 util::Reference<gui::MainCallWindow> ViewController::getMainWindow()
137 {
138 	return util::makeRef(*mainWindow);
139 }
140 
moveCallTabToNewWindow(size_t tabId)141 void ViewController::moveCallTabToNewWindow(size_t tabId)
142 {
143 	if (!hasCall(tabId))
144 		return;
145 	auto newWindow = util::make_unique<gui::CallWindow>(
146 	    util::makeRef<ViewController>(*this), ++max_window_id);
147 	removeCallTab(tabId);
148 	newWindow->addTab(getCallTab(tabId));
149 	newWindow->show();
150 	if (doesShowExitProgramButton)
151 	{
152 		newWindow->showExitProgramButton();
153 	}
154 	windowMap[max_window_id] = std::move(newWindow);
155 	removeEmptyWindowsWithDelay();
156 }
157 
moveCallTabToWindow(size_t tabId,size_t windowId)158 void ViewController::moveCallTabToWindow(size_t tabId, size_t windowId)
159 {
160 	if (!hasCall(tabId))
161 		return;
162 	removeCallTab(tabId);
163 	auto tab = getCallTab(tabId);
164 	windowMap[windowId]->addTab(tab);
165 	removeEmptyWindowsWithDelay();
166 }
167 
removeCallTab(size_t tabId,bool deleteIt,bool deleteCall,bool updateUI)168 void ViewController::removeCallTab(size_t tabId, bool deleteIt, bool deleteCall, bool updateUI)
169 {
170 	auto *curWindow = getCurrentWindowOfTab(tabId);
171 	if (curWindow->hasTab(tabId))
172 	{
173 		getCurrentWindowOfTab(tabId)->removeTab(tabId);
174 		if (deleteIt)
175 		{
176 			callTabMap.erase(tabId);
177 		}
178 	}
179 	if (deleteCall && hasCall(tabId))
180 	{
181 		if (updateUI)
182 		{
183 			ovPanel->removeElement(tabId);
184 		}
185 		impl::dataController().removeCall(tabId);
186 	}
187 	removeEmptyWindowsWithDelay();
188 }
189 
openHelpBrowser(const QString & topic)190 void ViewController::openHelpBrowser(const QString &topic)
191 {
192 	qtutil::openHelpBrowser(topic);
193 }
194 
resumeProgramExecution()195 void ViewController::resumeProgramExecution()
196 {
197 	QApplication::instance()->exit();
198 }
199 
setDefaultSetting(const QString & scope,const QString & key,const QString & value)200 void ViewController::setDefaultSetting(const QString &scope, const QString &key,
201                                        const QString &value)
202 {
203 	qtutil::setDefaultSetting(scope, key, value);
204 }
205 
setSetting(const QString & scope,const QString & key,const QString & value)206 void ViewController::setSetting(const QString &scope, const QString &key,
207                                 const QString &value)
208 {
209 	qtutil::setSetting(scope, key, value);
210 }
211 
showCallTab(size_t tabId)212 void ViewController::showCallTab(size_t tabId)
213 {
214 	auto *window = getCurrentWindowOfTab(tabId);
215 	window->showTab(tabId);
216 	window->setWindowState((window->windowState() & ~Qt::WindowMinimized) |
217 	                       Qt::WindowActive);
218 	window->raise();
219 }
220 
showAndOpenCallTab(size_t tabId)221 void ViewController::showAndOpenCallTab(size_t tabId)
222 {
223 	auto curWindow = getCurrentWindowOfTab(tabId);
224 	if (!curWindow->hasTab(tabId))
225 	{
226 		moveCallTabToWindow(tabId, 0);
227 		curWindow = mainWindow;
228 	}
229 	curWindow->showTab(tabId);
230 }
231 
openCallTab(size_t tabId)232 void ViewController::openCallTab(size_t tabId)
233 {
234 	auto curWindow = getCurrentWindowOfTab(tabId);
235 	if (!curWindow->hasTab(tabId))
236 	{
237 		moveCallTabToWindow(tabId, 0);
238 		curWindow = mainWindow;
239 	}
240 }
241 
showOverview()242 void ViewController::showOverview()
243 {
244 	mainWindow->setWindowState(
245 	    (mainWindow->windowState() & ~Qt::WindowMinimized) |
246 	    Qt::WindowActive);
247 	mainWindow->raise();
248 	mainWindow->showOverviewTab();
249 }
250 
getCurrentWindowOfTab(size_t tabId)251 gui::CallWindow *ViewController::getCurrentWindowOfTab(size_t tabId)
252 {
253 	for (auto &elem : windowMap)
254 	{
255 		if (elem.second->hasTab(tabId))
256 		{
257 			return elem.second.get();
258 		}
259 	}
260 	return mainWindow;
261 }
262 
getCallTab(size_t tabId)263 gui::CallTab *ViewController::getCallTab(size_t tabId)
264 {
265 	if (callTabMap.count(tabId) == 0)
266 	{
267 		auto *call = &(getCall(tabId));
268 		if (callTabType.count(call->type()) == 0)
269 		{
270 			throw std::invalid_argument{
271 				"no such type '" + call->type().toStdString() +
272 				"'"
273 			};
274 		}
275 		callTabMap[tabId] =
276 		    callTabType[call->type()](util::makeRef(*call));
277 	}
278 	return callTabMap[tabId].get();
279 }
280 
removeWindowFromMaps(size_t windowId)281 void ViewController::removeWindowFromMaps(size_t windowId)
282 {
283 	if (windowMap.count(windowId) > 0)
284 	{
285 		windowMap[windowId].release();
286 		windowMap.erase(windowId);
287 	}
288 }
289 
removeEmptyWindows()290 void ViewController::removeEmptyWindows()
291 {
292 	std::vector<size_t> remIds{};
293 	for (auto &elem : windowMap)
294 	{
295 		if (elem.second->tabCount() == 0 && elem.second->getId() != 0)
296 		{
297 			remIds.push_back(elem.first);
298 		}
299 	}
300 	for (auto windowId : remIds)
301 	{
302 		auto window = windowMap[windowId].release();
303 		windowMap.erase(windowId);
304 		window->deleteLater();
305 	}
306 	shouldRunRemoveEmptyWindows_ = false;
307 }
308 
removeEmptyWindowsWithDelay()309 void ViewController::removeEmptyWindowsWithDelay()
310 {
311 	shouldRunRemoveEmptyWindows_ = true;
312 }
313 
shouldRunRemoveEmptyWindows()314 bool ViewController::shouldRunRemoveEmptyWindows()
315 {
316 	return shouldRunRemoveEmptyWindows_;
317 }
318 
showExitProgramButton()319 void ViewController::showExitProgramButton()
320 {
321 	for (auto &elem : windowMap)
322 	{
323 		elem.second->showExitProgramButton();
324 	}
325 	doesShowExitProgramButton = true;
326 }
327 
hasCall(size_t id)328 bool ViewController::hasCall(size_t id)
329 {
330 	return impl::dataController().hasCall(id);
331 }
332 
setMode(Mode newMode)333 void ViewController::setMode(Mode newMode)
334 {
335 	mode = newMode;
336 	switch (newMode)
337 	{
338 	case Mode::NORMAL:
339 		break;
340 	case Mode::HIDE:
341 		hideAll();
342 		QApplication::instance()->exit();
343 		break;
344 	case Mode::FAST_FORWARD:
345 		if (!doesShowExitProgramButton)
346 		{
347 			QApplication::instance()->exit();
348 		}
349 		else
350 		{
351 			mode = Mode::NORMAL;
352 		}
353 		break;
354 	}
355 }
356 
getMode()357 Mode ViewController::getMode()
358 {
359 	return mode;
360 }
361 
updateMode()362 void ViewController::updateMode()
363 {
364 	if (mode == Mode::FAST_FORWARD && hasFinalCall())
365 	{
366 		mode = Mode::NORMAL;
367 		ovPanel->flushElementBuffer();
368 	}
369 }
370 
hideAll()371 void ViewController::hideAll()
372 {
373 	for (auto &window : windowMap)
374 	{
375 		window.second->hide();
376 	}
377 }
378 
hasFinalCall()379 bool ViewController::hasFinalCall()
380 {
381 	return doesShowExitProgramButton;
382 }
383 }
384 }
385