/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "switchsplittabwidget.h" #include #include #include #include #include #include #include #include #include #include namespace QmlDesigner { SwitchSplitTabWidget::SwitchSplitTabWidget(QWidget *parent) : QWidget(parent) , m_splitter(new QSplitter) , m_tabBar(new QTabBar) , m_tabBarBackground(new QWidget) { // setting object names for css setObjectName("backgroundWidget"); m_splitter->setObjectName("centralTabWidget"); m_splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_splitter->setHandleWidth(0); QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/centerwidget.css")); m_tabBarBackground->setStyleSheet(Theme::replaceCssColors(sheet)); m_tabBar->setObjectName("centralTabBar"); m_tabBar->setShape(QTabBar::RoundedEast); m_tabBar->setDocumentMode(false); // add a faketab to have the possibility to unselect all tabs m_tabBar->addTab(QString()); selectFakeTab(); m_tabBarBackground->setObjectName("tabBarBackground"); connect(m_tabBar, &QTabBar::tabBarClicked, [this] (int index) { if (index != -1) updateSplitterSizes(index - fakeTab); }); setLayout(new QHBoxLayout); layout()->setContentsMargins(0, 0, 0, 0); layout()->setSpacing(0); layout()->addWidget(m_splitter); m_tabBarBackground->setLayout(new QVBoxLayout); m_tabBarBackground->layout()->setContentsMargins(0, 0, 0, 0); m_tabBarBackground->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); m_tabBarBackground->layout()->addWidget(m_tabBar); auto horizontalButton = new QToolButton; horizontalButton->setObjectName("centralTabBar"); horizontalButton->setIcon(Utils::Icon({{QLatin1String(":/qmldesigner/images/spliteditorvertically.png"), Utils::Theme::IconsBaseColor}}).icon()); horizontalButton->setIconSize(QSize(8, 16)); connect(horizontalButton, &QToolButton::clicked, [this] () { m_splitter->setOrientation(Qt::Vertical); updateSplitterSizes(); selectFakeTab(); }); auto verticalButton = new QToolButton; verticalButton->setObjectName("centralTabBar"); verticalButton->setIcon(Utils::Icon({{QLatin1String(":/qmldesigner/images/spliteditorhorizontally.png"), Utils::Theme::IconsBaseColor}}).icon()); verticalButton->setIconSize(QSize(8, 16)); connect(verticalButton, &QToolButton::clicked, [this] () { m_splitter->setOrientation(Qt::Horizontal); updateSplitterSizes(); selectFakeTab(); }); m_tabBarBackground->layout()->addWidget(horizontalButton); m_tabBarBackground->layout()->addWidget(verticalButton); layout()->addWidget(m_tabBarBackground); updateSplitButtons(); } int SwitchSplitTabWidget::count() const { return m_splitter->count(); } QWidget *SwitchSplitTabWidget::currentWidget() const { QList sizes = m_splitter->sizes(); for (int i = 0; i < count(); ++i) { if (sizes.at(i) > 0 && m_splitter->widget(i)->hasFocus()) return m_splitter->widget(i); } return nullptr; } void SwitchSplitTabWidget::updateSplitterSizes(int index) { QVector splitterSizes(m_splitter->count()); int splitterFullSize = 0; bool isHorizontal = m_splitter->orientation() == Qt::Horizontal; for (int i = 0; i < m_splitter->count(); ++i) { auto widget = m_splitter->widget(i); splitterFullSize += isHorizontal ? widget->width() : widget->height(); } if (index > -1) { // collapse all but the one at index splitterSizes.fill(0); splitterSizes.replace(index, splitterFullSize); } else { // distribute full size among enabled tabs int divisor = splitterSizes.count(); for (int i = 0; i < m_splitter->count(); ++i) { if (!m_tabBar->isTabEnabled(i + fakeTab)) --divisor; } int splitSize = splitterFullSize / divisor; for (int i = 0; i < m_splitter->count(); ++i) splitterSizes.replace(i, m_tabBar->isTabEnabled(i + fakeTab) ? splitSize : 0); } m_splitter->setSizes(splitterSizes.toList()); } int SwitchSplitTabWidget::addTab(QWidget *w, const QString &label) { m_splitter->addWidget(w); const int newIndex = m_tabBar->addTab(label); if (mode() == TabMode) { m_tabBar->setCurrentIndex(newIndex); updateSplitterSizes(newIndex - fakeTab); } if (mode() == SplitMode) updateSplitterSizes(); updateSplitButtons(); return newIndex; } QWidget *SwitchSplitTabWidget::takeTabWidget(const int index) { if (index == -1 || index > count() - 1) return nullptr; QWidget *widget = m_splitter->widget(index); widget->setParent(nullptr); m_tabBar->removeTab(index + fakeTab); // TODO: set which mode and tab is the current one updateSplitButtons(); return widget; } void SwitchSplitTabWidget::switchTo(QWidget *widget) { if (widget == nullptr || currentWidget() == widget) return; const int widgetIndex = m_splitter->indexOf(widget); Q_ASSERT(widgetIndex != -1); if (mode() == TabMode) { updateSplitterSizes(widgetIndex); m_tabBar->setCurrentIndex(widgetIndex + fakeTab); } widget->setFocus(); } void SwitchSplitTabWidget::updateSplitButtons() { const bool isTabBarNecessary = count() > 1; m_tabBarBackground->setVisible(isTabBarNecessary); } void SwitchSplitTabWidget::selectFakeTab() { m_tabBar->setCurrentIndex(0); } SwitchSplitTabWidget::Mode SwitchSplitTabWidget::mode() const { const bool isTabBarNecessary = count() > 1; const int fakeTabPosition = 0; const int hasSelectedTab = m_tabBar->currentIndex() > fakeTabPosition; // Note: When splitting the view by dragging from the side of the view, SplitMode is not detected return (isTabBarNecessary && !hasSelectedTab) ? SplitMode : TabMode; } } // namespace QmlDesigner