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