Commit 5667fdc4 authored by Tim Jenssen's avatar Tim Jenssen Committed by Thomas Hartmann

QmlDesigner: introduce SwitchSplitTabWidget as center widget

Change-Id: I2ab91c3a6c68bb64c6875c37fa6fe2b4abc8b82d
Reviewed-by: Thomas Hartmann's avatarThomas Hartmann <thomas.hartmann@qt.io>
parent 7f597151
QWidget#backgroundWidget {
background-color: creatorTheme.QmlDesignerTabDark
QWidget#centralTabBar {
background-color: creatorTheme.QmlDesignerBackgroundColorDarkAlternate;
}
QTabWidget#centralTabWidget::pane {
border: 0px;
QWidget#tabBarBackground {
background-color: creatorTheme.QmlDesignerBackgroundColorDarkAlternate;
}
QTabWidget#centralTabWidget::tab-bar { alignment: right; }
QTabBar::tab:selected {
border: none;
background-color: creatorTheme.QmlDesignerTabLight;
color: creatorTheme.QmlDesignerTabDark;
QTabBar#centralTabBar::tab:first {
width: 0px;
height: 0px;
}
QTabBar#centralTabBar::tab {
width: 16px;
height: 80px;
border-image: none;
background-color: creatorTheme.QmlDesignerTabDark;
color: creatorTheme.QmlDesignerTabLight;
width: 11px;
height: 100px;
margin-top: 0x;
margin-bottom: 0px;
margin-left: 0px;
......@@ -35,3 +27,18 @@ QTabBar#centralTabBar::tab:selected {
background-color: creatorTheme.QmlDesignerTabLight;
color: creatorTheme.QmlDesignerTabDark;
}
QToolButton {
background-color: creatorTheme.QmlDesignerBackgroundColorDarkAlternate;
width: 08px;
height: 16px;
border: none;
}
QSplitter::handle:horizontal {
width: 0px;
}
QSplitter::handle:vertical {
height: 0px;
}
......@@ -79,10 +79,8 @@ ViewManager::ViewManager()
{
d->formEditorView.setGotoErrorCallback([this](int line, int column) {
d->textEditorView.gotoCursorPosition(line, column);
if (Internal::DesignModeWidget *designModeWidget = QmlDesignerPlugin::instance()->mainWidget()) {
if (QTabWidget *centralTabWidget = designModeWidget->centralTabWidget())
centralTabWidget->setCurrentIndex(1);
}
if (Internal::DesignModeWidget *designModeWidget = QmlDesignerPlugin::instance()->mainWidget())
designModeWidget->showInternalTextEditor();
});
}
......
......@@ -24,10 +24,10 @@
****************************************************************************/
#include "designmodewidget.h"
#include "switchsplittabwidget.h"
#include <designeractionmanager.h>
#include <coreplugin/outputpane.h>
#include "qmldesignerplugin.h"
#include "crumblebar.h"
#include "documentwarningwidget.h"
......@@ -37,6 +37,7 @@
#include <itemlibrarywidget.h>
#include <theming.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/designmode.h>
......@@ -229,7 +230,10 @@ void DesignModeWidget::disableWidgets()
void DesignModeWidget::switchTextOrForm()
{
m_centralTabWidget->setCurrentIndex(m_centralTabWidget->currentIndex() == 0 ? 1 : 0);
if (m_centralTabWidget->currentWidget() == viewManager().widget("TextEditor"))
m_centralTabWidget->switchTo(viewManager().widget("FormEditor"));
else
m_centralTabWidget->switchTo(viewManager().widget("TextEditor"));
}
void DesignModeWidget::showWarningMessageBox(const QList<DocumentMessage> &warnings)
......@@ -471,34 +475,24 @@ static QWidget *createbottomSideBarWidget(const QList<WidgetInfo> &widgetInfos)
static Core::MiniSplitter *createCentralSplitter(const QList<WidgetInfo> &widgetInfos)
{
QList<WidgetInfo> centralWidgetInfos;
foreach (const WidgetInfo &widgetInfo, widgetInfos) {
if (widgetInfo.placementHint == widgetInfo.CentralPane)
centralWidgetInfos.append(widgetInfo);
}
// editor and output panes
Core::MiniSplitter *outputPlaceholderSplitter = new Core::MiniSplitter;
outputPlaceholderSplitter->setStretchFactor(0, 10);
outputPlaceholderSplitter->setStretchFactor(1, 0);
outputPlaceholderSplitter->setOrientation(Qt::Vertical);
QTabWidget* tabWidget = createWidgetsInTabWidget(centralWidgetInfos);
tabWidget->setObjectName("centralTabWidget");
tabWidget->setTabPosition(QTabWidget::East);
tabWidget->tabBar()->setObjectName("centralTabBar");
tabWidget->setTabBarAutoHide(true);
SwitchSplitTabWidget *switchSplitTabWidget = new SwitchSplitTabWidget();
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/centerwidget.css"));
switchSplitTabWidget->setStyleSheet(Theming::replaceCssColors(sheet));
QWidget *backgroundWidget = new QWidget();
backgroundWidget->setObjectName("backgroundWidget");
backgroundWidget->setLayout(new QVBoxLayout());
backgroundWidget->layout()->setMargin(0);
backgroundWidget->layout()->addWidget(tabWidget);
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/centerwidget.css");
backgroundWidget->setStyleSheet(Theming::replaceCssColors(QString::fromUtf8(sheet)));
foreach (const WidgetInfo &widgetInfo, widgetInfos) {
if (widgetInfo.placementHint == widgetInfo.CentralPane)
switchSplitTabWidget->addTab(widgetInfo.widget, widgetInfo.tabName);
}
outputPlaceholderSplitter->addWidget(backgroundWidget);
outputPlaceholderSplitter->addWidget(switchSplitTabWidget);
QWidget *bottomSideBar = createbottomSideBarWidget(widgetInfos);
bottomSideBar->setObjectName("bottomSideBar");
......@@ -522,8 +516,10 @@ QWidget *DesignModeWidget::createCenterWidget()
horizontalLayout->addWidget(createCrumbleBarFrame());
Core::MiniSplitter *centralSplitter = createCentralSplitter(viewManager().widgetInfos());
m_centralTabWidget = centralSplitter->findChild<QTabWidget*>("centralTabWidget");
m_centralTabWidget = centralSplitter->findChild<SwitchSplitTabWidget*>();
Q_ASSERT(m_centralTabWidget);
m_centralTabWidget->switchTo(viewManager().widget("FormEditor"));
m_bottomSideBar = centralSplitter->findChild<QWidget*>("bottomSideBar");
Q_ASSERT(m_bottomSideBar);
horizontalLayout->addWidget(centralSplitter);
......@@ -574,9 +570,9 @@ CrumbleBar *DesignModeWidget::crumbleBar() const
return m_crumbleBar;
}
QTabWidget *DesignModeWidget::centralTabWidget() const
void DesignModeWidget::showInternalTextEditor()
{
return m_centralTabWidget;
m_centralTabWidget->switchTo(viewManager().widget("TextEditor"));
}
QString DesignModeWidget::contextHelpId() const
......
......@@ -34,10 +34,6 @@
#include <QWidget>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
class QTabWidget;
QT_END_NAMESPACE
namespace Core {
class SideBar;
class SideBarItem;
......@@ -50,6 +46,7 @@ namespace QmlDesigner {
class ItemLibraryWidget;
class CrumbleBar;
class DocumentWarningWidget;
class SwitchSplitTabWidget;
namespace Internal {
......@@ -85,7 +82,7 @@ public:
bool gotoCodeWasClicked();
CrumbleBar* crumbleBar() const;
QTabWidget* centralTabWidget() const;
void showInternalTextEditor();
public slots:
void restoreDefaultView();
......@@ -112,7 +109,7 @@ private: // functions
private: // variables
QSplitter *m_mainSplitter = nullptr;
QPointer<DocumentWarningWidget> m_warningWidget;
QTabWidget* m_centralTabWidget = nullptr;
SwitchSplitTabWidget* m_centralTabWidget = nullptr;
QScopedPointer<Core::SideBar> m_leftSideBar;
QScopedPointer<Core::SideBar> m_rightSideBar;
......
......@@ -2,6 +2,7 @@ HEADERS += $$PWD/qmldesignerconstants.h \
$$PWD/shortcutmanager.h \
$$PWD/qmldesignerplugin.h \
$$PWD/designmodewidget.h \
$$PWD/switchsplittabwidget.h \
$$PWD/designersettings.h \
$$PWD/settingspage.h \
$$PWD/designmodecontext.h \
......@@ -13,6 +14,7 @@ HEADERS += $$PWD/qmldesignerconstants.h \
SOURCES += $$PWD/qmldesignerplugin.cpp \
$$PWD/shortcutmanager.cpp \
$$PWD/designmodewidget.cpp \
$$PWD/switchsplittabwidget.cpp \
$$PWD/designersettings.cpp \
$$PWD/settingspage.cpp \
$$PWD/designmodecontext.cpp \
......
......@@ -641,6 +641,8 @@ Project {
"designmodecontext.h",
"designmodewidget.cpp",
"designmodewidget.h",
"switchsplittabwidget.cpp",
"switchsplittabwidget.h",
"documentmanager.cpp",
"documentmanager.h",
"documentwarningwidget.cpp",
......
/****************************************************************************
**
** 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 <utils/utilsicons.h>
#include <QVector>
#include <QBoxLayout>
#include <QTabWidget>
#include <QTabBar>
#include <QToolButton>
#include <QSplitter>
#include <QLayoutItem>
#include <QEvent>
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_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);
QToolButton *horizontalButton = new QToolButton;
horizontalButton->setIcon(Utils::Icons::SPLIT_HORIZONTAL.icon());
connect(horizontalButton, &QToolButton::clicked, [this] () {
m_splitter->setOrientation(Qt::Vertical);
updateSplitterSizes();
selectFakeTab();
});
QToolButton *verticalButton = new QToolButton;
verticalButton->setIcon(Utils::Icons::SPLIT_VERTICAL.icon());
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<int> 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)
{
if (isHidden()) {
// we can not get the sizes if the splitter is hidden
m_splittSizesAreDirty = true;
return;
}
QVector<int> splitterSizes = m_splitter->sizes().toVector();
int splitterFullSize = 0;
for (int size : splitterSizes)
splitterFullSize += size;
if (index > -1) {
// collapse all but not the one at index
splitterSizes.fill(0);
splitterSizes.replace(index, splitterFullSize);
} else {
// distribute full size
splitterSizes.fill(splitterFullSize / splitterSizes.count());
}
m_splitter->setSizes(splitterSizes.toList());
m_splittSizesAreDirty = false;
}
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();
}
bool SwitchSplitTabWidget::event(QEvent *event)
{
if (event->type() == QEvent::Show && m_splittSizesAreDirty) {
bool returnValue = QWidget::event(event);
updateSplitterSizes(m_tabBar->currentIndex() - fakeTab);
return returnValue;
}
return QWidget::event(event);
}
void SwitchSplitTabWidget::updateSplitButtons()
{
const bool isTabBarNecessary = count() > 1;
m_tabBarBackground->setVisible(isTabBarNecessary);
}
void SwitchSplitTabWidget::selectFakeTab()
{
m_tabBar->setCurrentIndex(0);
}
SwitchSplitTabWidget::Mode SwitchSplitTabWidget::mode()
{
const bool isTabBarNecessary = count() > 1;
const int fakeTabPosition = 0;
const int hasSelectedTab = m_tabBar->currentIndex() > fakeTabPosition;
if (isTabBarNecessary && !hasSelectedTab)
return SplitMode;
return TabMode;
}
} // namespace QmlDesigner
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <QWidget>
QT_BEGIN_NAMESPACE
class QTabBar;
class QSplitter;
class QPushButton;
QT_END_NAMESPACE
namespace QmlDesigner {
class SwitchSplitTabWidget : public QWidget
{
Q_OBJECT
enum Mode {
SplitMode,
TabMode
};
public:
explicit SwitchSplitTabWidget(QWidget *parent = 0);
int count() const;
QWidget *currentWidget() const;
int addTab(QWidget *widget, const QString &label);
QWidget *takeTabWidget(const int index);
void switchTo(QWidget *widget);
protected:
bool event(QEvent* event) override;
private:
void updateSplitterSizes(int index = -1);
void updateSplitButtons();
void selectFakeTab();
Mode mode();
QSplitter *m_splitter = nullptr;
QTabBar *m_tabBar = nullptr;
QWidget *m_tabBarBackground = nullptr;
const int fakeTab = 1;
bool m_splittSizesAreDirty = true;
};
} // namespace QmlDesigner
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment