forked from qt-creator/qt-creator
Add a fancy double tab widget for the project mode.
This commit is contained in:
267
src/plugins/projectexplorer/doubletabwidget.cpp
Normal file
267
src/plugins/projectexplorer/doubletabwidget.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
#include "doubletabwidget.h"
|
||||
#include "ui_doubletabwidget.h"
|
||||
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QtCore/QRect>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QMouseEvent>
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
|
||||
static const int MIN_LEFT_MARGIN = 50;
|
||||
static const int MARGIN = 12;
|
||||
static const int OTHER_HEIGHT = 38;
|
||||
static const int SELECTION_IMAGE_WIDTH = 10;
|
||||
static const int SELECTION_IMAGE_HEIGHT = 20;
|
||||
|
||||
static void drawFirstLevelSeparator(QPainter *painter, QPoint top, QPoint bottom)
|
||||
{
|
||||
QLinearGradient grad(top, bottom);
|
||||
grad.setColorAt(0, QColor(255, 255, 255, 20));
|
||||
grad.setColorAt(0.4, QColor(255, 255, 255, 60));
|
||||
grad.setColorAt(0.7, QColor(255, 255, 255, 50));
|
||||
grad.setColorAt(1, QColor(255, 255, 255, 40));
|
||||
painter->setPen(QPen(grad, 0));
|
||||
painter->drawLine(top, bottom);
|
||||
grad.setColorAt(0, QColor(0, 0, 0, 30));
|
||||
grad.setColorAt(0.4, QColor(0, 0, 0, 70));
|
||||
grad.setColorAt(0.7, QColor(0, 0, 0, 70));
|
||||
grad.setColorAt(1, QColor(0, 0, 0, 40));
|
||||
painter->setPen(QPen(grad, 0));
|
||||
painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
|
||||
}
|
||||
|
||||
static void drawSecondLevelSeparator(QPainter *painter, QPoint top, QPoint bottom)
|
||||
{
|
||||
QLinearGradient grad(top, bottom);
|
||||
grad.setColorAt(0, QColor(255, 255, 255, 0));
|
||||
grad.setColorAt(0.4, QColor(255, 255, 255, 100));
|
||||
grad.setColorAt(0.7, QColor(255, 255, 255, 100));
|
||||
grad.setColorAt(1, QColor(255, 255, 255, 0));
|
||||
painter->setPen(QPen(grad, 0));
|
||||
painter->drawLine(top, bottom);
|
||||
grad.setColorAt(0, QColor(0, 0, 0, 0));
|
||||
grad.setColorAt(0.4, QColor(0, 0, 0, 100));
|
||||
grad.setColorAt(0.7, QColor(0, 0, 0, 100));
|
||||
grad.setColorAt(1, QColor(0, 0, 0, 0));
|
||||
painter->setPen(QPen(grad, 0));
|
||||
painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
|
||||
}
|
||||
|
||||
DoubleTabWidget::DoubleTabWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::DoubleTabWidget),
|
||||
m_currentIndex(-1)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
DoubleTabWidget::~DoubleTabWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DoubleTabWidget::setTitle(const QString &title)
|
||||
{
|
||||
m_title = title;
|
||||
update();
|
||||
}
|
||||
|
||||
QSize DoubleTabWidget::minimumSizeHint() const
|
||||
{
|
||||
return QSize(0, Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT + 1);
|
||||
}
|
||||
|
||||
void DoubleTabWidget::addTab(const QString &name, const QStringList &subTabs)
|
||||
{
|
||||
Tab tab;
|
||||
tab.name = name;
|
||||
tab.subTabs = subTabs;
|
||||
tab.currentSubTab = tab.subTabs.isEmpty() ? -1 : 0;
|
||||
m_tabs.append(tab);
|
||||
if (m_currentIndex == -1) {
|
||||
m_currentIndex = m_tabs.size()-1;
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->y() < Utils::StyleHelper::navigationWidgetHeight()) {
|
||||
int eventX = event->x();
|
||||
// clicked on the top level part of the bar
|
||||
QFontMetrics fm(font());
|
||||
int x = 2 * MARGIN + qMax(fm.width(m_title), MIN_LEFT_MARGIN);
|
||||
if (eventX <= x)
|
||||
return;
|
||||
int i;
|
||||
for (i = 0; i < m_tabs.size(); ++i) {
|
||||
int otherX = x + 2 * MARGIN + fm.width(m_tabs.at(i).name);
|
||||
if (eventX > x && eventX < otherX) {
|
||||
break;
|
||||
}
|
||||
x = otherX;
|
||||
}
|
||||
if (i < m_tabs.size()) {
|
||||
if (m_currentIndex != i) {
|
||||
m_currentIndex = i;
|
||||
update();
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
}
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
} else if (event->y() < Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT) {
|
||||
int diff = (OTHER_HEIGHT - SELECTION_IMAGE_HEIGHT) / 2;
|
||||
if (event->y() < Utils::StyleHelper::navigationWidgetHeight() + diff
|
||||
|| event->y() > Utils::StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT - diff)
|
||||
return;
|
||||
if (m_currentIndex == -1)
|
||||
return;
|
||||
Tab currentTab = m_tabs.at(m_currentIndex);
|
||||
QStringList subTabs = currentTab.subTabs;
|
||||
if (subTabs.isEmpty())
|
||||
return;
|
||||
int eventX = event->x();
|
||||
QFontMetrics fm(font());
|
||||
// clicked on the lower level part of the bar
|
||||
int x = MARGIN;
|
||||
int i;
|
||||
for (i = 0; i < subTabs.size(); ++i) {
|
||||
int otherX = x + 2 * SELECTION_IMAGE_WIDTH + fm.width(subTabs.at(i));
|
||||
if (eventX > x && eventX < otherX) {
|
||||
break;
|
||||
}
|
||||
x = otherX + 2 * MARGIN;
|
||||
}
|
||||
if (i < subTabs.size()) {
|
||||
if (m_tabs[m_currentIndex].currentSubTab != i) {
|
||||
m_tabs[m_currentIndex].currentSubTab = i;
|
||||
update();
|
||||
}
|
||||
event->accept();
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
QPainter painter(this);
|
||||
QRect r = rect();
|
||||
|
||||
// draw top level tab bar
|
||||
r.setHeight(Utils::StyleHelper::navigationWidgetHeight());
|
||||
|
||||
QPoint offset = window()->mapToGlobal(QPoint(0, 0)) - mapToGlobal(r.topLeft());
|
||||
QRect gradientSpan = QRect(offset, window()->size());
|
||||
Utils::StyleHelper::horizontalGradient(&painter, gradientSpan, r);
|
||||
|
||||
painter.setPen(Utils::StyleHelper::borderColor());
|
||||
|
||||
QColor lighter(255, 255, 255, 40);
|
||||
painter.drawLine(r.bottomLeft(), r.bottomRight());
|
||||
painter.setPen(lighter);
|
||||
painter.drawLine(r.topLeft(), r.topRight());
|
||||
|
||||
QFontMetrics fm(font());
|
||||
int baseline = (r.height() + fm.ascent()) / 2 - 1;
|
||||
|
||||
// top level title
|
||||
painter.setPen(Utils::StyleHelper::panelTextColor());
|
||||
painter.drawText(MARGIN, baseline, m_title);
|
||||
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(0, r.height() + OTHER_HEIGHT - 1));
|
||||
grad.setColorAt(0, QColor(247, 247, 247));
|
||||
grad.setColorAt(1, QColor(205, 205, 205));
|
||||
|
||||
// draw background of second bar
|
||||
painter.fillRect(QRect(0, r.height(), r.width(), OTHER_HEIGHT), grad);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawLine(0, r.height() + OTHER_HEIGHT,
|
||||
r.width(), r.height() + OTHER_HEIGHT);
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawLine(0, r.height(),
|
||||
r.width(), r.height());
|
||||
|
||||
// top level tabs
|
||||
int x = 2 * MARGIN + qMax(fm.width(m_title), MIN_LEFT_MARGIN);
|
||||
for (int i = 0; i < m_tabs.size(); ++i) {
|
||||
if (i == m_currentIndex) {
|
||||
painter.setPen(Utils::StyleHelper::borderColor());
|
||||
painter.drawLine(x - 1, 0, x - 1, r.height() - 1);
|
||||
painter.fillRect(QRect(x, 0,
|
||||
2 * MARGIN + fm.width(m_tabs.at(i).name),
|
||||
r.height() + 1),
|
||||
grad);
|
||||
x += MARGIN;
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(x, baseline, m_tabs.at(i).name);
|
||||
x += fm.width(m_tabs.at(i).name);
|
||||
x += MARGIN;
|
||||
painter.setPen(Utils::StyleHelper::borderColor());
|
||||
painter.drawLine(x, 0, x, r.height() - 1);
|
||||
} else {
|
||||
if (i == 0)
|
||||
drawFirstLevelSeparator(&painter, QPoint(x, 0), QPoint(x, r.height()-1));
|
||||
x += MARGIN;
|
||||
painter.setPen(Utils::StyleHelper::panelTextColor());
|
||||
painter.drawText(x + 1, baseline, m_tabs.at(i).name);
|
||||
x += fm.width(m_tabs.at(i).name);
|
||||
x += MARGIN;
|
||||
drawFirstLevelSeparator(&painter, QPoint(x, 0), QPoint(x, r.height()-1));
|
||||
}
|
||||
if (x >= r.width()) // TODO: do something useful...
|
||||
break;
|
||||
}
|
||||
|
||||
// second level tabs
|
||||
static QPixmap left(":/projectexplorer/leftselection.png");
|
||||
static QPixmap mid(":/projectexplorer/midselection.png");
|
||||
static QPixmap right(":/projectexplorer/rightselection.png");
|
||||
if (m_currentIndex != -1) {
|
||||
int y = r.height() + (OTHER_HEIGHT - left.height()) / 2.;
|
||||
int imageHeight = left.height();
|
||||
Tab currentTab = m_tabs.at(m_currentIndex);
|
||||
QStringList subTabs = currentTab.subTabs;
|
||||
x = 0;
|
||||
for (int i = 0; i < subTabs.size(); ++i) {
|
||||
x += MARGIN;
|
||||
int textWidth = fm.width(subTabs.at(i));
|
||||
if (currentTab.currentSubTab == i) {
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawPixmap(x, y, left);
|
||||
painter.drawPixmap(QRect(x + SELECTION_IMAGE_WIDTH, y,
|
||||
textWidth, imageHeight),
|
||||
mid, QRect(0, 0, mid.width(), mid.height()));
|
||||
painter.drawPixmap(x + SELECTION_IMAGE_WIDTH + textWidth, y, right);
|
||||
} else {
|
||||
painter.setPen(Qt::black);
|
||||
}
|
||||
x += SELECTION_IMAGE_WIDTH;
|
||||
painter.drawText(x, y + (imageHeight + fm.ascent()) / 2. - 1,
|
||||
subTabs.at(i));
|
||||
x += textWidth + SELECTION_IMAGE_WIDTH + MARGIN;
|
||||
drawSecondLevelSeparator(&painter, QPoint(x, y), QPoint(x, y + imageHeight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoubleTabWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
50
src/plugins/projectexplorer/doubletabwidget.h
Normal file
50
src/plugins/projectexplorer/doubletabwidget.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef DOUBLETABWIDGET_H
|
||||
#define DOUBLETABWIDGET_H
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class DoubleTabWidget;
|
||||
}
|
||||
|
||||
class DoubleTabWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DoubleTabWidget(QWidget *parent = 0);
|
||||
~DoubleTabWidget();
|
||||
|
||||
void setTitle(const QString &title);
|
||||
QString title() const { return m_title; }
|
||||
|
||||
void addTab(const QString &name, const QStringList &subTabs);
|
||||
|
||||
signals:
|
||||
void currentIndexChanged(int index, int subIndex);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void changeEvent(QEvent *e);
|
||||
QSize minimumSizeHint() const;
|
||||
|
||||
private:
|
||||
struct Tab {
|
||||
QString name;
|
||||
QStringList subTabs;
|
||||
int currentSubTab;
|
||||
};
|
||||
|
||||
Ui::DoubleTabWidget *ui;
|
||||
|
||||
QString m_title;
|
||||
QList<Tab> m_tabs;
|
||||
int m_currentIndex;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
#endif // DOUBLETABWIDGET_H
|
||||
26
src/plugins/projectexplorer/doubletabwidget.ui
Normal file
26
src/plugins/projectexplorer/doubletabwidget.ui
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProjectExplorer::Internal::DoubleTabWidget</class>
|
||||
<widget class="QWidget" name="ProjectExplorer::Internal::DoubleTabWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DoubleTabWidget</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
BIN
src/plugins/projectexplorer/images/leftselection.png
Normal file
BIN
src/plugins/projectexplorer/images/leftselection.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 489 B |
BIN
src/plugins/projectexplorer/images/midselection.png
Normal file
BIN
src/plugins/projectexplorer/images/midselection.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 B |
BIN
src/plugins/projectexplorer/images/rightselection.png
Normal file
BIN
src/plugins/projectexplorer/images/rightselection.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 441 B |
@@ -68,7 +68,8 @@ HEADERS += projectexplorer.h \
|
||||
projectwelcomepagewidget.h \
|
||||
baseprojectwizarddialog.h \
|
||||
targetselector.h \
|
||||
targetsettingswidget.h
|
||||
targetsettingswidget.h \
|
||||
doubletabwidget.h
|
||||
SOURCES += projectexplorer.cpp \
|
||||
projectwindow.cpp \
|
||||
buildmanager.cpp \
|
||||
@@ -124,7 +125,8 @@ SOURCES += projectexplorer.cpp \
|
||||
corelistenercheckingforrunningbuild.cpp \
|
||||
baseprojectwizarddialog.cpp \
|
||||
targetselector.cpp \
|
||||
targetsettingswidget.cpp
|
||||
targetsettingswidget.cpp \
|
||||
doubletabwidget.cpp
|
||||
FORMS += processstep.ui \
|
||||
editorsettingspropertiespage.ui \
|
||||
runsettingspropertiespage.ui \
|
||||
@@ -133,7 +135,8 @@ FORMS += processstep.ui \
|
||||
removefiledialog.ui \
|
||||
projectexplorersettingspage.ui \
|
||||
projectwelcomepagewidget.ui \
|
||||
targetsettingswidget.ui
|
||||
targetsettingswidget.ui \
|
||||
doubletabwidget.ui
|
||||
|
||||
win32 {
|
||||
SOURCES += applicationlauncher_win.cpp \
|
||||
|
||||
@@ -23,5 +23,8 @@
|
||||
<file>images/targetrunselected.png</file>
|
||||
<file>images/targetseparatorbackground.png</file>
|
||||
<file>images/targetunselected.png</file>
|
||||
<file>images/leftselection.png</file>
|
||||
<file>images/rightselection.png</file>
|
||||
<file>images/midselection.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Reference in New Issue
Block a user