GCC Code Coverage Report


Directory: ./
File: src/gui/windows-manager.cc
Date: 2024-12-20 15:53:58
Exec Total Coverage
Lines: 0 163 0.0%
Branches: 0 310 0.0%

Line Branch Exec Source
1 // Copyright (c) 2015-2018, LAAS-CNRS
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4 // This file is part of gepetto-viewer.
5 // gepetto-viewer is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // gepetto-viewer is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // gepetto-viewer. If not, see <http://www.gnu.org/licenses/>.
16
17 #include "gepetto/gui/windows-manager.hh"
18
19 #include <gepetto/viewer/group-node.h>
20 #include <gepetto/viewer/window-manager.h>
21
22 #include <gepetto/gui/bodytreewidget.hh>
23
24 #include "gepetto/gui/mainwindow.hh"
25 #include "gepetto/gui/osgwidget.hh"
26 #include "gepetto/gui/tree-item.hh"
27
28 namespace gepetto {
29 namespace gui {
30 using viewer::ScopedLock;
31
32 Qt::ConnectionType connectionType(QObject* o, int blocking) {
33 if (o->thread() == QThread::currentThread())
34 return Qt::DirectConnection;
35 else if (blocking)
36 return Qt::BlockingQueuedConnection;
37 else
38 return Qt::QueuedConnection;
39 }
40
41 WindowsManagerPtr_t WindowsManager::create(BodyTreeWidget* bodyTree) {
42 return WindowsManagerPtr_t(new WindowsManager(bodyTree));
43 }
44
45 WindowsManager::WindowID WindowsManager::createWindow(QString windowName) {
46 return createWindow(windowName.toStdString());
47 }
48
49 WindowsManager::WindowID WindowsManager::createWindow(
50 const std::string& windowName) {
51 if (getWindowManager(windowName, false)) return windowName;
52 MainWindow* main = MainWindow::instance();
53 OSGWidget* widget;
54 QMetaObject::invokeMethod(main, "createView", connectionType(main, true),
55 Q_RETURN_ARG(OSGWidget*, widget),
56 Q_ARG(std::string, windowName));
57 return widget->windowID();
58 }
59
60 WindowsManager::WindowID WindowsManager::createWindow(
61 const std::string& windowName, gepetto::gui::OSGWidget* widget,
62 osgViewer::Viewer* viewer, osg::GraphicsContext* gc) {
63 if (getWindowManager(windowName, false)) return windowName;
64 viewer::WindowManagerPtr_t newWindow =
65 viewer::WindowManager::create(viewer, gc);
66 WindowID windowId = addWindow(windowName, newWindow);
67 assert(windowId == windowName);
68 widgets_.insert(std::make_pair(windowId, widget));
69 return windowId;
70 }
71
72 WindowsManager::WindowsManager(BodyTreeWidget* bodyTree)
73 : Parent_t(), bodyTree_(bodyTree), refreshIsSynchronous_(false) {}
74
75 void WindowsManager::addNode(const std::string& nodeName, NodePtr_t node,
76 GroupNodePtr_t parent) {
77 Parent_t::addNode(nodeName, node, parent);
78 if (parent) initParent(node, parent, false);
79 }
80
81 void WindowsManager::insertNode(const std::string& nodeName, NodePtr_t node) {
82 ScopedLock lock(osgFrameMutex());
83 addNode(nodeName, node, GroupNodePtr_t());
84 }
85
86 void WindowsManager::addGroup(const std::string& groupName,
87 GroupNodePtr_t group, GroupNodePtr_t parent) {
88 Parent_t::addGroup(groupName, group, parent);
89 if (!parent || !initParent(group, parent, true)) {
90 // Consider it a root group
91 BodyTreeItem* bti = new BodyTreeItem(NULL, group);
92 nodeItemMap_[groupName].first.push_back(bti);
93 nodeItemMap_[groupName].second = true;
94 if (bti->thread() != bodyTree_->thread())
95 bti->moveToThread(bodyTree_->thread());
96 bti->initialize();
97 bodyTree_->model()->appendRow(bti);
98 }
99 }
100
101 void WindowsManager::addToGroup(const std::string& nodeName,
102 const std::string& groupName,
103 const NodePtr_t& node,
104 const BodyTreeItems_t& groups, bool isGroup) {
105 for (std::size_t i = 0; i < groups.size(); ++i) {
106 BodyTreeItem* bti = new BodyTreeItem(NULL, node);
107 nodeItemMap_[nodeName].first.push_back(bti);
108 nodeItemMap_[nodeName].second = isGroup;
109 bti->setParentGroup(groupName);
110 if (bti->thread() != bodyTree_->thread())
111 bti->moveToThread(bodyTree_->thread());
112 bti->initialize();
113 groups[i]->appendRow(bti);
114 }
115 }
116
117 bool WindowsManager::addToGroup(const std::string& nodeName,
118 const std::string& groupName) {
119 if (Parent_t::addToGroup(nodeName, groupName)) {
120 NodePtr_t node = getNode(nodeName, false);
121 bool isGroup = true;
122 try {
123 getGroup(nodeName, true);
124 } catch (const std::invalid_argument& exc) {
125 isGroup = false;
126 }
127 assert(node);
128 BodyTreeItemMap_t::const_iterator _groups = nodeItemMap_.find(groupName);
129 assert(_groups != nodeItemMap_.end());
130 assert(!_groups->second.first.empty());
131 assert(_groups->second.second);
132 assert(getGroup(groupName));
133 addToGroup(nodeName, groupName, node, _groups->second.first, isGroup);
134 return true;
135 }
136 return false;
137 }
138
139 bool WindowsManager::removeFromGroup(const std::string& nodeName,
140 const std::string& groupName) {
141 bool ret = Parent_t::removeFromGroup(nodeName, groupName);
142 if (ret) {
143 BodyTreeItemMap_t::iterator _nodes = nodeItemMap_.find(nodeName);
144 BodyTreeItemMap_t::iterator _groups = nodeItemMap_.find(groupName);
145 assert(_nodes != nodeItemMap_.end());
146 assert(_groups != nodeItemMap_.end());
147 BodyTreeItems_t& nodes = _nodes->second.first;
148 const BodyTreeItems_t& groups = _groups->second.first;
149 bool found = false;
150 for (BodyTreeItems_t::iterator _node = nodes.begin(); _node != nodes.end();
151 ++_node) {
152 BodyTreeItems_t::const_iterator _group = std::find(
153 groups.begin(), groups.end(), (*_node)->QStandardItem::parent());
154 if (_group == groups.end()) continue;
155 bodyTree_->model()->takeRow((*_node)->row());
156 nodes.erase(_node);
157 found = true;
158 break;
159 }
160 if (!found)
161 qDebug() << "Could not find body tree item parent" << groupName.c_str()
162 << "of" << nodeName.c_str();
163 }
164 return ret;
165 }
166
167 bool WindowsManager::deleteNode(const std::string& nodeName, bool all) {
168 bool ret = Parent_t::deleteNode(nodeName, all);
169 if (ret) deleteBodyItem(nodeName);
170 return ret;
171 }
172
173 BodyTreeItems_t WindowsManager::bodyTreeItems(const std::string& name) const {
174 BodyTreeItemMap_t::const_iterator _btis = nodeItemMap_.find(name);
175 if (_btis != nodeItemMap_.end()) return _btis->second.first;
176 return BodyTreeItems_t();
177 }
178
179 void WindowsManager::deleteBodyItem(const std::string& nodeName) {
180 BodyTreeItemMap_t::iterator _nodes = nodeItemMap_.find(nodeName);
181 assert(_nodes != nodeItemMap_.end());
182 for (std::size_t i = 0; i < _nodes->second.first.size(); ++i) {
183 BodyTreeItem* bti = _nodes->second.first[i];
184 QStandardItem* parent = bti->QStandardItem::parent();
185 if (parent == NULL) {
186 bodyTree_->model()->takeRow(bti->row());
187 } else {
188 parent->takeRow(bti->row());
189 }
190 bti->deleteLater();
191 _nodes->second.first[i] = NULL;
192 }
193 nodeItemMap_.erase(_nodes);
194 }
195
196 bool WindowsManager::initParent(NodePtr_t node, GroupNodePtr_t parent,
197 bool isGroup) {
198 BodyTreeItemMap_t::const_iterator _groups =
199 nodeItemMap_.find(parent->getID());
200 if (_groups != nodeItemMap_.end() && _groups->second.second) {
201 assert(!_groups->second.first.empty());
202 addToGroup(node->getID(), parent->getID(), node, _groups->second.first,
203 isGroup);
204 return true;
205 }
206 return false;
207 }
208
209 void WindowsManager::captureFrame(const WindowID wid,
210 const std::string& filename) {
211 WindowManagerPtr_t wm = getWindowManager(wid, true);
212 OSGWidget* widget = widgets_[wid];
213 assert(widget->windowID() == wid);
214 // Here, it is not requred that invokeMethod is blocking. However, it may
215 // be suprising in user script to have this call done later...
216 QMetaObject::invokeMethod(widget, "captureFrame",
217 connectionType(widget, true),
218 Q_ARG(std::string, filename));
219 }
220
221 bool WindowsManager::startCapture(const WindowID wid,
222 const std::string& filename,
223 const std::string& extension) {
224 WindowManagerPtr_t wm = getWindowManager(wid, true);
225 OSGWidget* widget = widgets_[wid];
226 assert(widget->windowID() == wid);
227 bool res;
228 QMetaObject::invokeMethod(
229 widget, "startCapture", connectionType(widget, true),
230 Q_RETURN_ARG(bool, res), Q_ARG(std::string, filename),
231 Q_ARG(std::string, extension));
232 return res;
233 }
234
235 bool WindowsManager::stopCapture(const WindowID wid) {
236 WindowManagerPtr_t wm = getWindowManager(wid, true);
237 OSGWidget* widget = widgets_[wid];
238 assert(widget->windowID() == wid);
239 bool res;
240 QMetaObject::invokeMethod(widget, "stopCapture", connectionType(widget, true),
241 Q_RETURN_ARG(bool, res));
242 return res;
243 }
244
245 struct ApplyConfigurationFunctor {
246 void operator()(const viewer::NodeConfiguration& nc) const {
247 nc.node->applyConfiguration(nc);
248 }
249 };
250
251 void WindowsManager::refresh() {
252 if (refreshIsSynchronous_) {
253 {
254 ScopedLock lock(configListMtx_);
255 {
256 ScopedLock lock(osgFrameMutex());
257 // refresh scene with the new configuration
258 std::for_each(newNodeConfigurations_.begin(),
259 newNodeConfigurations_.end(),
260 ApplyConfigurationFunctor());
261 }
262 newNodeConfigurations_.resize(0);
263 }
264 if (autoCaptureTransform_) captureTransform();
265 } else {
266 {
267 ScopedLock lock1(configsAsyncMtx_);
268 ScopedLock lock2(configListMtx_);
269 if (configsAsync_.size() == 0) {
270 configsAsync_.swap(newNodeConfigurations_);
271 QMetaObject::invokeMethod(this, "asyncRefresh", Qt::QueuedConnection);
272 } else {
273 configsAsync_.insert(configsAsync_.end(),
274 newNodeConfigurations_.begin(),
275 newNodeConfigurations_.end());
276 newNodeConfigurations_.resize(0);
277 // No need to reinvoke asyncRefresh as it hasn't been ran yet.
278 }
279 }
280 }
281 }
282
283 void WindowsManager::asyncRefresh() {
284 NodeConfigurations_t& cfgs = configsAsync_;
285 {
286 ScopedLock lock(configsAsyncMtx_);
287 {
288 ScopedLock lock(osgFrameMutex());
289 // refresh scene with the new configuration
290 std::for_each(cfgs.begin(), cfgs.end(), ApplyConfigurationFunctor());
291 }
292 cfgs.resize(0);
293 }
294 if (autoCaptureTransform_) captureTransform();
295 }
296
297 void WindowsManager::setRefreshIsSynchronous(bool synchonous) {
298 refreshIsSynchronous_ = synchonous;
299 }
300 } // namespace gui
301 } // namespace gepetto
302