GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/gui/windows-manager.cc Lines: 0 162 0.0 %
Date: 2023-03-14 11:04:37 Branches: 0 306 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