dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
uavgadgetmanager.cpp
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  *
28  * Additional note on redistribution: The copyright and license notices above
29  * must be maintained in each individual source file that is a derivative work
30  * of this source file; otherwise redistribution is prohibited.
31  */
32 
33 #include "uavgadgetmanager.h"
34 #include "uavgadgetview.h"
35 #include "splitterorview.h"
37 #include "iuavgadgetfactory.h"
38 #include "iuavgadget.h"
39 #include "icore.h"
40 
42 #include <coreplugin/modemanager.h>
45 #include <coreplugin/baseview.h>
46 #include <coreplugin/imode.h>
47 
49 
50 #include <utils/qtcassert.h>
51 
52 #include <QtCore/QDebug>
53 #include <QtCore/QMap>
54 #include <QtCore/QProcess>
55 #include <QtCore/QSet>
56 
57 #include <QAction>
58 #include <QApplication>
59 #include <QLayout>
60 #include <QMainWindow>
61 #include <QMenu>
62 #include <QPushButton>
63 #include <QSplitter>
64 #include <QStackedLayout>
65 
67 
68 using namespace Core;
69 using namespace Core::Internal;
70 using namespace Utils;
71 
72 enum { debugUAVGadgetManager = 0 };
73 
74 UAVGadgetManager::UAVGadgetManager(ICore *core, QString name, QIcon icon, int priority,
75  QString uniqueName, QWidget *parent)
76  : m_showToolbars(true)
77  , m_splitterOrView(nullptr)
78  , m_currentGadget(nullptr)
79  , m_core(core)
80  , m_name(name)
81  , m_icon(icon)
82  , m_priority(priority)
83  , m_widget(new QWidget(parent))
84 {
85 
86  // checking that the mode name is unique gives harmless
87  // warnings on the console output
88  ModeManager *modeManager = ModeManager::instance();
89  if (!modeManager->mode(uniqueName)) {
90  m_uniqueName = uniqueName;
91  } else {
92  // this shouldn't happen
93  m_uniqueName = uniqueName + QString::number(quint64(this));
94  }
95  m_uniqueNameBA = m_uniqueName.toLatin1();
96  m_uniqueModeName = m_uniqueNameBA.data();
97 
98  connect(m_core, SIGNAL(contextAboutToChange(Core::IContext *)), this,
99  SLOT(handleContextChange(Core::IContext *)));
100 
101  connect(modeManager, SIGNAL(currentModeChanged(Core::IMode *)), this,
102  SLOT(modeChanged(Core::IMode *)));
103 
104  // other setup
105  m_splitterOrView = new SplitterOrView(this, nullptr, true);
106 
107  // SplitterOrView with 0 as gadget calls our setCurrentGadget, which relies on
108  // currentSplitterOrView(),
109  // which needs our m_splitterorView to be set, which isn't set yet at that time.
110  // So directly set our currentGadget to 0, and do it again.
111  m_currentGadget = nullptr;
112  setCurrentGadget(m_splitterOrView->view()->gadget());
113 
114  QHBoxLayout *layout = new QHBoxLayout(m_widget);
115  layout->setMargin(0);
116  layout->setSpacing(0);
117  layout->addWidget(m_splitterOrView);
118 
119  showToolbars(m_showToolbars);
120 }
121 
123 {
124 }
125 
127 {
128  static QList<int> contexts = QList<int>()
130  return contexts;
131 }
132 
133 void UAVGadgetManager::modeChanged(Core::IMode *mode)
134 {
135  if (mode != this)
136  return;
137 
138  if (!m_currentGadget) {
139  m_splitterOrView->view()->doReplaceGadget(0);
140  }
141 
142  m_currentGadget->widget()->setFocus();
144 }
145 
147 {
149  context << m_core->uniqueIDManager()->uniqueIdentifier("OpenPilot.UAVGadgetManager");
150 }
151 
152 void UAVGadgetManager::handleContextChange(Core::IContext *context)
153 {
154  // if (debugUAVGadgetManager)
155  // qDebug() << Q_FUNC_INFO << context;
156  IUAVGadget *uavGadget = context ? qobject_cast<IUAVGadget *>(context) : 0;
157  if (uavGadget)
158  setCurrentGadget(uavGadget);
159 }
160 
161 void UAVGadgetManager::setCurrentGadget(IUAVGadget *uavGadget)
162 {
163  if (m_currentGadget == uavGadget)
164  return;
165 
166  SplitterOrView *oldView = currentSplitterOrView();
167  m_currentGadget = uavGadget;
168  SplitterOrView *view = currentSplitterOrView();
169  if (oldView != view) {
170  if (oldView)
171  oldView->update();
172  if (view)
173  view->update();
174  }
175  uavGadget->widget()->setFocus();
176  emit currentGadgetChanged(uavGadget);
177 }
178 
179 /* Contract: return current SplitterOrView.
180  * Implications: must not return SplitterOrView that is splitter.
181  */
182 Core::Internal::SplitterOrView *UAVGadgetManager::currentSplitterOrView() const
183 {
184  if (!m_splitterOrView) // this is only for startup
185  return nullptr;
186  SplitterOrView *view = m_currentGadget ? m_splitterOrView->findView(m_currentGadget) : nullptr;
187  return view;
188 }
189 
191 {
192  return m_currentGadget;
193 }
194 
195 void UAVGadgetManager::emptyView(Core::Internal::UAVGadgetView *view)
196 {
197  if (!view)
198  return;
199 
200  IUAVGadget *uavGadget = view->gadget();
201  // emit uavGadgetAboutToClose(uavGadget);
202  removeGadget(uavGadget);
203  view->removeGadget();
204  // emit uavGadgetsClosed(uavGadgets);
205 }
206 
207 void UAVGadgetManager::closeView(Core::Internal::UAVGadgetView *view)
208 {
209  if (!view)
210  return;
211  SplitterOrView *splitterOrView = m_splitterOrView->findView(view);
212  Q_ASSERT(splitterOrView);
213  Q_ASSERT(splitterOrView->view() == view);
214  if (splitterOrView == m_splitterOrView)
215  return;
216 
217  IUAVGadget *gadget = view->gadget();
218  emptyView(view);
219  UAVGadgetInstanceManager *im = ICore::instance()->uavGadgetInstanceManager();
220  im->removeGadget(gadget);
221 
222  SplitterOrView *splitter = m_splitterOrView->findSplitter(splitterOrView);
223  Q_ASSERT(splitterOrView->hasGadget() == false);
224  Q_ASSERT(splitter->isSplitter() == true);
225  splitterOrView->hide();
226  delete splitterOrView;
227 
228  splitter->unsplit();
229 
230  SplitterOrView *newCurrent = splitter->findFirstView();
231  Q_ASSERT(newCurrent);
232  if (newCurrent)
233  setCurrentGadget(newCurrent->gadget());
234 }
235 
236 void UAVGadgetManager::addGadgetToContext(IUAVGadget *gadget)
237 {
238  if (!gadget)
239  return;
240  m_core->addContextObject(gadget);
241 
242  // emit uavGadgetOpened(uavGadget);
243 }
244 
245 void UAVGadgetManager::removeGadget(IUAVGadget *gadget)
246 {
247  if (!gadget)
248  return;
249  m_core->removeContextObject(qobject_cast<IContext *>(gadget));
250 }
251 
253 {
254  if (!m_widget->isVisible())
255  m_core->modeManager()->activateMode(this->uniqueModeName());
256 }
257 
259 {
260  if (m_core->modeManager()->currentMode() != this)
261  return;
262 
263  m_showToolbars = show;
264  SplitterOrView *next = m_splitterOrView->findFirstView();
265  do {
266  next->view()->showToolbar(show);
267  next = m_splitterOrView->findNextView(next);
268  } while (next);
269 
270  updateUavGadgetMenus();
271 }
272 
273 void UAVGadgetManager::updateUavGadgetMenus()
274 {
275  if (m_core->modeManager()->currentMode() != this)
276  return;
277  if (!m_splitterOrView) // this is only for startup
278  return;
279  // Splitting is only possible when the toolbars are shown
280  bool hasSplitter = m_splitterOrView->isSplitter();
281  emit showUavGadgetMenus(m_showToolbars, hasSplitter);
282 }
283 
284 void UAVGadgetManager::saveState(QSettings *qSettings) const
285 {
286  qSettings->setValue("version", "UAVGadgetManagerV1");
287  qSettings->setValue("showToolbars", m_showToolbars);
288  qSettings->beginGroup("splitter");
289  m_splitterOrView->saveState(qSettings);
290  qSettings->endGroup();
291 }
292 
293 bool UAVGadgetManager::restoreState(QSettings *qSettings)
294 {
295  removeAllSplits();
296 
298  IUAVGadget *gadget = m_splitterOrView->view()->gadget();
299  emptyView(m_splitterOrView->view());
300  im->removeGadget(gadget);
301 
302  QString version = qSettings->value("version").toString();
303  if (version != "UAVGadgetManagerV1") {
304  return false;
305  }
306 
307  m_showToolbars = qSettings->value("showToolbars").toBool();
308 
309  QApplication::setOverrideCursor(Qt::WaitCursor);
310 
311  qSettings->beginGroup("splitter");
312  m_splitterOrView->restoreState(qSettings);
313  qSettings->endGroup();
314 
315  QApplication::restoreOverrideCursor();
316  return true;
317 }
318 
320 {
321  qs->beginGroup("UAVGadgetManager");
322  qs->beginGroup(this->uniqueModeName());
323 
324  // Make sure the old tree is wiped.
325  qs->remove("");
326 
327  // Do actual saving
328  saveState(qs);
329 
330  qs->endGroup();
331  qs->endGroup();
332 }
333 
335 {
336  QString uavGadgetManagerRootKey = "UAVGadgetManager";
337  if (!qs->childGroups().contains(uavGadgetManagerRootKey)) {
338  return;
339  }
340  qs->beginGroup(uavGadgetManagerRootKey);
341 
342  if (!qs->childGroups().contains(uniqueModeName())) {
343  qs->endGroup();
344  return;
345  }
346  qs->beginGroup(uniqueModeName());
347 
348  restoreState(qs);
349 
350  showToolbars(m_showToolbars);
351 
352  qs->endGroup();
353  qs->endGroup();
354 }
355 
356 void UAVGadgetManager::split(Qt::Orientation orientation)
357 {
358  if (m_core->modeManager()->currentMode() != this)
359  return;
360 
361  IUAVGadget *uavGadget = m_currentGadget;
362  Q_ASSERT(uavGadget);
363  SplitterOrView *view = currentSplitterOrView();
364  Q_ASSERT(view);
365  view->split(orientation);
366 
367  SplitterOrView *sor = m_splitterOrView->findView(uavGadget);
368  SplitterOrView *next = m_splitterOrView->findNextView(sor);
369  setCurrentGadget(next->gadget());
370  updateUavGadgetMenus();
371 }
372 
374 {
375  split(Qt::Vertical);
376 }
377 
379 {
380  split(Qt::Horizontal);
381 }
382 
384 {
385  if (m_core->modeManager()->currentMode() != this)
386  return;
387 
388  SplitterOrView *viewToClose = currentSplitterOrView();
389  if (viewToClose == m_splitterOrView)
390  return;
391  closeView(viewToClose->view());
392  updateUavGadgetMenus();
393 }
394 
395 // Removes all gadgets and splits in the workspace, except the current/active gadget.
397 {
398  if (m_core->modeManager()->currentMode() != this)
399  return;
400 
401  if (!m_splitterOrView->isSplitter())
402  return;
403 
404  // Use a QPointer, just in case we accidently delete the gadget we want to keep.
405  QPointer<IUAVGadget> currentGadget = m_currentGadget;
406 
407  Q_ASSERT(currentGadget);
408  QList<IUAVGadget *> gadgets = m_splitterOrView->gadgets();
409  Q_ASSERT(gadgets.count(currentGadget) == 1);
410  gadgets.removeOne(currentGadget);
411 
412  // Remove all splits and their gadgets, then create a new view with the current gadget.
413  m_splitterOrView->unsplitAll(currentGadget);
414 
415  // Zeroing the current gadget means setCurrentGadget will do something when we call it.
416  m_currentGadget = nullptr;
417  setCurrentGadget(currentGadget);
418 
419  // Remove all other gadgets from the instance manager.
421  foreach (IUAVGadget *g, gadgets) {
422  im->removeGadget(g);
423  }
424  updateUavGadgetMenus();
425 }
426 
428 {
429  if (m_core->modeManager()->currentMode() != this)
430  return;
431 
432  if (m_splitterOrView->isSplitter()) {
433  SplitterOrView *currentView = currentSplitterOrView();
434  SplitterOrView *view = m_splitterOrView->findNextView(currentView);
435  if (!view)
436  view = m_splitterOrView->findFirstView();
437  if (view) {
438  setCurrentGadget(view->gadget());
439  }
440  }
441 }
QList< int > context() const
static UniqueIDManager * instance()
IUAVGadget * currentGadget() const
virtual void addContextObject(IContext *context)=0
Registers an additional context object.
void split(Qt::Orientation orientation, bool restoring=false)
int uniqueIdentifier(const QString &id)
QList< Core::IUAVGadget * > gadgets()
static ModeManager * instance()
Definition: modemanager.h:62
void doReplaceGadget(int index)
Slot called when the user changes the selected gadget on the view's dropbox.
SplitterOrView * findSplitter(Core::IUAVGadget *uavGadget)
void saveState(QSettings *) const
Core::IUAVGadget * gadget() const
UAVGadgetView * view() const
The ICore class allows access to the different part that make up the basic functionality of the GCS...
Definition: icore.h:58
void unsplitAll(IUAVGadget *currentGadget)
IUAVGadget * gadget() const
virtual QWidget * widget()=0
void readSettings(QSettings *qs)
IMode * mode(const QString &id) const
IMode * currentMode() const
Definition: modemanager.cpp:94
bool hasGadget(Core::IUAVGadget *uavGadget) const
void showUavGadgetMenus(bool show, bool hasSplitter)
void saveSettings(QSettings *qs)
void saveState(QSettings *) const
static ICore * instance()
Definition: coreimpl.cpp:46
void showToolbars(bool show)
SplitterOrView * findView(Core::IUAVGadget *uavGadget)
virtual void removeContextObject(IContext *context)=0
Unregisters a context object from the list of know contexts.
const char * uniqueModeName() const
const char *const C_UAVGADGETMANAGER
Definition: coreconstants.h:93
SplitterOrView * findNextView(SplitterOrView *view)
Q_DECLARE_METATYPE(Core::IUAVGadget *) using namespace Core
virtual ModeManager * modeManager() const =0
Returns the application's mode manager.
void currentGadgetChanged(IUAVGadget *gadget)
virtual UniqueIDManager * uniqueIDManager() const =0
Returns the application's id manager.
void activateMode(const QString &id)
SplitterOrView * findFirstView()
virtual UAVGadgetInstanceManager * uavGadgetInstanceManager() const =0
bool restoreState(QSettings *qSettings)