forked from qt-creator/qt-creator
QmlDesigner: introduce SwitchSplitTabWidget as center widget
Change-Id: I2ab91c3a6c68bb64c6875c37fa6fe2b4abc8b82d Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
7f597151db
commit
5667fdc46a
@@ -1,28 +1,20 @@
|
||||
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();
|
||||
|
||||
QWidget *backgroundWidget = new QWidget();
|
||||
backgroundWidget->setObjectName("backgroundWidget");
|
||||
backgroundWidget->setLayout(new QVBoxLayout());
|
||||
backgroundWidget->layout()->setMargin(0);
|
||||
backgroundWidget->layout()->addWidget(tabWidget);
|
||||
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/centerwidget.css"));
|
||||
switchSplitTabWidget->setStyleSheet(Theming::replaceCssColors(sheet));
|
||||
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/centerwidget.css");
|
||||
backgroundWidget->setStyleSheet(Theming::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
|
||||
outputPlaceholderSplitter->addWidget(backgroundWidget);
|
||||
foreach (const WidgetInfo &widgetInfo, widgetInfos) {
|
||||
if (widgetInfo.placementHint == widgetInfo.CentralPane)
|
||||
switchSplitTabWidget->addTab(widgetInfo.widget, widgetInfo.tabName);
|
||||
}
|
||||
|
||||
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",
|
||||
|
||||
205
src/plugins/qmldesigner/switchsplittabwidget.cpp
Normal file
205
src/plugins/qmldesigner/switchsplittabwidget.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
68
src/plugins/qmldesigner/switchsplittabwidget.h
Normal file
68
src/plugins/qmldesigner/switchsplittabwidget.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
Reference in New Issue
Block a user