diff --git a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetdecorator.cpp b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetdecorator.cpp index e9111c1b4..bca700785 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetdecorator.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetdecorator.cpp @@ -44,7 +44,7 @@ UAVGadgetDecorator::UAVGadgetDecorator(IUAVGadget *gadget, QListsetMinimumContentsLength(15); foreach(IUAVGadgetConfiguration * config, *m_configurations) m_toolbar->addItem(config->name()); - connect(m_toolbar, SIGNAL(activated(int)), this, SLOT(loadConfiguration(int))); + connect(m_toolbar, SIGNAL(currentIndexChanged(int)), this, SLOT(loadConfiguration(int))); updateToolbar(); } @@ -63,15 +63,22 @@ void UAVGadgetDecorator::loadConfiguration(int index) void UAVGadgetDecorator::loadConfiguration(IUAVGadgetConfiguration *config) { + if (m_activeConfiguration == config) { + return; + } m_activeConfiguration = config; int index = m_toolbar->findText(config->name()); - m_toolbar->setCurrentIndex(index); + if (m_toolbar->currentIndex() != index) { + m_toolbar->setCurrentIndex(index); + } m_gadget->loadConfiguration(config); } void UAVGadgetDecorator::configurationChanged(IUAVGadgetConfiguration *config) { if (config == m_activeConfiguration) { + // force a configuration reload + m_activeConfiguration = NULL; loadConfiguration(config); } } @@ -133,7 +140,6 @@ void UAVGadgetDecorator::restoreState(QSettings *qSettings) foreach(IUAVGadgetConfiguration * config, *m_configurations) { if (config->name() == configName) { - m_activeConfiguration = config; loadConfiguration(config); break; } diff --git a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetinstancemanager.cpp b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetinstancemanager.cpp index 89b31bf08..17bf5a187 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetinstancemanager.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetinstancemanager.cpp @@ -166,7 +166,7 @@ void UAVGadgetInstanceManager::readConfigs_1_1_0(QSettings *qs) configs = qs->childGroups(); foreach(QString configName, configs) { - qDebug() << "Loading config: " << classId << "," << configName; + qDebug().nospace() << "Loading config: " << classId << ", " << configName; qs->beginGroup(configName); bool locked = qs->value("config.locked").toBool(); configInfo.setNameOfConfigurable(classId + "-" + configName); diff --git a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.cpp b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.cpp index e9868b4a3..ed84b65d7 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.cpp @@ -34,7 +34,6 @@ #include - #ifdef Q_WS_MAC #include #endif @@ -46,22 +45,28 @@ SplitterOrView::SplitterOrView(Core::UAVGadgetManager *uavGadgetManager, Core::I m_uavGadgetManager(uavGadgetManager), m_splitter(0) { - m_view = new UAVGadgetView(m_uavGadgetManager, uavGadget, this); - m_layout = new QStackedLayout(this); - m_layout->addWidget(m_view); + m_view = new UAVGadgetView(m_uavGadgetManager, uavGadget, this); + setLayout(new QStackedLayout()); + layout()->addWidget(m_view); +} + +SplitterOrView::SplitterOrView(SplitterOrView &splitterOrView, QWidget *parent) : + QWidget(parent), + m_uavGadgetManager(splitterOrView.m_uavGadgetManager), + m_view(splitterOrView.m_view), + m_splitter(splitterOrView.m_splitter) +{ + Q_ASSERT((m_view || m_splitter) && !(m_view && m_splitter)); + setLayout(new QStackedLayout()); + if (m_view) { + layout()->addWidget(m_view); + } else if (m_splitter) { + layout()->addWidget(m_splitter); + } } SplitterOrView::~SplitterOrView() -{ - if (m_view) { - delete m_view; - m_view = 0; - } - if (m_splitter) { - delete m_splitter; - m_splitter = 0; - } -} +{} void SplitterOrView::mousePressEvent(QMouseEvent *e) { @@ -221,7 +226,7 @@ QSplitter *SplitterOrView::takeSplitter() QSplitter *oldSplitter = m_splitter; if (m_splitter) { - m_layout->removeWidget(m_splitter); + layout()->removeWidget(m_splitter); } m_splitter = 0; return oldSplitter; @@ -232,7 +237,7 @@ UAVGadgetView *SplitterOrView::takeView() UAVGadgetView *oldView = m_view; if (m_view) { - m_layout->removeWidget(m_view); + layout()->removeWidget(m_splitter); } m_view = 0; return oldView; @@ -255,35 +260,6 @@ QList SplitterOrView::gadgets() return g; } -void SplitterOrView::split(Qt::Orientation orientation) -{ - Q_ASSERT(m_view); - Q_ASSERT(!m_splitter); - m_splitter = new MiniSplitter(this); - m_splitter->setOrientation(orientation); - connect(m_splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(onSplitterMoved(int, int))); - m_layout->addWidget(m_splitter); - Core::IUAVGadget *ourGadget = m_view->gadget(); - - if (ourGadget) { - // Give our gadget to the new left or top SplitterOrView. - m_view->removeGadget(); - m_splitter->addWidget(new SplitterOrView(m_uavGadgetManager, ourGadget)); - m_splitter->addWidget(new SplitterOrView(m_uavGadgetManager)); - } else { - m_splitter->addWidget(new SplitterOrView(m_uavGadgetManager)); - m_splitter->addWidget(new SplitterOrView(m_uavGadgetManager)); - } - - m_layout->setCurrentWidget(m_splitter); - - if (m_view) { - m_uavGadgetManager->emptyView(m_view); - delete m_view; - m_view = 0; - } -} - void SplitterOrView::onSplitterMoved(int pos, int index) { Q_UNUSED(pos); @@ -292,66 +268,107 @@ void SplitterOrView::onSplitterMoved(int pos, int index) m_sizes = m_splitter->sizes(); } -void SplitterOrView::unsplitAll(IUAVGadget *currentGadget) +void SplitterOrView::split(Qt::Orientation orientation) { - Q_ASSERT(m_splitter); - Q_ASSERT(!m_view); - m_splitter->hide(); - m_layout->removeWidget(m_splitter); // workaround Qt bug - unsplitAll_helper(); - delete m_splitter; - m_splitter = 0; + Q_ASSERT(m_view); + Q_ASSERT(!m_splitter); - m_view = new UAVGadgetView(m_uavGadgetManager, currentGadget, this); - m_layout->addWidget(m_view); + MiniSplitter *splitter = new MiniSplitter(this); + splitter->setOrientation(orientation); + layout()->addWidget(splitter); + + // [OP-1586] make sure that the view never becomes parent less otherwise a rendering bug happens + // in osgearth QML views (not all kind of scenes are affected but those containing terrain are) + // Making the view parent less will destroy the OpenGL context used by the QQuickFramebufferObject used OSGViewport + // A new OpenGL context will be created but for some reason, osgearth does not switch to it gracefully. + // Enabling the stats overlay (by pressing the 's' key in the view) will restore proper rendering (?). + // Note : avoiding to make the view parent less is a workaround... the real cause of the rendering bug needs to be + // understood and fixed (the same workaround is also need in unsplit and unsplitAll) + // Important : the changes also apparently make splitting and un-splitting more reactive and less jumpy! + + // Give our view to the new left or top SplitterOrView. + splitter->addWidget(new SplitterOrView(*this, splitter)); + splitter->addWidget(new SplitterOrView(m_uavGadgetManager)); + + m_view = 0; + m_splitter = splitter; + + connect(m_splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(onSplitterMoved(int, int))); } -void SplitterOrView::unsplitAll_helper() -{ - if (m_view) { - m_uavGadgetManager->emptyView(m_view); - } - if (m_splitter) { - for (int i = 0; i < m_splitter->count(); ++i) { - if (SplitterOrView * splitterOrView = qobject_cast(m_splitter->widget(i))) { - splitterOrView->unsplitAll_helper(); - } - } - } -} - -void SplitterOrView::unsplit() +void SplitterOrView::unsplit(IUAVGadget *gadget) { if (!m_splitter) { return; } - Q_ASSERT(m_splitter->count() == 1); - SplitterOrView *childSplitterOrView = qobject_cast(m_splitter->widget(0)); - QSplitter *oldSplitter = m_splitter; - m_splitter = 0; - - if (childSplitterOrView->isSplitter()) { - Q_ASSERT(childSplitterOrView->view() == 0); - m_splitter = childSplitterOrView->takeSplitter(); - m_layout->addWidget(m_splitter); - m_layout->setCurrentWidget(m_splitter); - } else { - UAVGadgetView *childView = childSplitterOrView->view(); - Q_ASSERT(childView); - if (m_view) { - if (IUAVGadget * e = childView->gadget()) { - childView->removeGadget(); - m_view->setGadget(e); - } - m_uavGadgetManager->emptyView(childView); - } else { - m_view = childSplitterOrView->takeView(); - m_layout->addWidget(m_view); - } - m_layout->setCurrentWidget(m_view); + SplitterOrView *view = findView(gadget); + if (!view || view == this) { + return; + } + + // find the other gadgets + // TODO handle case where m_splitter->count() > 2 + SplitterOrView *splitterOrView = NULL; + for (int i = 0; i < m_splitter->count(); ++i) { + splitterOrView = qobject_cast(m_splitter->widget(i)); + if (splitterOrView && (splitterOrView != view)) { + break; + } + } + if (splitterOrView) { + if (splitterOrView->isView()) { + layout()->addWidget(splitterOrView->m_view); + } else { + layout()->addWidget(splitterOrView->m_splitter); + } + layout()->removeWidget(m_splitter); + + m_uavGadgetManager->emptyView(view->m_view); + delete view; + delete m_splitter; + + m_view = splitterOrView->m_view; + m_splitter = splitterOrView->m_splitter; + } +} + +void SplitterOrView::unsplitAll(Core::IUAVGadget *gadget) +{ + Q_ASSERT(m_splitter); + Q_ASSERT(!m_view); + + SplitterOrView *splitterOrView = findView(gadget); + if (!splitterOrView || splitterOrView == this) { + return; + } + + // first re-parent the gadget (see split for an explanation) + m_view = splitterOrView->m_view; + layout()->addWidget(m_view); + layout()->removeWidget(m_splitter); + // make sure the old m_view is not emptied... + splitterOrView->m_view = NULL; + + // cleanup + unsplitAll_helper(m_uavGadgetManager, m_splitter); + + delete m_splitter; + m_splitter = 0; +} + +void SplitterOrView::unsplitAll_helper(UAVGadgetManager *uavGadgetManager, QSplitter *splitter) +{ + for (int i = 0; i < splitter->count(); ++i) { + if (SplitterOrView * splitterOrView = qobject_cast(splitter->widget(i))) { + if (splitterOrView->m_view) { + uavGadgetManager->emptyView(splitterOrView->m_view); + } + if (splitterOrView->m_splitter) { + unsplitAll_helper(uavGadgetManager, splitterOrView->m_splitter); + } + delete splitterOrView; + } } - delete oldSplitter; - m_uavGadgetManager->setCurrentGadget(findFirstView()->gadget()); } void SplitterOrView::saveState(QSettings *qSettings) const diff --git a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.h b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.h index fd75779a2..6549c84fa 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.h +++ b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/splitterorview.h @@ -43,7 +43,11 @@ public: ~SplitterOrView(); void split(Qt::Orientation orientation); - void unsplit(); + + void unsplit(IUAVGadget *gadget); + + // un-split all and keep only the specified gadget + void unsplitAll(IUAVGadget *gadget); inline bool isView() const { @@ -95,10 +99,7 @@ public: } QSize minimumSizeHint() const; - void unsplitAll(IUAVGadget *currentGadget); - protected: -// void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *e); private slots: @@ -106,19 +107,19 @@ private slots: void onSplitterMoved(int pos, int index); private: - void unsplitAll_helper(); + // private "copy" constructor + SplitterOrView(SplitterOrView &splitterOrView, QWidget *parent); + + static void unsplitAll_helper(UAVGadgetManager *uavGadgetManager, QSplitter *splitter); SplitterOrView *findNextView_helper(SplitterOrView *view, bool *found); // The gadget manager that controls us. QPointer m_uavGadgetManager; - // Our layout, we use stacked so we can change stuff without visual artifacts (I think...) - QPointer m_layout; - // Our view, if we are a view (showing 1 gadget) and not a splitter. QPointer m_view; - // Out splitter, if we are a splitter. + // Our splitter, if we are a splitter. QPointer m_splitter; // The splitter sizes. We keep our own copy of these, since after loading they can't realiably be retrieved. diff --git a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/uavgadgetmanager.cpp b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/uavgadgetmanager.cpp index 9e569c49b..f2bcd5098 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/uavgadgetmanager.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/uavgadgetmanager/uavgadgetmanager.cpp @@ -108,7 +108,7 @@ UAVGadgetManager::UAVGadgetManager(ICore *core, QString name, QIcon icon, int pr this, SLOT(modeChanged(Core::IMode *))); // other setup - m_splitterOrView = new SplitterOrView(this, 0); + m_splitterOrView = new SplitterOrView(this); // SplitterOrView with 0 as gadget calls our setCurrentGadget, which relies on currentSplitterOrView(), // which needs our m_splitterorView to be set, which isn't set yet at that time. @@ -209,10 +209,10 @@ void UAVGadgetManager::emptyView(Core::Internal::UAVGadgetView *view) } IUAVGadget *uavGadget = view->gadget(); -// emit uavGadgetAboutToClose(uavGadget); + // emit uavGadgetAboutToClose(uavGadget); removeGadget(uavGadget); view->removeGadget(); -// emit uavGadgetsClosed(uavGadgets); + // emit uavGadgetsClosed(uavGadgets); } @@ -221,27 +221,22 @@ void UAVGadgetManager::closeView(Core::Internal::UAVGadgetView *view) if (!view) { return; } - SplitterOrView *splitterOrView = m_splitterOrView->findView(view); - Q_ASSERT(splitterOrView); - Q_ASSERT(splitterOrView->view() == view); - if (splitterOrView == m_splitterOrView) { - return; - } IUAVGadget *gadget = view->gadget(); - emptyView(view); + + // find SplitterOrView splitter that contains the view to delete + SplitterOrView *splitter = m_splitterOrView->findSplitter(gadget); + if (!splitter) { + return; + } + Q_ASSERT(splitter->isSplitter() == true); + + splitter->unsplit(gadget); + UAVGadgetInstanceManager *im = ICore::instance()->uavGadgetInstanceManager(); im->removeGadget(gadget); - SplitterOrView *splitter = m_splitterOrView->findSplitter(splitterOrView); - Q_ASSERT(splitterOrView->hasGadget() == false); - Q_ASSERT(splitter->isSplitter() == true); - splitterOrView->hide(); - delete splitterOrView; - - splitter->unsplit(); - - SplitterOrView *newCurrent = splitter->findFirstView(); + SplitterOrView *newCurrent = splitter->findFirstView(); Q_ASSERT(newCurrent); if (newCurrent) { setCurrentGadget(newCurrent->gadget()); @@ -254,8 +249,7 @@ void UAVGadgetManager::addGadgetToContext(IUAVGadget *gadget) return; } m_core->addContextObject(gadget); - -// emit uavGadgetOpened(uavGadget); + // emit uavGadgetOpened(uavGadget); } void UAVGadgetManager::removeGadget(IUAVGadget *gadget)