/** ****************************************************************************** * * @file uavgadgetview.cpp * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. * @brief * @see The GNU Public License (GPL) Version 3 * @defgroup coreplugin * @{ * *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "uavgadgetview.h" #include "uavgadgetmanager.h" #include "uavgadgetinstancemanager.h" #include "iuavgadget.h" #include "coreimpl.h" #include "minisplitter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_WS_MAC #include #endif Q_DECLARE_METATYPE(Core::IUAVGadget *) using namespace Core; using namespace Core::Internal; // ================UAVGadgetView==================== UAVGadgetView::UAVGadgetView(Core::UAVGadgetManager *uavGadgetManager, IUAVGadget *uavGadget, QWidget *parent) : QWidget(parent), m_uavGadgetManager(uavGadgetManager), m_uavGadget(uavGadget), m_toolBar(new QWidget(this)), m_defaultToolBar(new QComboBox(this)), m_uavGadgetList(new QComboBox(this)), m_closeButton(new QToolButton(this)), m_defaultIndex(0), m_activeLabel(new QLabel) { tl = new QVBoxLayout(this); tl->setSpacing(0); tl->setMargin(0); { m_uavGadgetList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_uavGadgetList->setMinimumContentsLength(15); m_uavGadgetList->setMaxVisibleItems(40); m_uavGadgetList->setContextMenuPolicy(Qt::CustomContextMenu); UAVGadgetInstanceManager *im = ICore::instance()->uavGadgetInstanceManager(); QStringList sl = im->classIds(); int index = 0; foreach(QString classId, sl) { m_uavGadgetList->addItem(im->gadgetName(classId), classId); if (classId == QString("EmptyGadget")) m_defaultIndex = index; ++index; } m_defaultToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); m_activeToolBar = m_defaultToolBar; QHBoxLayout *toolBarLayout = new QHBoxLayout(m_toolBar); toolBarLayout->setMargin(0); toolBarLayout->setSpacing(0); toolBarLayout->addWidget(m_defaultToolBar); m_toolBar->setLayout(toolBarLayout); m_toolBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); QWidget *spacerWidget = new QWidget(this); spacerWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); m_activeLabel->setTextFormat(Qt::RichText); m_activeLabel->setText("" + tr("Active") + ""); m_closeButton->setAutoRaise(true); m_closeButton->setIcon(QIcon(":/core/images/closebutton.png")); m_top = new Utils::StyledBar(this); QHBoxLayout *toplayout = new QHBoxLayout(m_top); toplayout->setSpacing(0); toplayout->setMargin(0); toplayout->addWidget(m_uavGadgetList); toplayout->addWidget(m_toolBar); // Custom toolbar stretches toplayout->addWidget(spacerWidget); toplayout->addWidget(m_activeLabel); toplayout->addWidget(m_closeButton); m_top->setLayout(toplayout); tl->addWidget(m_top); connect(m_uavGadgetList, SIGNAL(activated(int)), this, SLOT(listSelectionActivated(int))); connect(m_closeButton, SIGNAL(clicked()), this, SLOT(closeView()), Qt::QueuedConnection); connect(m_uavGadgetManager, SIGNAL(currentGadgetChanged(IUAVGadget*)), this, SLOT(currentGadgetChanged(IUAVGadget*))); } if (m_uavGadget) { setGadget(m_uavGadget); } else { listSelectionActivated(m_defaultIndex); } } UAVGadgetView::~UAVGadgetView() { } bool UAVGadgetView::hasGadget(IUAVGadget *uavGadget) const { return (m_uavGadget == uavGadget); } void UAVGadgetView::showToolbar(bool show) { m_top->setHidden(!show); } void UAVGadgetView::closeView() { m_uavGadgetManager->closeView(this); } void UAVGadgetView::removeGadget() { if (!m_uavGadget) return; tl->removeWidget(m_uavGadget->widget()); m_uavGadget->setParent(0); m_uavGadget->widget()->setParent(0); QWidget *toolBar = m_uavGadget->toolBar(); if (toolBar != 0) { if (m_activeToolBar == toolBar) { m_activeToolBar = m_defaultToolBar; m_activeToolBar->setVisible(true); } m_toolBar->layout()->removeWidget(toolBar); toolBar->setParent(0); } m_uavGadget = 0; } IUAVGadget *UAVGadgetView::gadget() const { return m_uavGadget; } void UAVGadgetView::setGadget(IUAVGadget *uavGadget) { if (!uavGadget) { return; } removeGadget(); m_uavGadget = uavGadget; tl->addWidget(m_uavGadget->widget()); m_uavGadget->widget()->setParent(this); m_uavGadget->widget()->show(); int index = indexOfClassId(m_uavGadget->classId()); Q_ASSERT(index >= 0); m_uavGadgetList->setCurrentIndex(index); updateToolBar(); } void UAVGadgetView::updateToolBar() { if (!m_uavGadget) return; QComboBox *toolBar = m_uavGadget->toolBar(); if (!toolBar) toolBar = m_defaultToolBar; if (m_activeToolBar == toolBar) return; if (toolBar->count() == 0) toolBar->hide(); m_toolBar->layout()->addWidget(toolBar); m_activeToolBar->setVisible(false); m_activeToolBar = toolBar; } void UAVGadgetView::listSelectionActivated(int index) { if (index < 0) // this could happen when called from SplitterOrView::restoreState() index = m_defaultIndex; QString classId = m_uavGadgetList->itemData(index).toString(); if (m_uavGadget && (m_uavGadget->classId() == classId)) return; UAVGadgetInstanceManager *im = ICore::instance()->uavGadgetInstanceManager(); IUAVGadget *gadgetToRemove = m_uavGadget; IUAVGadget *gadget = im->createGadget(classId, this); setGadget(gadget); m_uavGadgetManager->setCurrentGadget(gadget); im->removeGadget(gadgetToRemove); } int UAVGadgetView::indexOfClassId(QString classId) { return m_uavGadgetList->findData(classId); } void UAVGadgetView::currentGadgetChanged(IUAVGadget *gadget) { m_activeLabel->setVisible(m_uavGadget == gadget); } SplitterOrView::SplitterOrView(Core::UAVGadgetManager *uavGadgetManager, Core::IUAVGadget *uavGadget, bool isRoot) : m_uavGadgetManager(uavGadgetManager), m_isRoot(isRoot) { m_view = new UAVGadgetView(m_uavGadgetManager, uavGadget, this); m_layout = new QStackedLayout(this); m_splitter = 0; m_layout->addWidget(m_view); } SplitterOrView::~SplitterOrView() { delete m_view; m_view = 0; delete m_splitter; m_splitter = 0; } void SplitterOrView::mousePressEvent(QMouseEvent *e) { if (e->button() != Qt::LeftButton) return; if (gadget()) { setFocus(Qt::MouseFocusReason); m_uavGadgetManager->setCurrentGadget(this->gadget()); } } //void SplitterOrView::paintEvent(QPaintEvent *event) //{ // if (m_uavGadgetManager->currentSplitterOrView() != this) // return; // // if (!m_view) // return; // // if (hasGadget()) // return; // // if (m_uavGadgetManager->toolbarsShown()) // return; // // // Discreet indication where an uavGadget would be if there is none // QPainter painter(this); // painter.setRenderHint(QPainter::Antialiasing, true); // painter.setPen(Qt::NoPen); // QColor shadeBrush(Qt::black); // shadeBrush.setAlpha(25); // painter.setBrush(shadeBrush); // const int r = 3; // painter.drawRoundedRect(rect().adjusted(r, r, -r, -r), r * 2, r * 2); // //#if 0 // if (hasFocus()) { //#ifdef Q_WS_MAC // // With QMacStyle, we have to draw our own focus rect, since I didn't find // // a way to draw the nice mac focus rect _inside_ this widget // if (qobject_cast(style())) { // painter.setPen(Qt::DotLine); // painter.setBrush(Qt::NoBrush); // painter.setOpacity(0.75); // painter.drawRect(rect()); // } else { //#endif // QStyleOptionFocusRect option; // option.initFrom(this); // option.backgroundColor = palette().color(QPalette::Background); // // // Some styles require a certain state flag in order to draw the focus rect // option.state |= QStyle::State_KeyboardFocusChange; // // style()->drawPrimitive(QStyle::PE_FrameFocusRect, &option, &painter); //#ifdef Q_WS_MAC // } //#endif // } //#endif //} /* Contract: return SplitterOrView that is not splitter, or 0 if not found. * Implications: must not return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findFirstView() { if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) if (SplitterOrView *result = splitterOrView->findFirstView()) return result; } return 0; } return this; } /* Contract: return SplitterOrView that has 'uavGadget', or 0 if not found. * Implications: must not return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findView(Core::IUAVGadget *uavGadget) { if (!uavGadget || hasGadget(uavGadget)) return this; if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) if (SplitterOrView *result = splitterOrView->findView(uavGadget)) return result; } } return 0; } /* Contract: return SplitterOrView that has 'view', or 0 if not found. * Implications: must not return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findView(UAVGadgetView *view) { if (view == m_view) return this; if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) if (SplitterOrView *result = splitterOrView->findView(view)) return result; } } return 0; } /* Contract: return SplitterOrView that is splitter that has as child SplitterOrView containing 'uavGadget', * or 0 if not found. * Implications: must return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findSplitter(Core::IUAVGadget *uavGadget) { if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) { if (splitterOrView->hasGadget(uavGadget)) return this; if (SplitterOrView *result = splitterOrView->findSplitter(uavGadget)) return result; } } } return 0; } /* Contract: return SplitterOrView that is splitter that has as child SplitterOrView 'child', * or 0 if not found. * Implications: must return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findSplitter(SplitterOrView *child) { if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) { if (splitterOrView == child) return this; if (SplitterOrView *result = splitterOrView->findSplitter(child)) return result; } } } return 0; } /* Contract: return SplitterOrView that follows SplitterOrView 'view' in tree structure, * or 0 if not found. * Implications: must not return SplitterOrView that is splitter. */ SplitterOrView *SplitterOrView::findNextView(SplitterOrView *view) { bool found = false; return findNextView_helper(view, &found); } SplitterOrView *SplitterOrView::findNextView_helper(SplitterOrView *view, bool *found) { if (*found && m_view) { return this; } if (this == view) { *found = true; return 0; } if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) { if (SplitterOrView *result = splitterOrView->findNextView_helper(view, found)) return result; } } } return 0; } QSize SplitterOrView::minimumSizeHint() const { if (m_splitter) return m_splitter->minimumSizeHint(); return QSize(64, 64); } QSplitter *SplitterOrView::takeSplitter() { QSplitter *oldSplitter = m_splitter; if (m_splitter) m_layout->removeWidget(m_splitter); m_splitter = 0; return oldSplitter; } UAVGadgetView *SplitterOrView::takeView() { UAVGadgetView *oldView = m_view; if (m_view) m_layout->removeWidget(m_view); m_view = 0; return oldView; } QList SplitterOrView::gadgets() { QList g; if (hasGadget()) g.append(gadget()); if (m_splitter) { for (int i = 0; i < m_splitter->count(); ++i) { if (SplitterOrView *splitterOrView = qobject_cast(m_splitter->widget(i))) { QList result = splitterOrView->gadgets(); g.append(result); } } } return g; } void SplitterOrView::split(Qt::Orientation orientation) { Q_ASSERT(m_view && (m_splitter == 0)); m_splitter = new MiniSplitter(this); m_splitter->setOrientation(orientation); m_layout->addWidget(m_splitter); Core::IUAVGadget *e = m_view->gadget(); SplitterOrView *view = 0; SplitterOrView *otherView = 0; if (e) { m_view->removeGadget(); m_splitter->addWidget((view = new SplitterOrView(m_uavGadgetManager, e))); m_splitter->addWidget((otherView = new SplitterOrView(m_uavGadgetManager))); } else { m_splitter->addWidget((otherView = new SplitterOrView(m_uavGadgetManager))); m_splitter->addWidget((view = new SplitterOrView(m_uavGadgetManager))); } m_layout->setCurrentWidget(m_splitter); if (m_view && !m_isRoot) { m_uavGadgetManager->emptyView(m_view); delete m_view; m_view = 0; } } void SplitterOrView::unsplitAll() { m_splitter->hide(); m_layout->removeWidget(m_splitter); // workaround Qt bug unsplitAll_helper(); delete m_splitter; m_splitter = 0; } void SplitterOrView::unsplitAll_helper() { if (!m_isRoot && 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() { 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); } delete oldSplitter; m_uavGadgetManager->setCurrentGadget(findFirstView()->gadget()); } QByteArray SplitterOrView::saveState() const { QByteArray bytes; QDataStream stream(&bytes, QIODevice::WriteOnly); if (m_splitter) { stream << QByteArray("splitter") << (qint32)m_splitter->orientation() << m_splitter->saveState() << static_cast(m_splitter->widget(0))->saveState() << static_cast(m_splitter->widget(1))->saveState(); } else { if (gadget()) stream << QByteArray("uavGadget") << gadget()->classId() << gadget()->saveState(); } return bytes; } void SplitterOrView::restoreState(const QByteArray &state) { QDataStream stream(state); QByteArray mode; stream >> mode; if (mode == "splitter") { qint32 orientation; QByteArray splitter, first, second; stream >> orientation >> splitter >> first >> second; split((Qt::Orientation)orientation); m_splitter->restoreState(splitter); static_cast(m_splitter->widget(0))->restoreState(first); static_cast(m_splitter->widget(1))->restoreState(second); } else if (mode == "uavGadget") { QString classId; QByteArray uavGadgetState; stream >> classId >> uavGadgetState; int index = m_view->indexOfClassId(classId); m_view->listSelectionActivated(index); gadget()->restoreState(uavGadgetState); } }