GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/gui/windows-manager.cc Lines: 1 167 0.6 %
Date: 2020-05-14 11:23:33 Branches: 2 312 0.6 %

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/window-manager.h>
20
#include <gepetto/viewer/group-node.h>
21
22
#include "gepetto/gui/osgwidget.hh"
23
#include "gepetto/gui/mainwindow.hh"
24
#include "gepetto/gui/tree-item.hh"
25
#include <gepetto/gui/bodytreewidget.hh>
26
27
namespace gepetto {
28
  namespace gui {
29
    using viewer::ScopedLock;
30
31
    Qt::ConnectionType connectionType (QObject* o, int blocking)
32
    {
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
    {
43
      return WindowsManagerPtr_t (new WindowsManager(bodyTree));
44
    }
45
46
    WindowsManager::WindowID WindowsManager::createWindow(QString windowName)
47
    {
48
      return createWindow(windowName.toStdString());
49
    }
50
51
    WindowsManager::WindowID WindowsManager::createWindow(const std::string& windowName)
52
    {
53
      if (getWindowManager(windowName, false))
54
        return windowName;
55
      MainWindow* main = MainWindow::instance();
56
      OSGWidget* widget;
57
      QMetaObject::invokeMethod (main, "createView",
58
          connectionType (main, true),
59
          Q_RETURN_ARG (OSGWidget*, widget),
60
          Q_ARG (std::string, windowName));
61
      return widget->windowID();
62
    }
63
64
    WindowsManager::WindowID WindowsManager::createWindow(const std::string& windowName,
65
                                                          gepetto::gui::OSGWidget* widget,
66
                                                          osgViewer::Viewer *viewer,
67
                                                          osg::GraphicsContext *gc)
68
    {
69
      if (getWindowManager(windowName, false))
70
        return windowName;
71
      viewer::WindowManagerPtr_t newWindow = viewer::WindowManager::create (viewer, gc);
72
      WindowID windowId = addWindow (windowName, newWindow);
73
      assert (windowId == windowName);
74
      widgets_.insert(std::make_pair(windowId, widget));
75
      return windowId;
76
    }
77
78
    WindowsManager::WindowsManager(BodyTreeWidget* bodyTree)
79
      : Parent_t ()
80
      , bodyTree_ (bodyTree)
81
      , refreshIsSynchronous_ (false)
82
    {
83
    }
84
85
    void WindowsManager::addNode(const std::string& nodeName, NodePtr_t node, GroupNodePtr_t parent)
86
    {
87
      Parent_t::addNode (nodeName, node, parent);
88
      if (parent)
89
        initParent(node, parent, false);
90
    }
91
92
    void WindowsManager::insertNode(const std::string& nodeName, NodePtr_t node)
93
    {
94
      ScopedLock lock(osgFrameMutex());
95
      addNode (nodeName, node, GroupNodePtr_t());
96
    }
97
98
    void WindowsManager::addGroup(const std::string& groupName, GroupNodePtr_t group, GroupNodePtr_t parent)
99
    {
100
      Parent_t::addGroup (groupName, group, parent);
101
      if (!parent || !initParent(group, parent, true)) {
102
        // Consider it a root group
103
        BodyTreeItem* bti = new BodyTreeItem (NULL, group);
104
        nodeItemMap_[groupName].first.push_back(bti);
105
        nodeItemMap_[groupName].second = true;
106
        if (bti->thread() != bodyTree_->thread())
107
          bti->moveToThread(bodyTree_->thread());
108
        bti->initialize();
109
        bodyTree_->model()->appendRow(bti);
110
      }
111
    }
112
113
    void WindowsManager::addToGroup (const std::string& nodeName, const std::string& groupName,
114
        const NodePtr_t& node, const BodyTreeItems_t& groups, bool isGroup)
115
    {
116
      for(std::size_t i = 0; i < groups.size(); ++i) {
117
        BodyTreeItem* bti = new BodyTreeItem (NULL, node);
118
        nodeItemMap_[nodeName].first.push_back(bti);
119
        nodeItemMap_[nodeName].second = isGroup;
120
        bti->setParentGroup(groupName);
121
        if (bti->thread() != bodyTree_->thread())
122
          bti->moveToThread(bodyTree_->thread());
123
        bti->initialize();
124
        groups[i]->appendRow(bti);
125
      }
126
    }
127
128
    bool WindowsManager::addToGroup(const std::string& nodeName, const std::string& groupName)
129
    {
130
      if (Parent_t::addToGroup(nodeName, groupName)) {
131
        NodePtr_t node = getNode(nodeName, false);
132
        bool isGroup = true;
133
        try {
134
            getGroup(nodeName, true);
135
        } catch (const std::invalid_argument& exc) {
136
            isGroup = false;
137
        }
138
        assert(node);
139
        BodyTreeItemMap_t::const_iterator _groups = nodeItemMap_.find(groupName);
140
        assert(_groups != nodeItemMap_.end());
141
        assert(!_groups->second.first.empty());
142
        assert(_groups->second.second);
143
        assert(getGroup(groupName));
144
        addToGroup(nodeName, groupName, node, _groups->second.first, isGroup);
145
        return true;
146
      }
147
      return false;
148
    }
149
150
    bool WindowsManager::removeFromGroup (const std::string& nodeName, const std::string& groupName)
151
    {
152
      bool ret = Parent_t::removeFromGroup(nodeName, groupName);
153
      if (ret) {
154
        BodyTreeItemMap_t::iterator _nodes  = nodeItemMap_.find(nodeName);
155
        BodyTreeItemMap_t::iterator _groups = nodeItemMap_.find(groupName);
156
        assert (_nodes  != nodeItemMap_.end());
157
        assert (_groups != nodeItemMap_.end());
158
        BodyTreeItems_t& nodes  = _nodes ->second.first;
159
        const BodyTreeItems_t& groups = _groups->second.first;
160
        bool found = false;
161
        for (BodyTreeItems_t::iterator _node = nodes.begin(); _node != nodes.end(); ++_node) {
162
          BodyTreeItems_t::const_iterator _group = std::find
163
            (groups.begin(), groups.end(), (*_node)->QStandardItem::parent());
164
          if (_group == groups.end()) continue;
165
          bodyTree_->model()->takeRow((*_node)->row());
166
          nodes.erase(_node);
167
          found = true;
168
          break;
169
        }
170
        if (!found)
171
          qDebug() << "Could not find body tree item parent" << groupName.c_str()
172
            << "of" << nodeName.c_str();
173
      }
174
      return ret;
175
    }
176
177
    bool WindowsManager::deleteNode (const std::string& nodeName, bool all)
178
    {
179
      bool ret = Parent_t::deleteNode(nodeName, all);
180
      if (ret) deleteBodyItem(nodeName);
181
      return ret;
182
    }
183
184
    BodyTreeItems_t WindowsManager::bodyTreeItems (const std::string& name) const
185
    {
186
      BodyTreeItemMap_t::const_iterator _btis = nodeItemMap_.find(name);
187
      if (_btis != nodeItemMap_.end())
188
        return _btis->second.first;
189
      return BodyTreeItems_t();
190
    }
191
192
    void WindowsManager::deleteBodyItem(const std::string& nodeName)
193
    {
194
      BodyTreeItemMap_t::iterator _nodes = nodeItemMap_.find(nodeName);
195
      assert (_nodes != nodeItemMap_.end());
196
      for (std::size_t i = 0; i < _nodes->second.first.size(); ++i) {
197
        BodyTreeItem* bti = _nodes->second.first[i];
198
        QStandardItem* parent = bti->QStandardItem::parent();
199
        if (parent == NULL) {
200
          bodyTree_->model()->takeRow(bti->row());
201
        } else {
202
          parent->takeRow(bti->row());
203
        }
204
        bti->deleteLater();
205
        _nodes->second.first[i] = NULL;
206
      }
207
      nodeItemMap_.erase(_nodes);
208
    }
209
210
    bool WindowsManager::initParent (NodePtr_t node,
211
        GroupNodePtr_t parent, bool isGroup)
212
    {
213
      BodyTreeItemMap_t::const_iterator _groups = nodeItemMap_.find(parent->getID());
214
      if (_groups != nodeItemMap_.end() && _groups->second.second) {
215
        assert(!_groups->second.first.empty());
216
        addToGroup(node->getID(), parent->getID(), node, _groups->second.first, isGroup);
217
        return true;
218
      }
219
      return false;
220
    }
221
222
    void WindowsManager::captureFrame (const WindowID wid, const std::string& filename)
223
    {
224
      WindowManagerPtr_t wm = getWindowManager(wid, true);
225
      OSGWidget* widget = widgets_[wid];
226
      assert(widget->windowID()==wid);
227
      // Here, it is not requred that invokeMethod is blocking. However, it may
228
      // be suprising in user script to have this call done later...
229
      QMetaObject::invokeMethod (widget, "captureFrame",
230
          connectionType (widget, true),
231
          Q_ARG (std::string, filename));
232
    }
233
234
    bool WindowsManager::startCapture (const WindowID wid, const std::string& filename,
235
            const std::string& extension)
236
    {
237
      WindowManagerPtr_t wm = getWindowManager(wid, true);
238
      OSGWidget* widget = widgets_[wid];
239
      assert(widget->windowID()==wid);
240
      bool res;
241
      QMetaObject::invokeMethod (widget, "startCapture",
242
          connectionType (widget, true),
243
          Q_RETURN_ARG (bool, res),
244
          Q_ARG (std::string, filename),
245
          Q_ARG (std::string, extension));
246
      return res;
247
    }
248
249
    bool WindowsManager::stopCapture (const WindowID wid)
250
    {
251
      WindowManagerPtr_t wm = getWindowManager(wid, true);
252
      OSGWidget* widget = widgets_[wid];
253
      assert(widget->windowID()==wid);
254
      bool res;
255
      QMetaObject::invokeMethod (widget, "stopCapture",
256
          connectionType (widget, true),
257
          Q_RETURN_ARG (bool, res));
258
      return res;
259
    }
260
261
    struct ApplyConfigurationFunctor
262
    {
263
      void operator() (const viewer::NodeConfiguration& nc) const
264
      {
265
        nc.node->applyConfiguration (nc);
266
      }
267
    };
268
269
    void WindowsManager::refresh ()
270
    {
271
      if (refreshIsSynchronous_) {
272
        {
273
          ScopedLock lock(configListMtx_);
274
          {
275
            ScopedLock lock(osgFrameMutex());
276
            //refresh scene with the new configuration
277
            std::for_each(newNodeConfigurations_.begin(),
278
                newNodeConfigurations_.end(), ApplyConfigurationFunctor());
279
          }
280
          newNodeConfigurations_.resize (0);
281
        }
282
        if (autoCaptureTransform_) captureTransform ();
283
      } else {
284
        {
285
          ScopedLock lock1(configsAsyncMtx_);
286
          ScopedLock lock2(configListMtx_);
287
          if (configsAsync_.size() == 0) {
288
            configsAsync_.swap (newNodeConfigurations_);
289
            QMetaObject::invokeMethod (this, "asyncRefresh", Qt::QueuedConnection);
290
          } else {
291
            configsAsync_.insert (configsAsync_.end(),
292
                newNodeConfigurations_.begin(),
293
                newNodeConfigurations_.end());
294
            newNodeConfigurations_.resize(0);
295
            // No need to reinvoke asyncRefresh as it hasn't been ran yet.
296
          }
297
        }
298
      }
299
    }
300
301
    void WindowsManager::asyncRefresh ()
302
    {
303
      NodeConfigurations_t& cfgs = configsAsync_;
304
      {
305
        ScopedLock lock(configsAsyncMtx_);
306
        {
307
          ScopedLock lock(osgFrameMutex());
308
          //refresh scene with the new configuration
309
          std::for_each(cfgs.begin(), cfgs.end(), ApplyConfigurationFunctor());
310
        }
311
        cfgs.resize (0);
312
      }
313
      if (autoCaptureTransform_) captureTransform ();
314
    }
315
316
    void WindowsManager::setRefreshIsSynchronous (bool synchonous)
317
    {
318
      refreshIsSynchronous_ = synchonous;
319
    }
320
  } // namespace gui
321

3
} // namespace gepetto