From 56d72a00bfc201c08cea6c8887dc15ffbae3ccfb Mon Sep 17 00:00:00 2001 From: David Sansome Date: Fri, 1 Oct 2010 19:27:01 +0000 Subject: [PATCH] Try the next UI experiment - wide buttons down the side like Qt Creator --- 3rdparty/fancytabwidget/CMakeLists.txt | 24 + 3rdparty/fancytabwidget/fancytabwidget.cpp | 519 ++++++++++++++++++ 3rdparty/fancytabwidget/fancytabwidget.h | 187 +++++++ 3rdparty/fancytabwidget/styledbar.cpp | 95 ++++ 3rdparty/fancytabwidget/styledbar.h | 63 +++ 3rdparty/fancytabwidget/stylehelper.cpp | 485 ++++++++++++++++ 3rdparty/fancytabwidget/stylehelper.h | 97 ++++ CMakeLists.txt | 2 + data/data.qrc | 1 - data/slimbuttonbox.css | 22 - src/CMakeLists.txt | 8 +- src/devices/deviceview.cpp | 5 + src/library/libraryview.cpp | 5 + src/library/libraryviewcontainer.cpp | 41 ++ .../libraryviewcontainer.h} | 40 +- src/library/libraryviewcontainer.ui | 47 ++ src/lyrics/songinfobuttonbox.cpp | 113 ---- src/lyrics/songinfobuttonbox.h | 62 --- src/playlist/playlistcontainer.cpp | 21 +- src/playlist/playlistcontainer.h | 3 - src/playlist/playlistcontainer.ui | 92 ++-- src/ui/mainwindow.cpp | 126 +++-- src/ui/mainwindow.h | 12 + src/ui/mainwindow.ui | 162 +----- src/widgets/slimbuttonbox.cpp | 111 ---- 25 files changed, 1716 insertions(+), 627 deletions(-) create mode 100644 3rdparty/fancytabwidget/CMakeLists.txt create mode 100644 3rdparty/fancytabwidget/fancytabwidget.cpp create mode 100644 3rdparty/fancytabwidget/fancytabwidget.h create mode 100644 3rdparty/fancytabwidget/styledbar.cpp create mode 100644 3rdparty/fancytabwidget/styledbar.h create mode 100644 3rdparty/fancytabwidget/stylehelper.cpp create mode 100644 3rdparty/fancytabwidget/stylehelper.h delete mode 100644 data/slimbuttonbox.css create mode 100644 src/library/libraryviewcontainer.cpp rename src/{widgets/slimbuttonbox.h => library/libraryviewcontainer.h} (53%) create mode 100644 src/library/libraryviewcontainer.ui delete mode 100644 src/lyrics/songinfobuttonbox.cpp delete mode 100644 src/lyrics/songinfobuttonbox.h delete mode 100644 src/widgets/slimbuttonbox.cpp diff --git a/3rdparty/fancytabwidget/CMakeLists.txt b/3rdparty/fancytabwidget/CMakeLists.txt new file mode 100644 index 000000000..085c4ef24 --- /dev/null +++ b/3rdparty/fancytabwidget/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.6) + +set(SOURCES + fancytabwidget.cpp + styledbar.cpp + stylehelper.cpp +) + +set(HEADERS + fancytabwidget.h + styledbar.h +) + +qt4_wrap_cpp(MOC ${HEADERS}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(fancytabwidget STATIC + ${SOURCES} + ${MOC} +) +target_link_libraries(fancytabwidget + ${QT_LIBRARIES} +) diff --git a/3rdparty/fancytabwidget/fancytabwidget.cpp b/3rdparty/fancytabwidget/fancytabwidget.cpp new file mode 100644 index 000000000..8ed95775e --- /dev/null +++ b/3rdparty/fancytabwidget/fancytabwidget.cpp @@ -0,0 +1,519 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "fancytabwidget.h" +#include "stylehelper.h" +#include "styledbar.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Core; +using namespace Internal; + +const int FancyTabBar::m_rounding = 22; +const int FancyTabBar::m_textPadding = 4; + +void FancyTab::fadeIn() +{ + animator.stop(); + animator.setDuration(80); + animator.setEndValue(40); + animator.start(); +} + +void FancyTab::fadeOut() +{ + animator.stop(); + animator.setDuration(160); + animator.setEndValue(0); + animator.start(); +} + +void FancyTab::setFader(float value) +{ + m_fader = value; + tabbar->update(); +} + +FancyTabBar::FancyTabBar(QWidget *parent) + : QWidget(parent) +{ + m_hoverIndex = -1; + m_currentIndex = -1; + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + setStyle(new QWindowsStyle); + setMinimumWidth(qMax(2 * m_rounding, 40)); + setAttribute(Qt::WA_Hover, true); + setFocusPolicy(Qt::NoFocus); + setMouseTracking(true); // Needed for hover events + m_triggerTimer.setSingleShot(true); + + // We use a zerotimer to keep the sidebar responsive + connect(&m_triggerTimer, SIGNAL(timeout()), this, SLOT(emitCurrentIndex())); +} + +FancyTabBar::~FancyTabBar() +{ + delete style(); +} + +QSize FancyTabBar::tabSizeHint(bool minimum) const +{ + QFont boldFont(font()); + boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); + boldFont.setBold(true); + QFontMetrics fm(boldFont); + int spacing = 8; + int width = 60 + spacing + 2; + int maxLabelwidth = 0; + for (int tab=0 ; tab maxLabelwidth) + maxLabelwidth = width; + } + int iconHeight = minimum ? 0 : 32; + return QSize(qMax(width, maxLabelwidth + 4), iconHeight + spacing + fm.height()); +} + +void FancyTabBar::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + QPainter p(this); + + for (int i = 0; i < count(); ++i) + if (i != currentIndex()) + paintTab(&p, i); + + // paint active tab last, since it overlaps the neighbors + if (currentIndex() != -1) + paintTab(&p, currentIndex()); +} + +// Handle hover events for mouse fade ins +void FancyTabBar::mouseMoveEvent(QMouseEvent *e) +{ + int newHover = -1; + for (int i = 0; i < count(); ++i) { + QRect area = tabRect(i); + if (area.contains(e->pos())) { + newHover = i; + break; + } + } + if (newHover == m_hoverIndex) + return; + + if (validIndex(m_hoverIndex)) + m_tabs[m_hoverIndex]->fadeOut(); + + m_hoverIndex = newHover; + + if (validIndex(m_hoverIndex)) { + m_tabs[m_hoverIndex]->fadeIn(); + m_hoverRect = tabRect(m_hoverIndex); + } +} + +bool FancyTabBar::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + if (validIndex(m_hoverIndex)) { + QString tt = tabToolTip(m_hoverIndex); + if (!tt.isEmpty()) { + QToolTip::showText(static_cast(event)->globalPos(), tt, this); + return true; + } + } + } + return QWidget::event(event); +} + +// Resets hover animation on mouse enter +void FancyTabBar::enterEvent(QEvent *e) +{ + Q_UNUSED(e) + m_hoverRect = QRect(); + m_hoverIndex = -1; +} + +// Resets hover animation on mouse enter +void FancyTabBar::leaveEvent(QEvent *e) +{ + Q_UNUSED(e) + m_hoverIndex = -1; + m_hoverRect = QRect(); + for (int i = 0 ; i < m_tabs.count() ; ++i) { + m_tabs[i]->fadeOut(); + } +} + +QSize FancyTabBar::sizeHint() const +{ + QSize sh = tabSizeHint(); + return QSize(sh.width(), sh.height() * m_tabs.count()); +} + +QSize FancyTabBar::minimumSizeHint() const +{ + QSize sh = tabSizeHint(true); + return QSize(sh.width(), sh.height() * m_tabs.count()); +} + +QRect FancyTabBar::tabRect(int index) const +{ + QSize sh = tabSizeHint(); + + if (sh.height() * m_tabs.count() > height()) + sh.setHeight(height() / m_tabs.count()); + + return QRect(0, index * sh.height(), sh.width(), sh.height()); + +} + +// This keeps the sidebar responsive since +// we get a repaint before loading the +// mode itself +void FancyTabBar::emitCurrentIndex() +{ + emit currentChanged(m_currentIndex); +} + +void FancyTabBar::mousePressEvent(QMouseEvent *e) +{ + e->accept(); + for (int index = 0; index < m_tabs.count(); ++index) { + if (tabRect(index).contains(e->pos())) { + + if (isTabEnabled(index)) { + m_currentIndex = index; + update(); + m_triggerTimer.start(0); + } + break; + } + } +} + +void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const +{ + if (!validIndex(tabIndex)) { + qWarning("invalid index"); + return; + } + painter->save(); + + QRect rect = tabRect(tabIndex); + bool selected = (tabIndex == m_currentIndex); + bool enabled = isTabEnabled(tabIndex); + + if (selected) { + //background + painter->save(); + QLinearGradient grad(rect.topLeft(), rect.topRight()); + grad.setColorAt(0, QColor(255, 255, 255, 140)); + grad.setColorAt(1, QColor(255, 255, 255, 210)); + painter->fillRect(rect.adjusted(0, 0, 0, -1), grad); + painter->restore(); + + //shadows + painter->setPen(QColor(0, 0, 0, 110)); + painter->drawLine(rect.topLeft() + QPoint(1,-1), rect.topRight() - QPoint(0,1)); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + painter->setPen(QColor(0, 0, 0, 40)); + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + + //highlights + painter->setPen(QColor(255, 255, 255, 50)); + painter->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0,2)); + painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0,1)); + painter->setPen(QColor(255, 255, 255, 40)); + painter->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight()); + painter->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1)); + painter->drawLine(rect.bottomLeft() + QPoint(0,-1), rect.bottomRight()-QPoint(0,1)); + } + + QString tabText(this->tabText(tabIndex)); + QRect tabTextRect(tabRect(tabIndex)); + QRect tabIconRect(tabTextRect); + tabTextRect.translate(0, -2); + QFont boldFont(painter->font()); + boldFont.setPointSizeF(Utils::StyleHelper::sidebarFontSize()); + boldFont.setBold(true); + painter->setFont(boldFont); + painter->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110)); + int textFlags = Qt::AlignCenter | Qt::AlignBottom | Qt::TextWordWrap; + if (enabled) { + painter->drawText(tabTextRect, textFlags, tabText); + painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor()); + } else { + painter->setPen(selected ? Utils::StyleHelper::panelTextColor() : QColor(255, 255, 255, 120)); + } +#ifndef Q_WS_MAC + if (!selected && enabled) { + painter->save(); + int fader = int(m_tabs[tabIndex]->fader()); + QLinearGradient grad(rect.topLeft(), rect.topRight()); + grad.setColorAt(0, Qt::transparent); + grad.setColorAt(0.5, QColor(255, 255, 255, fader)); + grad.setColorAt(1, Qt::transparent); + painter->fillRect(rect, grad); + painter->setPen(QPen(grad, 1.0)); + painter->drawLine(rect.topLeft(), rect.topRight()); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + painter->restore(); + } +#endif + + if (!enabled) + painter->setOpacity(0.7); + + int textHeight = painter->fontMetrics().boundingRect(QRect(0, 0, width(), height()), Qt::TextWordWrap, tabText).height(); + tabIconRect.adjust(0, 4, 0, -textHeight); + Utils::StyleHelper::drawIconWithShadow(tabIcon(tabIndex), tabIconRect, painter, enabled ? QIcon::Normal : QIcon::Disabled); + + painter->translate(0, -1); + painter->drawText(tabTextRect, textFlags, tabText); + painter->restore(); +} + +void FancyTabBar::setCurrentIndex(int index) { + if (isTabEnabled(index)) { + m_currentIndex = index; + update(); + emit currentChanged(m_currentIndex); + } +} + +void FancyTabBar::setTabEnabled(int index, bool enable) +{ + Q_ASSERT(index < m_tabs.size()); + Q_ASSERT(index >= 0); + + if (index < m_tabs.size() && index >= 0) { + m_tabs[index]->enabled = enable; + update(tabRect(index)); + } +} + +bool FancyTabBar::isTabEnabled(int index) const +{ + Q_ASSERT(index < m_tabs.size()); + Q_ASSERT(index >= 0); + + if (index < m_tabs.size() && index >= 0) + return m_tabs[index]->enabled; + + return false; +} + + +////// +// FancyColorButton +////// + +class FancyColorButton : public QWidget +{ +public: + FancyColorButton(QWidget *parent) + : m_parent(parent) + { + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + } + + void mousePressEvent(QMouseEvent *ev) + { + if (ev->modifiers() & Qt::ShiftModifier) + Utils::StyleHelper::setBaseColor(QColorDialog::getColor(Utils::StyleHelper::requestedBaseColor(), m_parent)); + } +private: + QWidget *m_parent; +}; + +////// +// FancyTabWidget +////// + +FancyTabWidget::FancyTabWidget(QWidget *parent) + : QWidget(parent) +{ + m_tabBar = new FancyTabBar(this); + + m_selectionWidget = new QWidget(this); + QVBoxLayout *selectionLayout = new QVBoxLayout; + selectionLayout->setSpacing(0); + selectionLayout->setMargin(0); + + Utils::StyledBar *bar = new Utils::StyledBar; + QHBoxLayout *layout = new QHBoxLayout(bar); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(new FancyColorButton(this)); + selectionLayout->addWidget(bar); + + selectionLayout->addWidget(m_tabBar, 1); + m_selectionWidget->setLayout(selectionLayout); + m_selectionWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + + m_cornerWidgetContainer = new QWidget(this); + m_cornerWidgetContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + m_cornerWidgetContainer->setAutoFillBackground(false); + + QVBoxLayout *cornerWidgetLayout = new QVBoxLayout; + cornerWidgetLayout->setSpacing(0); + cornerWidgetLayout->setMargin(0); + cornerWidgetLayout->addStretch(); + m_cornerWidgetContainer->setLayout(cornerWidgetLayout); + + selectionLayout->addWidget(m_cornerWidgetContainer, 0); + + m_modesStack = new QStackedLayout; + m_statusBar = new QStatusBar; + m_statusBar->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + + QVBoxLayout *vlayout = new QVBoxLayout; + vlayout->setMargin(0); + vlayout->setSpacing(0); + vlayout->addLayout(m_modesStack); + vlayout->addWidget(m_statusBar); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->setMargin(0); + mainLayout->setSpacing(1); + mainLayout->addWidget(m_selectionWidget); + mainLayout->addLayout(vlayout); + setLayout(mainLayout); + + connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(showWidget(int))); +} + +void FancyTabWidget::insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label) +{ + m_modesStack->insertWidget(index, tab); + m_tabBar->insertTab(index, icon, label); +} + +void FancyTabWidget::removeTab(int index) +{ + m_modesStack->removeWidget(m_modesStack->widget(index)); + m_tabBar->removeTab(index); +} + +void FancyTabWidget::setBackgroundBrush(const QBrush &brush) +{ + QPalette pal = m_tabBar->palette(); + pal.setBrush(QPalette::Mid, brush); + m_tabBar->setPalette(pal); + pal = m_cornerWidgetContainer->palette(); + pal.setBrush(QPalette::Mid, brush); + m_cornerWidgetContainer->setPalette(pal); +} + +void FancyTabWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + QPainter painter(this); + + QRect rect = m_selectionWidget->rect().adjusted(0, 0, 1, 0); + rect = style()->visualRect(layoutDirection(), geometry(), rect); + Utils::StyleHelper::verticalGradient(&painter, rect, rect); + painter.setPen(Utils::StyleHelper::borderColor()); + painter.drawLine(rect.topRight(), rect.bottomRight()); + + QColor light = Utils::StyleHelper::sidebarHighlight(); + painter.setPen(light); + painter.drawLine(rect.bottomLeft(), rect.bottomRight()); +} + +void FancyTabWidget::insertCornerWidget(int pos, QWidget *widget) +{ + QVBoxLayout *layout = static_cast(m_cornerWidgetContainer->layout()); + layout->insertWidget(pos, widget); +} + +int FancyTabWidget::cornerWidgetCount() const +{ + return m_cornerWidgetContainer->layout()->count(); +} + +void FancyTabWidget::addCornerWidget(QWidget *widget) +{ + m_cornerWidgetContainer->layout()->addWidget(widget); +} + +int FancyTabWidget::currentIndex() const +{ + return m_tabBar->currentIndex(); +} + +QStatusBar *FancyTabWidget::statusBar() const +{ + return m_statusBar; +} + +void FancyTabWidget::setCurrentIndex(int index) +{ + if (m_tabBar->isTabEnabled(index)) + m_tabBar->setCurrentIndex(index); +} + +void FancyTabWidget::showWidget(int index) +{ + emit currentAboutToShow(index); + m_modesStack->setCurrentIndex(index); + emit currentChanged(index); +} + +void FancyTabWidget::setTabToolTip(int index, const QString &toolTip) +{ + m_tabBar->setTabToolTip(index, toolTip); +} + +void FancyTabWidget::setTabEnabled(int index, bool enable) +{ + m_tabBar->setTabEnabled(index, enable); +} + +bool FancyTabWidget::isTabEnabled(int index) const +{ + return m_tabBar->isTabEnabled(index); +} diff --git a/3rdparty/fancytabwidget/fancytabwidget.h b/3rdparty/fancytabwidget/fancytabwidget.h new file mode 100644 index 000000000..42a8b91ec --- /dev/null +++ b/3rdparty/fancytabwidget/fancytabwidget.h @@ -0,0 +1,187 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef FANCYTABWIDGET_H +#define FANCYTABWIDGET_H + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE +class QPainter; +class QStackedLayout; +class QStatusBar; +QT_END_NAMESPACE + +namespace Core { +namespace Internal { + +class FancyTab : public QObject{ + Q_OBJECT + + Q_PROPERTY(float fader READ fader WRITE setFader) +public: + FancyTab(QWidget *tabbar) : enabled(false), tabbar(tabbar), m_fader(0) { + animator.setPropertyName("fader"); + animator.setTargetObject(this); + } + float fader() { return m_fader; } + void setFader(float value); + + void fadeIn(); + void fadeOut(); + + QIcon icon; + QString text; + QString toolTip; + bool enabled; + +private: + QPropertyAnimation animator; + QWidget *tabbar; + float m_fader; +}; + +class FancyTabBar : public QWidget +{ + Q_OBJECT + +public: + FancyTabBar(QWidget *parent = 0); + ~FancyTabBar(); + + bool event(QEvent *event); + + void paintEvent(QPaintEvent *event); + void paintTab(QPainter *painter, int tabIndex) const; + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void enterEvent(QEvent *); + void leaveEvent(QEvent *); + bool validIndex(int index) const { return index >= 0 && index < m_tabs.count(); } + + QSize sizeHint() const; + QSize minimumSizeHint() const; + + void setTabEnabled(int index, bool enable); + bool isTabEnabled(int index) const; + + void insertTab(int index, const QIcon &icon, const QString &label) { + FancyTab *tab = new FancyTab(this); + tab->icon = icon; + tab->text = label; + m_tabs.insert(index, tab); + } + void setEnabled(int index, bool enabled); + void removeTab(int index) { + FancyTab *tab = m_tabs.takeAt(index); + delete tab; + } + void setCurrentIndex(int index); + int currentIndex() const { return m_currentIndex; } + + void setTabToolTip(int index, QString toolTip) { m_tabs[index]->toolTip = toolTip; } + QString tabToolTip(int index) const { return m_tabs.at(index)->toolTip; } + + QIcon tabIcon(int index) const {return m_tabs.at(index)->icon; } + QString tabText(int index) const { return m_tabs.at(index)->text; } + int count() const {return m_tabs.count(); } + QRect tabRect(int index) const; + +signals: + void currentChanged(int); + +public slots: + void emitCurrentIndex(); + +private: + static const int m_rounding; + static const int m_textPadding; + QRect m_hoverRect; + int m_hoverIndex; + int m_currentIndex; + QList m_tabs; + QTimer m_triggerTimer; + QSize tabSizeHint(bool minimum = false) const; + +}; + +class FancyTabWidget : public QWidget +{ + Q_OBJECT + +public: + FancyTabWidget(QWidget *parent = 0); + + void insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label); + void removeTab(int index); + void setBackgroundBrush(const QBrush &brush); + void addCornerWidget(QWidget *widget); + void insertCornerWidget(int pos, QWidget *widget); + int cornerWidgetCount() const; + void setTabToolTip(int index, const QString &toolTip); + int count() const { return m_tabBar->count(); } + + void paintEvent(QPaintEvent *event); + + int currentIndex() const; + QStatusBar *statusBar() const; + + void setTabEnabled(int index, bool enable); + bool isTabEnabled(int index) const; + +signals: + void currentAboutToShow(int index); + void currentChanged(int index); + +public slots: + void setCurrentIndex(int index); + +private slots: + void showWidget(int index); + +private: + FancyTabBar *m_tabBar; + QWidget *m_cornerWidgetContainer; + QStackedLayout *m_modesStack; + QWidget *m_selectionWidget; + QStatusBar *m_statusBar; +}; + +} // namespace Internal +} // namespace Core + +using Core::Internal::FancyTab; +using Core::Internal::FancyTabBar; +using Core::Internal::FancyTabWidget; + +#endif // FANCYTABWIDGET_H diff --git a/3rdparty/fancytabwidget/styledbar.cpp b/3rdparty/fancytabwidget/styledbar.cpp new file mode 100644 index 000000000..288db2cb1 --- /dev/null +++ b/3rdparty/fancytabwidget/styledbar.cpp @@ -0,0 +1,95 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "styledbar.h" + +#include "stylehelper.h" + +#include +#include +#include +#include +#include + +using namespace Utils; + +StyledBar::StyledBar(QWidget *parent) + : QWidget(parent) +{ + setProperty("panelwidget", true); + setProperty("panelwidget_singlerow", true); + setProperty("lightColored", false); +} + +void StyledBar::setSingleRow(bool singleRow) +{ + setProperty("panelwidget_singlerow", singleRow); +} + +bool StyledBar::isSingleRow() const +{ + return property("panelwidget_singlerow").toBool(); +} + +void StyledBar::setLightColored(bool lightColored) +{ + setProperty("lightColored", lightColored); +} + +bool StyledBar::isLightColored() const +{ + return property("lightColored").toBool(); +} + +void StyledBar::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + QPainter painter(this); + QStyleOption option; + option.rect = rect(); + option.state = QStyle::State_Horizontal; + style()->drawControl(QStyle::CE_ToolBar, &option, &painter, this); +} + +StyledSeparator::StyledSeparator(QWidget *parent) + : QWidget(parent) +{ + setFixedWidth(10); +} + +void StyledSeparator::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + QPainter painter(this); + QStyleOption option; + option.rect = rect(); + option.state = QStyle::State_Horizontal; + option.palette = palette(); + style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &option, &painter, this); +} diff --git a/3rdparty/fancytabwidget/styledbar.h b/3rdparty/fancytabwidget/styledbar.h new file mode 100644 index 000000000..38f6a302a --- /dev/null +++ b/3rdparty/fancytabwidget/styledbar.h @@ -0,0 +1,63 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef STYLEDBAR_H +#define STYLEDBAR_H + +#include + +namespace Utils { + +class StyledBar : public QWidget +{ + Q_OBJECT +public: + StyledBar(QWidget *parent = 0); + void setSingleRow(bool singleRow); + bool isSingleRow() const; + + void setLightColored(bool lightColored); + bool isLightColored() const; + +protected: + void paintEvent(QPaintEvent *event); +}; + +class StyledSeparator : public QWidget +{ + Q_OBJECT +public: + StyledSeparator(QWidget *parent = 0); +protected: + void paintEvent(QPaintEvent *event); +}; + +} // Utils + +#endif // STYLEDBAR_H diff --git a/3rdparty/fancytabwidget/stylehelper.cpp b/3rdparty/fancytabwidget/stylehelper.cpp new file mode 100644 index 000000000..d6a5d5464 --- /dev/null +++ b/3rdparty/fancytabwidget/stylehelper.cpp @@ -0,0 +1,485 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "stylehelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +// Clamps float color values within (0, 255) +static int clamp(float x) +{ + const int val = x > 255 ? 255 : static_cast(x); + return val < 0 ? 0 : val; +} + +// Clamps float color values within (0, 255) +/* +static int range(float x, int min, int max) +{ + int val = x > max ? max : x; + return val < min ? min : val; +} +*/ + +namespace Utils { + +QColor StyleHelper::mergedColors(const QColor &colorA, const QColor &colorB, int factor) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +qreal StyleHelper::sidebarFontSize() +{ +#if defined(Q_WS_MAC) + return 10; +#else + return 7.5; +#endif +} + +QPalette StyleHelper::sidebarFontPalette(const QPalette &original) +{ + QPalette palette = original; + palette.setColor(QPalette::Active, QPalette::Text, panelTextColor()); + palette.setColor(QPalette::Active, QPalette::WindowText, panelTextColor()); + palette.setColor(QPalette::Inactive, QPalette::Text, panelTextColor().darker()); + palette.setColor(QPalette::Inactive, QPalette::WindowText, panelTextColor().darker()); + return palette; +} + +QColor StyleHelper::panelTextColor(bool lightColored) +{ + //qApp->palette().highlightedText().color(); + if (!lightColored) + return Qt::white; + else + return Qt::black; +} + +// Invalid by default, setBaseColor needs to be called at least once +QColor StyleHelper::m_baseColor; +QColor StyleHelper::m_requestedBaseColor; + +QColor StyleHelper::baseColor(bool lightColored) +{ + if (!lightColored) + return m_baseColor; + else + return m_baseColor.lighter(230); +} + +QColor StyleHelper::highlightColor(bool lightColored) +{ + QColor result = baseColor(lightColored); + if (!lightColored) + result.setHsv(result.hue(), + clamp(result.saturation()), + clamp(result.value() * 1.16)); + else + result.setHsv(result.hue(), + clamp(result.saturation()), + clamp(result.value() * 1.06)); + return result; +} + +QColor StyleHelper::shadowColor(bool lightColored) +{ + QColor result = baseColor(lightColored); + result.setHsv(result.hue(), + clamp(result.saturation() * 1.1), + clamp(result.value() * 0.70)); + return result; +} + +QColor StyleHelper::borderColor(bool lightColored) +{ + QColor result = baseColor(lightColored); + result.setHsv(result.hue(), + result.saturation(), + result.value() / 2); + return result; +} + +// We try to ensure that the actual color used are within +// reasonalbe bounds while generating the actual baseColor +// from the users request. +void StyleHelper::setBaseColor(const QColor &newcolor) +{ + m_requestedBaseColor = newcolor; + + QColor color; + color.setHsv(newcolor.hue(), + newcolor.saturation() * 0.7, + 64 + newcolor.value() / 3); + + if (color.isValid() && color != m_baseColor) { + m_baseColor = color; + foreach (QWidget *w, QApplication::topLevelWidgets()) + w->update(); + } +} + +static void verticalGradientHelper(QPainter *p, const QRect &spanRect, const QRect &rect, bool lightColored) +{ + QColor highlight = StyleHelper::highlightColor(lightColored); + QColor shadow = StyleHelper::shadowColor(lightColored); + QLinearGradient grad(spanRect.topRight(), spanRect.topLeft()); + grad.setColorAt(0, highlight.lighter(117)); + grad.setColorAt(1, shadow.darker(109)); + p->fillRect(rect, grad); + + QColor light(255, 255, 255, 80); + p->setPen(light); + p->drawLine(rect.topRight() - QPoint(1, 0), rect.bottomRight() - QPoint(1, 0)); + QColor dark(0, 0, 0, 90); + p->setPen(dark); + p->drawLine(rect.topLeft(), rect.bottomLeft()); +} + +void StyleHelper::verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored) +{ + if (StyleHelper::usePixmapCache()) { + QString key; + QColor keyColor = baseColor(lightColored); + key.sprintf("mh_vertical %d %d %d %d %d", + spanRect.width(), spanRect.height(), clipRect.width(), + clipRect.height(), keyColor.rgb());; + + QPixmap pixmap; + if (!QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(clipRect.size()); + QPainter p(&pixmap); + QRect rect(0, 0, clipRect.width(), clipRect.height()); + verticalGradientHelper(&p, spanRect, rect, lightColored); + p.end(); + QPixmapCache::insert(key, pixmap); + } + + painter->drawPixmap(clipRect.topLeft(), pixmap); + } else { + verticalGradientHelper(painter, spanRect, clipRect, lightColored); + } +} + +static void horizontalGradientHelper(QPainter *p, const QRect &spanRect, const +QRect &rect, bool lightColored) +{ + if (lightColored) { + QLinearGradient shadowGradient(rect.topLeft(), rect.bottomLeft()); + shadowGradient.setColorAt(0, 0xf0f0f0); + shadowGradient.setColorAt(1, 0xcfcfcf); + p->fillRect(rect, shadowGradient); + return; + } + + QColor base = StyleHelper::baseColor(lightColored); + QColor highlight = StyleHelper::highlightColor(lightColored); + QColor shadow = StyleHelper::shadowColor(lightColored); + QLinearGradient grad(rect.topLeft(), rect.bottomLeft()); + grad.setColorAt(0, highlight.lighter(120)); + if (rect.height() == StyleHelper::navigationWidgetHeight()) { + grad.setColorAt(0.4, highlight); + grad.setColorAt(0.401, base); + } + grad.setColorAt(1, shadow); + p->fillRect(rect, grad); + + QLinearGradient shadowGradient(spanRect.topLeft(), spanRect.topRight()); + shadowGradient.setColorAt(0, QColor(0, 0, 0, 30)); + QColor lighterHighlight; + if (!lightColored) + lighterHighlight = highlight.lighter(130); + else + lighterHighlight = highlight.lighter(90); + lighterHighlight.setAlpha(100); + shadowGradient.setColorAt(0.7, lighterHighlight); + shadowGradient.setColorAt(1, QColor(0, 0, 0, 40)); + p->fillRect(rect, shadowGradient); +} + +void StyleHelper::horizontalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored) +{ + if (StyleHelper::usePixmapCache()) { + QString key; + QColor keyColor = baseColor(lightColored); + key.sprintf("mh_horizontal %d %d %d %d %d %d", + spanRect.width(), spanRect.height(), clipRect.width(), + clipRect.height(), keyColor.rgb(), spanRect.x()); + + QPixmap pixmap; + if (!QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(clipRect.size()); + QPainter p(&pixmap); + QRect rect = QRect(0, 0, clipRect.width(), clipRect.height()); + horizontalGradientHelper(&p, spanRect, rect, lightColored); + p.end(); + QPixmapCache::insert(key, pixmap); + } + + painter->drawPixmap(clipRect.topLeft(), pixmap); + + } else { + horizontalGradientHelper(painter, spanRect, clipRect, lightColored); + } +} + +static void menuGradientHelper(QPainter *p, const QRect &spanRect, const QRect &rect) +{ + QLinearGradient grad(spanRect.topLeft(), spanRect.bottomLeft()); + QColor menuColor = StyleHelper::mergedColors(StyleHelper::baseColor(), QColor(244, 244, 244), 25); + grad.setColorAt(0, menuColor.lighter(112)); + grad.setColorAt(1, menuColor); + p->fillRect(rect, grad); +} + +void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter, const QStyleOption *option) +{ + // From windowsstyle but modified to enable AA + if (option->rect.width() <= 1 || option->rect.height() <= 1) + return; + + QRect r = option->rect; + int size = qMin(r.height(), r.width()); + QPixmap pixmap; + QString pixmapName; + pixmapName.sprintf("arrow-%s-%d-%d-%d-%lld", + "$qt_ia", + uint(option->state), element, + size, option->palette.cacheKey()); + if (!QPixmapCache::find(pixmapName, pixmap)) { + int border = size/5; + int sqsize = 2*(size/2); + QImage image(sqsize, sqsize, QImage::Format_ARGB32); + image.fill(Qt::transparent); + QPainter imagePainter(&image); + imagePainter.setRenderHint(QPainter::Antialiasing, true); + imagePainter.translate(0.5, 0.5); + QPolygon a; + switch (element) { + case QStyle::PE_IndicatorArrowUp: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize - border, sqsize/2); + break; + case QStyle::PE_IndicatorArrowDown: + a.setPoints(3, border, sqsize/2, sqsize/2, sqsize - border, sqsize - border, sqsize/2); + break; + case QStyle::PE_IndicatorArrowRight: + a.setPoints(3, sqsize - border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + case QStyle::PE_IndicatorArrowLeft: + a.setPoints(3, border, sqsize/2, sqsize/2, border, sqsize/2, sqsize - border); + break; + default: + break; + } + + int bsx = 0; + int bsy = 0; + + if (option->state & QStyle::State_Sunken) { + bsx = qApp->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal); + bsy = qApp->style()->pixelMetric(QStyle::PM_ButtonShiftVertical); + } + + QRect bounds = a.boundingRect(); + int sx = sqsize / 2 - bounds.center().x() - 1; + int sy = sqsize / 2 - bounds.center().y() - 1; + imagePainter.translate(sx + bsx, sy + bsy); + + if (!(option->state & QStyle::State_Enabled)) { + QColor foreGround(150, 150, 150, 150); + imagePainter.setBrush(option->palette.mid().color()); + imagePainter.setPen(option->palette.mid().color()); + } else { + QColor shadow(0, 0, 0, 100); + imagePainter.translate(0, 1); + imagePainter.setPen(shadow); + imagePainter.setBrush(shadow); + QColor foreGround(255, 255, 255, 210); + imagePainter.drawPolygon(a); + imagePainter.translate(0, -1); + imagePainter.setPen(foreGround); + imagePainter.setBrush(foreGround); + } + imagePainter.drawPolygon(a); + imagePainter.end(); + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(pixmapName, pixmap); + } + int xOffset = r.x() + (r.width() - size)/2; + int yOffset = r.y() + (r.height() - size)/2; + painter->drawPixmap(xOffset, yOffset, pixmap); +} + +void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect) +{ + if (StyleHelper::usePixmapCache()) { + QString key; + key.sprintf("mh_menu %d %d %d %d %d", + spanRect.width(), spanRect.height(), clipRect.width(), + clipRect.height(), StyleHelper::baseColor().rgb()); + + QPixmap pixmap; + if (!QPixmapCache::find(key, pixmap)) { + pixmap = QPixmap(clipRect.size()); + QPainter p(&pixmap); + QRect rect = QRect(0, 0, clipRect.width(), clipRect.height()); + menuGradientHelper(&p, spanRect, rect); + p.end(); + QPixmapCache::insert(key, pixmap); + } + + painter->drawPixmap(clipRect.topLeft(), pixmap); + } else { + menuGradientHelper(painter, spanRect, clipRect); + } +} + +// Draws a cached pixmap with shadow +void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, + QPainter *p, QIcon::Mode iconMode, int radius, const QColor &color, const QPoint &offset) +{ + QPixmap cache; + QString pixmapName = QString("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); + + if (!QPixmapCache::find(pixmapName, cache)) { + QPixmap px = icon.pixmap(rect.size()); + cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); + cache.fill(Qt::transparent); + + QPainter cachePainter(&cache); + if (iconMode == QIcon::Disabled) { + QImage im = px.toImage().convertToFormat(QImage::Format_ARGB32); + for (int y=0; ydrawPixmap(targetRect.topLeft() - offset, cache); +} + +// Draws a CSS-like border image where the defined borders are not stretched +void StyleHelper::drawCornerImage(const QImage &img, QPainter *painter, QRect rect, + int left, int top, int right, int bottom) +{ + QSize size = img.size(); + if (top > 0) { //top + painter->drawImage(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), img, + QRect(left, 0, size.width() -right - left, top)); + if (left > 0) //top-left + painter->drawImage(QRect(rect.left(), rect.top(), left, top), img, + QRect(0, 0, left, top)); + if (right > 0) //top-right + painter->drawImage(QRect(rect.left() + rect.width() - right, rect.top(), right, top), img, + QRect(size.width() - right, 0, right, top)); + } + //left + if (left > 0) + painter->drawImage(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), img, + QRect(0, top, left, size.height() - bottom - top)); + //center + painter->drawImage(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left, + rect.height() - bottom - top), img, + QRect(left, top, size.width() -right -left, + size.height() - bottom - top)); + if (right > 0) //right + painter->drawImage(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), img, + QRect(size.width() - right, top, right, size.height() - bottom - top)); + if (bottom > 0) { //bottom + painter->drawImage(QRect(rect.left() +left, rect.top() + rect.height() - bottom, + rect.width() - right - left, bottom), img, + QRect(left, size.height() - bottom, + size.width() - right - left, bottom)); + if (left > 0) //bottom-left + painter->drawImage(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), img, + QRect(0, size.height() - bottom, left, bottom)); + if (right > 0) //bottom-right + painter->drawImage(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), img, + QRect(size.width() - right, size.height() - bottom, right, bottom)); + } +} + +} // namespace Utils diff --git a/3rdparty/fancytabwidget/stylehelper.h b/3rdparty/fancytabwidget/stylehelper.h new file mode 100644 index 000000000..9bdce5c37 --- /dev/null +++ b/3rdparty/fancytabwidget/stylehelper.h @@ -0,0 +1,97 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef STYLEHELPER_H +#define STYLEHELPER_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QPalette; +class QPainter; +class QRect; +// Note, this is exported but in a private header as qtopengl depends on it. +// We should consider adding this as a public helper function. +void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); +QT_END_NAMESPACE + +// Helper class holding all custom color values + +namespace Utils { +class StyleHelper +{ +public: + static const unsigned int DEFAULT_BASE_COLOR = 0x666666; + + // Height of the project explorer navigation bar + static int navigationWidgetHeight() { return 24; } + static qreal sidebarFontSize(); + static QPalette sidebarFontPalette(const QPalette &original); + + // This is our color table, all colors derive from baseColor + static QColor requestedBaseColor() { return m_requestedBaseColor; } + static QColor baseColor(bool lightColored = false); + static QColor panelTextColor(bool lightColored = false); + static QColor highlightColor(bool lightColored = false); + static QColor shadowColor(bool lightColored = false); + static QColor borderColor(bool lightColored = false); + static QColor buttonTextColor() { return QColor(0x4c4c4c); } + static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50); + + static QColor sidebarHighlight() { return QColor(255, 255, 255, 40); } + static QColor sidebarShadow() { return QColor(0, 0, 0, 40); } + + // Sets the base color and makes sure all top level widgets are updated + static void setBaseColor(const QColor &color); + + // Draws a shaded anti-aliased arrow + static void drawArrow(QStyle::PrimitiveElement element, QPainter *painter, const QStyleOption *option); + + // Gradients used for panels + static void horizontalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored = false); + static void verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored = false); + static void menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect); + static bool usePixmapCache() { return true; } + + static void drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, + int radius = 3, const QColor &color = QColor(0, 0, 0, 130), + const QPoint &offset = QPoint(1, -2)); + static void drawCornerImage(const QImage &img, QPainter *painter, QRect rect, + int left = 0, int top = 0, int right = 0, int bottom = 0); + +private: + static QColor m_baseColor; + static QColor m_requestedBaseColor; +}; + +} // namespace Utils + +using Utils::StyleHelper; +#endif // STYLEHELPER_H diff --git a/CMakeLists.txt b/CMakeLists.txt index 68e706f5d..67dc6fbb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ include_directories(${GLIB_INCLUDE_DIRS}) include_directories(${GLIBCONFIG_INCLUDE_DIRS}) include_directories(${LIBXML_INCLUDE_DIRS}) include_directories(${LASTFM_INCLUDE_DIRS}) +include_directories("3rdparty/fancytabwidget") include_directories("3rdparty/qsqlite") include_directories("3rdparty/universalchardet") @@ -213,6 +214,7 @@ if (WIN32) add_subdirectory(3rdparty/qtwin) endif (WIN32) add_subdirectory(3rdparty/universalchardet) +add_subdirectory(3rdparty/fancytabwidget) add_subdirectory(tests) add_subdirectory(dist) add_subdirectory(tools/ultimate_lyrics_parser) diff --git a/data/data.qrc b/data/data.qrc index 197ce3d78..a5747d1b7 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -1,7 +1,6 @@ mainwindow.css - slimbuttonbox.css schema.sql volumeslider-handle_glow.png volumeslider-handle.png diff --git a/data/slimbuttonbox.css b/data/slimbuttonbox.css deleted file mode 100644 index 2fd29ca0a..000000000 --- a/data/slimbuttonbox.css +++ /dev/null @@ -1,22 +0,0 @@ -QPushButton { - border: 1px solid palette(dark); - border-radius: 4px; - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 palette(button), stop: 1 palette(dark)); - padding: 1px 5px 1px 5px; - margin: 0px; - min-width: 60px; - min-height: 18px; -} - -QPushButton:hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 palette(light), stop: 1 palette(button)); -} - -QPushButton:checked:!disabled { - border: 1px solid palette(text); - color: palette(highlighted-text); - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 palette(highlight), stop: 1 %darkhighlight); -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7cff3ea4b..3427e5d91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -80,6 +80,7 @@ set(SOURCES library/libraryplaylistitem.cpp library/libraryquery.cpp library/libraryview.cpp + library/libraryviewcontainer.cpp library/librarywatcher.cpp library/sqlrow.cpp @@ -88,7 +89,6 @@ set(SOURCES lyrics/lyricprovider.cpp lyrics/lyricsettings.cpp lyrics/lyricview.cpp - lyrics/songinfobuttonbox.cpp lyrics/ultimatelyricsreader.cpp playlist/playlist.cpp @@ -167,7 +167,6 @@ set(SOURCES widgets/osdpretty.cpp widgets/progressitemdelegate.cpp widgets/sliderwidget.cpp - widgets/slimbuttonbox.cpp widgets/spinbox.cpp widgets/stickyslider.cpp widgets/stretchheaderview.cpp @@ -217,6 +216,7 @@ set(HEADERS library/libraryfilterwidget.h library/librarymodel.h library/libraryview.h + library/libraryviewcontainer.h library/librarywatcher.h lyrics/htmlscraper.h @@ -224,7 +224,6 @@ set(HEADERS lyrics/lyricprovider.h lyrics/lyricsettings.h lyrics/lyricview.h - lyrics/songinfobuttonbox.h lyrics/ultimatelyricsreader.h playlist/playlist.h @@ -296,7 +295,6 @@ set(HEADERS widgets/osdpretty.h widgets/progressitemdelegate.h widgets/sliderwidget.h - widgets/slimbuttonbox.h widgets/spinbox.h widgets/stickyslider.h widgets/stretchheaderview.h @@ -309,6 +307,7 @@ set(UI library/groupbydialog.ui library/libraryconfig.ui library/libraryfilterwidget.ui + library/libraryviewcontainer.ui lyrics/lyricsettings.ui lyrics/lyricview.ui @@ -679,6 +678,7 @@ add_dependencies(clementine_lib pot) target_link_libraries(clementine_lib chardet + fancytabwidget ${GOBJECT_LIBRARIES} ${GLIB_LIBRARIES} ${TAGLIB_LIBRARIES} diff --git a/src/devices/deviceview.cpp b/src/devices/deviceview.cpp index c881e4cd0..6de54cb15 100644 --- a/src/devices/deviceview.cpp +++ b/src/devices/deviceview.cpp @@ -150,6 +150,11 @@ DeviceView::DeviceView(QWidget* parent) setItemDelegate(new DeviceItemDelegate(this)); SetExpandOnReset(false); setAttribute(Qt::WA_MacShowFocusRect, false); + setHeaderHidden(true); + setAllColumnsShowFocus(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DragOnly); + setSelectionMode(QAbstractItemView::ExtendedSelection); } DeviceView::~DeviceView() { diff --git a/src/library/libraryview.cpp b/src/library/libraryview.cpp index 317586c34..bc15bc39e 100644 --- a/src/library/libraryview.cpp +++ b/src/library/libraryview.cpp @@ -92,6 +92,11 @@ LibraryView::LibraryView(QWidget* parent) { setItemDelegate(new LibraryItemDelegate(this)); setAttribute(Qt::WA_MacShowFocusRect, false); + setHeaderHidden(true); + setAllColumnsShowFocus(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DragOnly); + setSelectionMode(QAbstractItemView::ExtendedSelection); ReloadSettings(); } diff --git a/src/library/libraryviewcontainer.cpp b/src/library/libraryviewcontainer.cpp new file mode 100644 index 000000000..fd6d9e97f --- /dev/null +++ b/src/library/libraryviewcontainer.cpp @@ -0,0 +1,41 @@ +/* This file is part of Clementine. + + Clementine 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. + + Clementine 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 Clementine. If not, see . +*/ + +#include "libraryviewcontainer.h" +#include "ui_libraryviewcontainer.h" + +LibraryViewContainer::LibraryViewContainer(QWidget* parent) + : QWidget(parent), + ui_(new Ui_LibraryViewContainer) +{ + ui_->setupUi(this); + + connect(filter(), SIGNAL(UpPressed()), view(), SLOT(UpAndFocus())); + connect(filter(), SIGNAL(DownPressed()), view(), SLOT(DownAndFocus())); + connect(filter(), SIGNAL(ReturnPressed()), view(), SLOT(FilterReturnPressed())); +} + +LibraryViewContainer::~LibraryViewContainer() { + delete ui_; +} + +LibraryView* LibraryViewContainer::view() const { + return ui_->view; +} + +LibraryFilterWidget* LibraryViewContainer::filter() const { + return ui_->filter; +} diff --git a/src/widgets/slimbuttonbox.h b/src/library/libraryviewcontainer.h similarity index 53% rename from src/widgets/slimbuttonbox.h rename to src/library/libraryviewcontainer.h index 07bbef193..ba1d7ef27 100644 --- a/src/widgets/slimbuttonbox.h +++ b/src/library/libraryviewcontainer.h @@ -14,43 +14,27 @@ along with Clementine. If not, see . */ -#ifndef SLIMBUTTONBOX_H -#define SLIMBUTTONBOX_H +#ifndef LIBRARYVIEWCONTAINER_H +#define LIBRARYVIEWCONTAINER_H -#include -#include #include -class QPushButton; +class LibraryFilterWidget; +class LibraryView; +class Ui_LibraryViewContainer; -class SlimButtonBox : public QWidget { +class LibraryViewContainer : public QWidget { Q_OBJECT public: - SlimButtonBox(QWidget* parent = 0); + LibraryViewContainer(QWidget* parent = 0); + ~LibraryViewContainer(); - void AddButton(const QString& text, const QIcon& icon = QIcon()); - bool IsAnyButtonChecked() const; - void SetCurrentButton(int index); - - void SetTabBarBase(bool tab_bar_base); - -signals: - void CurrentChanged(int index); - -protected: - void changeEvent(QEvent* e); - void paintEvent(QPaintEvent*); - -private slots: - void ButtonClicked(); + LibraryFilterWidget* filter() const; + LibraryView* view() const; private: - void ReloadStylesheet(); - -private: - bool tab_bar_base_; - QList buttons_; + Ui_LibraryViewContainer* ui_; }; -#endif // SLIMBUTTONBOX_H +#endif // LIBRARYVIEWCONTAINER_H diff --git a/src/library/libraryviewcontainer.ui b/src/library/libraryviewcontainer.ui new file mode 100644 index 000000000..e07e906a0 --- /dev/null +++ b/src/library/libraryviewcontainer.ui @@ -0,0 +1,47 @@ + + + LibraryViewContainer + + + + 0 + 0 + 400 + 300 + + + + Form + + + + 0 + + + 0 + + + + + + + + + + + + LibraryFilterWidget + QWidget +
library/libraryfilterwidget.h
+ 1 +
+ + LibraryView + QWidget +
library/libraryview.h
+ 1 +
+
+ + +
diff --git a/src/lyrics/songinfobuttonbox.cpp b/src/lyrics/songinfobuttonbox.cpp deleted file mode 100644 index 61ff1dba8..000000000 --- a/src/lyrics/songinfobuttonbox.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* This file is part of Clementine. - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "lyricview.h" -#include "songinfobuttonbox.h" - -#include -#include -#include - -const char* SongInfoButtonBox::kSettingsGroup = "SongInfo"; - -SongInfoButtonBox::SongInfoButtonBox(QWidget* parent) - : SlimButtonBox(parent), - splitter_(NULL), - stack_(NULL), - lyrics_(NULL) -{ - setEnabled(false); - AddButton(tr("Lyrics")); - AddButton(tr("Song info")); - AddButton(tr("Artist info")); - - connect(this, SIGNAL(CurrentChanged(int)), SLOT(SetActive(int))); -} - -void SongInfoButtonBox::SetSplitter(QSplitter* splitter) { - splitter_ = splitter; - connect(splitter_, SIGNAL(splitterMoved(int,int)), SLOT(SplitterSizeChanged())); - - stack_ = new QStackedWidget; - splitter->addWidget(stack_); - stack_->setVisible(false); - - lyrics_ = new LyricView; - stack_->addWidget(lyrics_); - stack_->addWidget(new QWidget); - stack_->addWidget(new QWidget); - - // Restore settings - QSettings s; - s.beginGroup(kSettingsGroup); - - const int current_index = s.value("current_index", -1).toInt(); - SetCurrentButton(current_index); - SetActive(current_index); - - if (!splitter_->restoreState(s.value("splitter_state").toByteArray())) { - // Set sensible default sizes - splitter_->setSizes(QList() << 850 << 150); - } -} - -LyricFetcher* SongInfoButtonBox::lyric_fetcher() const { - return lyrics_->fetcher(); -} - -void SongInfoButtonBox::SongChanged(const Song& metadata) { - setEnabled(true); - - metadata_ = metadata; - - if (IsAnyButtonChecked()) { - stack_->show(); - UpdateCurrentSong(); - } -} - -void SongInfoButtonBox::SongFinished() { - metadata_ = Song(); - setEnabled(false); - stack_->hide(); -} - -void SongInfoButtonBox::SetActive(int index) { - if (index == -1) { - stack_->hide(); - } else { - if (isEnabled()) - stack_->show(); - stack_->setCurrentIndex(index); - if (metadata_.is_valid()) - UpdateCurrentSong(); - } - - QSettings s; - s.beginGroup(kSettingsGroup); - s.setValue("current_index", index); -} - -void SongInfoButtonBox::SplitterSizeChanged() { - QSettings s; - s.beginGroup(kSettingsGroup); - s.setValue("splitter_state", splitter_->saveState()); -} - -void SongInfoButtonBox::UpdateCurrentSong() { - QMetaObject::invokeMethod(stack_->currentWidget(), "SongChanged", - Q_ARG(Song, metadata_)); -} diff --git a/src/lyrics/songinfobuttonbox.h b/src/lyrics/songinfobuttonbox.h deleted file mode 100644 index 6ab4a1445..000000000 --- a/src/lyrics/songinfobuttonbox.h +++ /dev/null @@ -1,62 +0,0 @@ -/* This file is part of Clementine. - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#ifndef SONGINFOBUTTONBOX_H -#define SONGINFOBUTTONBOX_H - -#include "core/song.h" -#include "widgets/slimbuttonbox.h" - -class QSplitter; -class QStackedWidget; - -class LyricFetcher; -class LyricView; - -class SongInfoButtonBox : public SlimButtonBox { - Q_OBJECT - -public: - SongInfoButtonBox(QWidget* parent = 0); - - static const char* kSettingsGroup; - - void SetSplitter(QSplitter* splitter); - - LyricFetcher* lyric_fetcher() const; - LyricView* lyric_view() const { return lyrics_; } - -public slots: - void SongChanged(const Song& metadata); - void SongFinished(); - -private slots: - void SetActive(int index); - void SplitterSizeChanged(); - -private: - void UpdateCurrentSong(); - -private: - QSplitter* splitter_; - QStackedWidget* stack_; - - LyricView* lyrics_; - - Song metadata_; -}; - -#endif // SONGINFOBUTTONBOX_H diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp index 14c225f17..adf68e844 100644 --- a/src/playlist/playlistcontainer.cpp +++ b/src/playlist/playlistcontainer.cpp @@ -17,7 +17,6 @@ #include "playlistcontainer.h" #include "playlistmanager.h" #include "ui_playlistcontainer.h" -#include "lyrics/songinfobuttonbox.h" #include "playlistparsers/playlistparser.h" #include "ui/iconloader.h" #include "widgets/maclineedit.h" @@ -36,7 +35,6 @@ const char* PlaylistContainer::kSettingsGroup = "Playlist"; PlaylistContainer::PlaylistContainer(QWidget *parent) : QWidget(parent), ui_(new Ui_PlaylistContainer), - song_info_button_box_(new SongInfoButtonBox(this)), manager_(NULL), undo_(NULL), redo_(NULL), @@ -47,12 +45,6 @@ PlaylistContainer::PlaylistContainer(QWidget *parent) { ui_->setupUi(this); - song_info_button_box_->SetSplitter(ui_->splitter); - - // Initially add the info button box to the toolbar, but it might get moved - // later when the user adds a playlist. - ui_->toolbar->layout()->addWidget(song_info_button_box_); - no_matches_label_->setText(tr("No matches found. Clear the search box to show the whole playlist again.")); no_matches_label_->setAlignment(Qt::AlignTop | Qt::AlignHCenter); no_matches_label_->setAttribute(Qt::WA_TransparentForMouseEvents); @@ -82,7 +74,7 @@ PlaylistContainer::PlaylistContainer(QWidget *parent) ui_->tab_bar->setMovable(true); connect(tab_bar_animation_, SIGNAL(frameChanged(int)), SLOT(SetTabBarHeight(int))); - ui_->tab_bar_container->setMaximumHeight(0); + ui_->tab_bar->setMaximumHeight(0); // Connections connect(ui_->clear, SIGNAL(clicked()), SLOT(ClearFilter())); @@ -237,7 +229,7 @@ void PlaylistContainer::PlaylistAdded(int id, const QString &name) { // Skip the animation since the window is hidden (eg. if we're still // loading the UI). tab_bar_visible_ = true; - SetTabBarHeight(tab_bar_animation_->endFrame()); + ui_->tab_bar->setMaximumHeight(tab_bar_animation_->endFrame()); } else { SetTabBarVisible(true); } @@ -330,17 +322,10 @@ void PlaylistContainer::SetTabBarVisible(bool visible) { tab_bar_animation_->setDirection(visible ? QTimeLine::Forward : QTimeLine::Backward); tab_bar_animation_->start(); - - if (visible) { - ui_->tab_bar_container->layout()->addWidget(song_info_button_box_); - } else { - ui_->toolbar->layout()->addWidget(song_info_button_box_); - } - song_info_button_box_->SetTabBarBase(visible); } void PlaylistContainer::SetTabBarHeight(int height) { - ui_->tab_bar_container->setMaximumHeight(height); + ui_->tab_bar->setMaximumHeight(height); } void PlaylistContainer::UpdateFilter() { diff --git a/src/playlist/playlistcontainer.h b/src/playlist/playlistcontainer.h index 5cabf191e..55c382835 100644 --- a/src/playlist/playlistcontainer.h +++ b/src/playlist/playlistcontainer.h @@ -26,7 +26,6 @@ class LineEditInterface; class Playlist; class PlaylistManager; class PlaylistView; -class SongInfoButtonBox; class QTimeLine; class QLabel; @@ -45,7 +44,6 @@ public: void SetManager(PlaylistManager* manager); PlaylistView* view() const; - SongInfoButtonBox* song_info() const { return song_info_button_box_; } signals: void TabChanged(int id); @@ -88,7 +86,6 @@ private: private: Ui_PlaylistContainer* ui_; - SongInfoButtonBox* song_info_button_box_; PlaylistManager* manager_; QAction* undo_; diff --git a/src/playlist/playlistcontainer.ui b/src/playlist/playlistcontainer.ui index 40b0d8933..2b4655039 100644 --- a/src/playlist/playlistcontainer.ui +++ b/src/playlist/playlistcontainer.ui @@ -20,7 +20,7 @@ border-width: 0px 1px 0px 1px; } - + 0 @@ -28,26 +28,7 @@ 0 - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - - + @@ -154,48 +135,37 @@ - - - - 0 - 0 - + + + true - - Qt::Horizontal + + QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + true + + + QAbstractItemView::DragDrop + + + QAbstractItemView::ExtendedSelection + + + false + + + true + + + false + + + true + + + true - - - true - - - QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked - - - true - - - QAbstractItemView::DragDrop - - - QAbstractItemView::ExtendedSelection - - - false - - - true - - - false - - - true - - - true - - diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index e8bedc930..a4c5fc78d 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -15,6 +15,7 @@ */ #include "mainwindow.h" +#include "stylehelper.h" #include "ui_mainwindow.h" #include "core/commandlineoptions.h" #include "core/database.h" @@ -28,15 +29,17 @@ #include "core/taskmanager.h" #include "devices/devicemanager.h" #include "devices/devicestatefiltermodel.h" +#include "devices/deviceview.h" #include "engines/enginebase.h" #include "library/groupbydialog.h" +#include "library/library.h" #include "library/librarybackend.h" #include "library/libraryconfig.h" #include "library/librarydirectorymodel.h" -#include "library/library.h" +#include "library/libraryfilterwidget.h" +#include "library/libraryviewcontainer.h" #include "lyrics/lyricfetcher.h" #include "lyrics/lyricview.h" -#include "lyrics/songinfobuttonbox.h" #include "playlist/playlistbackend.h" #include "playlist/playlist.h" #include "playlist/playlistmanager.h" @@ -68,6 +71,7 @@ #include "ui/settingsdialog.h" #include "ui/systemtrayicon.h" #include "widgets/errordialog.h" +#include "widgets/fileview.h" #include "widgets/multiloadingindicator.h" #include "widgets/osd.h" #include "widgets/trackslider.h" @@ -84,19 +88,22 @@ # include "visualisations/visualisationcontainer.h" #endif -#include -#include -#include +#include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include + #include @@ -130,6 +137,11 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg library_(NULL), global_shortcuts_(new GlobalShortcuts(this)), devices_(NULL), + library_view_(new LibraryViewContainer(this)), + file_view_(new FileView(this)), + radio_view_(new RadioViewContainer(this)), + device_view_(new DeviceView(this)), + lyric_view_(new LyricView(this)), settings_dialog_(NULL), cover_manager_(NULL), equalizer_(new Equalizer), @@ -166,14 +178,21 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg ui_->multi_loading_indicator->SetTaskManager(task_manager_); ui_->volume->setValue(player_->GetVolume()); + // Add tabs to the fancy tab widget + AddFancyTab(library_view_, IconLoader::Load("folder-sound"), tr("Library")); + AddFancyTab(file_view_, IconLoader::Load("document-open"), tr("Files")); + AddFancyTab(radio_view_, QIcon(":last.fm/icon_radio.png"), tr("Internet")); + AddFancyTab(device_view_, IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Devices")); + AddFancyTab(lyric_view_, IconLoader::Load("view-media-lyrics"), tr("Lyrics")); + AddFancyTab(new QWidget, IconLoader::Load("view-media-lyrics"), tr("Song info")); + AddFancyTab(new QWidget, IconLoader::Load("view-media-lyrics"), tr("Artist info")); + + ui_->tabs->statusBar()->hide(); + StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker()); + track_position_timer_->setInterval(1000); connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition())); -#ifdef Q_OS_MAC - // For some reason this makes the tabs go a funny colour on mac - ui_->tabs->setDocumentMode(false); -#endif - // Start initialising the player player_->Init(); @@ -193,15 +212,15 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg ui_->playlist->SetManager(playlists_); - ui_->library_view->setModel(library_sort_model_); - ui_->library_view->SetLibrary(library_->model()); - ui_->library_view->SetTaskManager(task_manager_); - ui_->library_view->SetDeviceManager(devices_); + library_view_->view()->setModel(library_sort_model_); + library_view_->view()->SetLibrary(library_->model()); + library_view_->view()->SetTaskManager(task_manager_); + library_view_->view()->SetDeviceManager(devices_); - ui_->radio_view->SetModel(radio_model_); + radio_view_->SetModel(radio_model_); - ui_->devices_view->SetDeviceManager(devices_); - ui_->devices_view->SetLibrary(library_->model()); + device_view_->SetDeviceManager(devices_); + device_view_->SetLibrary(library_->model()); organise_dialog_->SetDestinationModel(library_->model()->directory_model()); @@ -235,14 +254,14 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg ui_->action_rain->setIcon(IconLoader::Load("weather-showers-scattered")); // File view connections - connect(ui_->file_view, SIGNAL(AddToPlaylist(QList)), SLOT(AddFilesToPlaylist(QList))); - connect(ui_->file_view, SIGNAL(Load(QList)), SLOT(LoadFilesToPlaylist(QList))); - connect(ui_->file_view, SIGNAL(DoubleClicked(QList)), SLOT(FilesDoubleClicked(QList))); - connect(ui_->file_view, SIGNAL(PathChanged(QString)), SLOT(FilePathChanged(QString))); - connect(ui_->file_view, SIGNAL(CopyToLibrary(QList)), SLOT(CopyFilesToLibrary(QList))); - connect(ui_->file_view, SIGNAL(MoveToLibrary(QList)), SLOT(MoveFilesToLibrary(QList))); - connect(ui_->file_view, SIGNAL(CopyToDevice(QList)), SLOT(CopyFilesToDevice(QList))); - ui_->file_view->SetTaskManager(task_manager_); + connect(file_view_, SIGNAL(AddToPlaylist(QList)), SLOT(AddFilesToPlaylist(QList))); + connect(file_view_, SIGNAL(Load(QList)), SLOT(LoadFilesToPlaylist(QList))); + connect(file_view_, SIGNAL(DoubleClicked(QList)), SLOT(FilesDoubleClicked(QList))); + connect(file_view_, SIGNAL(PathChanged(QString)), SLOT(FilePathChanged(QString))); + connect(file_view_, SIGNAL(CopyToLibrary(QList)), SLOT(CopyFilesToLibrary(QList))); + connect(file_view_, SIGNAL(MoveToLibrary(QList)), SLOT(MoveFilesToLibrary(QList))); + connect(file_view_, SIGNAL(CopyToDevice(QList)), SLOT(CopyFilesToDevice(QList))); + file_view_->SetTaskManager(task_manager_); // Action connections connect(ui_->action_next_track, SIGNAL(triggered()), player_, SLOT(Next())); @@ -325,14 +344,12 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg connect(player_, SIGNAL(Paused()), osd_, SLOT(Paused())); connect(player_, SIGNAL(Stopped()), osd_, SLOT(Stopped())); connect(player_, SIGNAL(PlaylistFinished()), osd_, SLOT(PlaylistFinished())); - connect(player_, SIGNAL(Stopped()), ui_->playlist->song_info(), SLOT(SongFinished())); - connect(player_, SIGNAL(PlaylistFinished()), ui_->playlist->song_info(), SLOT(SongFinished())); connect(player_, SIGNAL(VolumeChanged(int)), osd_, SLOT(VolumeChanged(int))); connect(player_, SIGNAL(VolumeChanged(int)), ui_->volume, SLOT(setValue(int))); connect(player_, SIGNAL(ForceShowOSD(Song)), SLOT(ForceShowOSD(Song))); connect(playlists_, SIGNAL(CurrentSongChanged(Song)), osd_, SLOT(SongChanged(Song))); connect(playlists_, SIGNAL(CurrentSongChanged(Song)), player_, SLOT(CurrentMetadataChanged(Song))); - connect(playlists_, SIGNAL(CurrentSongChanged(Song)), ui_->playlist->song_info(), SLOT(SongChanged(Song))); + connect(playlists_, SIGNAL(CurrentSongChanged(Song)), lyric_view_, SLOT(SongChanged(Song))); connect(playlists_, SIGNAL(PlaylistChanged()), player_, SLOT(PlaylistChanged())); connect(playlists_, SIGNAL(EditingFinished(QModelIndex)), SLOT(PlaylistEditFinished(QModelIndex))); connect(playlists_, SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString))); @@ -349,31 +366,28 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg connect(database_->Worker().get(), SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString))); // Library connections - connect(ui_->library_view, SIGNAL(doubleClicked(QModelIndex)), SLOT(LibraryItemDoubleClicked(QModelIndex))); - connect(ui_->library_view, SIGNAL(Load(QModelIndexList)), SLOT(LoadLibraryItemToPlaylist(QModelIndexList))); - connect(ui_->library_view, SIGNAL(AddToPlaylist(QModelIndexList)), SLOT(AddLibraryItemToPlaylist(QModelIndexList))); - connect(ui_->library_view, SIGNAL(ShowConfigDialog()), SLOT(ShowLibraryConfig())); - connect(library_->model(), SIGNAL(TotalSongCountUpdated(int)), ui_->library_view, SLOT(TotalSongCountUpdated(int))); + connect(library_view_->view(), SIGNAL(doubleClicked(QModelIndex)), SLOT(LibraryItemDoubleClicked(QModelIndex))); + connect(library_view_->view(), SIGNAL(Load(QModelIndexList)), SLOT(LoadLibraryItemToPlaylist(QModelIndexList))); + connect(library_view_->view(), SIGNAL(AddToPlaylist(QModelIndexList)), SLOT(AddLibraryItemToPlaylist(QModelIndexList))); + connect(library_view_->view(), SIGNAL(ShowConfigDialog()), SLOT(ShowLibraryConfig())); + connect(library_->model(), SIGNAL(TotalSongCountUpdated(int)), library_view_->view(), SLOT(TotalSongCountUpdated(int))); connect(task_manager_, SIGNAL(PauseLibraryWatchers()), library_, SLOT(PauseWatcher())); connect(task_manager_, SIGNAL(ResumeLibraryWatchers()), library_, SLOT(ResumeWatcher())); // Devices connections connect(devices_, SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString))); - connect(ui_->devices_view, SIGNAL(Load(SongList)), SLOT(LoadDeviceSongsToPlaylist(SongList))); - connect(ui_->devices_view, SIGNAL(AddToPlaylist(SongList)), SLOT(AddDeviceSongsToPlaylist(SongList))); - connect(ui_->devices_view, SIGNAL(DoubleClicked(SongList)), SLOT(DeviceSongsDoubleClicked(SongList))); + connect(device_view_, SIGNAL(Load(SongList)), SLOT(LoadDeviceSongsToPlaylist(SongList))); + connect(device_view_, SIGNAL(AddToPlaylist(SongList)), SLOT(AddDeviceSongsToPlaylist(SongList))); + connect(device_view_, SIGNAL(DoubleClicked(SongList)), SLOT(DeviceSongsDoubleClicked(SongList))); // Library filter widget QAction* library_config_action = new QAction( IconLoader::Load("configure"), tr("Configure library..."), this); connect(library_config_action, SIGNAL(triggered()), SLOT(ShowLibraryConfig())); - ui_->library_filter->SetSettingsGroup(kSettingsGroup); - ui_->library_filter->SetLibraryModel(library_->model()); - ui_->library_filter->AddMenuAction(library_config_action); - connect(ui_->library_filter, SIGNAL(UpPressed()), ui_->library_view, SLOT(UpAndFocus())); - connect(ui_->library_filter, SIGNAL(DownPressed()), ui_->library_view, SLOT(DownAndFocus())); - connect(ui_->library_filter, SIGNAL(ReturnPressed()), ui_->library_view, SLOT(FilterReturnPressed())); + library_view_->filter()->SetSettingsGroup(kSettingsGroup); + library_view_->filter()->SetLibraryModel(library_->model()); + library_view_->filter()->AddMenuAction(library_config_action); // Playlist menu playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay())); @@ -421,7 +435,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg connect(radio_model_, SIGNAL(AddItemsToPlaylist(PlaylistItemList)), SLOT(InsertRadioItems(PlaylistItemList))); connect(radio_model_->GetLastFMService(), SIGNAL(ScrobblingEnabledChanged(bool)), SLOT(ScrobblingEnabledChanged(bool))); connect(radio_model_->GetLastFMService(), SIGNAL(ButtonVisibilityChanged(bool)), SLOT(LastFMButtonVisibilityChanged(bool))); - connect(ui_->radio_view->tree(), SIGNAL(doubleClicked(QModelIndex)), SLOT(RadioDoubleClick(QModelIndex))); + connect(radio_view_->tree(), SIGNAL(doubleClicked(QModelIndex)), SLOT(RadioDoubleClick(QModelIndex))); connect(radio_model_->Service(), SIGNAL(DownloadFinished(QStringList)), osd_, SLOT(MagnatuneDownloadFinished(QStringList))); LastFMButtonVisibilityChanged(radio_model_->GetLastFMService()->AreButtonsVisible()); @@ -474,7 +488,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg connect(global_shortcuts_, SIGNAL(ShowOSD()), player_, SLOT(ShowOSD())); // Lyrics - ui_->playlist->song_info()->lyric_view()->set_network(network); + lyric_view_->set_network(network); // Analyzer ui_->analyzer->SetEngine(player_->GetEngine()); @@ -521,7 +535,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg ui_->splitter->setSizes(QList() << 200 << width() - 200); } ui_->tabs->setCurrentIndex(settings_.value("current_tab", 0).toInt()); - ui_->file_view->SetPath(settings_.value("file_path", QDir::homePath()).toString()); + file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString()); ReloadSettings(); @@ -1476,17 +1490,17 @@ void MainWindow::EnsureSettingsDialogCreated() { #endif settings_dialog_->SetGlobalShortcutManager(global_shortcuts_); - settings_dialog_->SetLyricFetcher(ui_->playlist->song_info()->lyric_fetcher()); + settings_dialog_->SetLyricFetcher(lyric_view_->fetcher()); // Settings connect(settings_dialog_.get(), SIGNAL(accepted()), SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(accepted()), library_, SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(accepted()), player_, SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(accepted()), osd_, SLOT(ReloadSettings())); - connect(settings_dialog_.get(), SIGNAL(accepted()), ui_->library_view, SLOT(ReloadSettings())); + connect(settings_dialog_.get(), SIGNAL(accepted()), library_view_, SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(accepted()), player_->GetEngine(), SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(accepted()), ui_->playlist->view(), SLOT(ReloadSettings())); - connect(settings_dialog_.get(), SIGNAL(accepted()), ui_->playlist->song_info()->lyric_fetcher(), SLOT(ReloadSettings())); + connect(settings_dialog_.get(), SIGNAL(accepted()), lyric_view_->fetcher(), SLOT(ReloadSettings())); #ifdef ENABLE_WIIMOTEDEV connect(settings_dialog_.get(), SIGNAL(accepted()), wiimotedev_shortcuts_.get(), SLOT(ReloadSettings())); connect(settings_dialog_.get(), SIGNAL(SetWiimotedevInterfaceActived(bool)), wiimotedev_shortcuts_.get(), SLOT(SetWiimotedevInterfaceActived(bool))); @@ -1562,3 +1576,9 @@ void MainWindow::ShowVisualisations() { visualisation_->show(); #endif // ENABLE_VISUALISATIONS } + +void MainWindow::AddFancyTab(QWidget* widget, const QIcon& icon, const QString& label) { + const int i = ui_->tabs->count(); + ui_->tabs->insertTab(i, widget, icon, label); + ui_->tabs->setTabEnabled(i, true); +} diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 3e2abfdfb..88c825776 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -36,12 +36,16 @@ class AlbumCoverManager; class CommandlineOptions; class Database; class DeviceManager; +class DeviceView; class EditTagDialog; class Equalizer; class ErrorDialog; +class FileView; class GlobalShortcuts; class GroupByDialog; class Library; +class LibraryViewContainer; +class LyricView; class MultiLoadingIndicator; class NetworkAccessManager; class OrganiseDialog; @@ -53,6 +57,7 @@ class PlaylistParser; class QueueManager; class RadioItem; class RadioModel; +class RadioViewContainer; class Song; class SystemTrayIcon; class TaskManager; @@ -190,6 +195,7 @@ class MainWindow : public QMainWindow, public PlatformInterface { void AddLibrarySongsToPlaylist(bool clear_first, const SongList& songs); void AddDeviceSongsToPlaylist(bool clear_first, const SongList& songs); void AddUrls(bool play_now, const QList& urls); + void AddFancyTab(QWidget* widget, const QIcon& icon, const QString& label); private: Ui_MainWindow* ui_; @@ -212,6 +218,12 @@ class MainWindow : public QMainWindow, public PlatformInterface { DeviceManager* devices_; + LibraryViewContainer* library_view_; + FileView* file_view_; + RadioViewContainer* radio_view_; + DeviceView* device_view_; + LyricView* lyric_view_; + boost::scoped_ptr settings_dialog_; boost::scoped_ptr add_stream_dialog_; boost::scoped_ptr cover_manager_; diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index 199359cbc..d863ab372 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -36,131 +36,7 @@ 0 - - - QTabWidget::North - - - 0 - - - true - - - true - - - false - - - true - - - - Library - - - - 0 - - - 0 - - - - - - - - true - - - QAbstractItemView::DragOnly - - - true - - - QAbstractItemView::ExtendedSelection - - - true - - - false - - - - - - - - Files - - - - 0 - - - 0 - - - - - - - - - Internet - - - - 0 - - - 0 - - - - - - - - - Devices - - - - 0 - - - 0 - - - - - true - - - QAbstractItemView::DragOnly - - - true - - - QAbstractItemView::ExtendedSelection - - - true - - - true - - - - - - + @@ -860,35 +736,12 @@ QSlider
widgets/sliderwidget.h
- - LibraryView - QTreeView -
library/libraryview.h
-
- - FileView - QWidget -
widgets/fileview.h
- 1 -
AnalyzerContainer QWidget
analyzers/analyzercontainer.h
1
- - LibraryFilterWidget - QWidget -
library/libraryfilterwidget.h
- 1 -
- - RadioViewContainer - QWidget -
radio/radioviewcontainer.h
- 1 -
PlaylistContainer QWidget @@ -920,9 +773,16 @@ 1 - DeviceView - QTreeView -
devices/deviceview.h
+ FancyTabWidget + QWidget +
fancytabwidget.h
+ 0 +
+ + LyricView + QWidget +
lyrics/lyricview.h
+ 1
diff --git a/src/widgets/slimbuttonbox.cpp b/src/widgets/slimbuttonbox.cpp deleted file mode 100644 index 5f7f63b17..000000000 --- a/src/widgets/slimbuttonbox.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* This file is part of Clementine. - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "slimbuttonbox.h" - -#include -#include -#include -#include -#include -#include - -SlimButtonBox::SlimButtonBox(QWidget* parent) - : QWidget(parent), - tab_bar_base_(false) -{ - setLayout(new QHBoxLayout); - layout()->setSpacing(3); - layout()->setContentsMargins(6, 0, 0, 0); - - ReloadStylesheet(); -} - -void SlimButtonBox::AddButton(const QString& text, const QIcon& icon) { - QPushButton* button = new QPushButton(icon, text, this); - button->setCheckable(true); - - connect(button, SIGNAL(clicked()), SLOT(ButtonClicked())); - - layout()->addWidget(button); - buttons_ << button; -} - -void SlimButtonBox::ButtonClicked() { - QPushButton* button = qobject_cast(sender()); - if (!button) - return; - - if (!button->isChecked()) { - emit CurrentChanged(-1); - } else { - // Uncheck all the other buttons as well. We can't use auto exclusive, - // because we want to allow no buttons being pressed. - foreach (QPushButton* other_button, buttons_) { - if (other_button != button) - other_button->setChecked(false); - } - - emit CurrentChanged(buttons_.indexOf(button)); - } -} - -void SlimButtonBox::changeEvent(QEvent* e) { - if (e->type() == QEvent::PaletteChange) { - ReloadStylesheet(); - } -} - -void SlimButtonBox::paintEvent(QPaintEvent*) { - QStylePainter p(this); - - if (tab_bar_base_) { - QStyleOptionTabBarBaseV2 opt; - opt.initFrom(this); - opt.documentMode = true; - opt.shape = QTabBar::RoundedSouth; - - p.drawPrimitive(QStyle::PE_FrameTabBarBase, opt); - } -} - -void SlimButtonBox::ReloadStylesheet() { - QFile resource(":/slimbuttonbox.css"); - resource.open(QIODevice::ReadOnly); - QString css = QString::fromLatin1(resource.readAll()); - - css.replace("%darkhighlight", palette().color(QPalette::Highlight).darker(150).name()); - setStyleSheet(css); -} - -void SlimButtonBox::SetTabBarBase(bool tab_bar_base) { - tab_bar_base_ = tab_bar_base; - update(); -} - -bool SlimButtonBox::IsAnyButtonChecked() const { - foreach (QPushButton* button, buttons_) { - if (button->isChecked()) - return true; - } - return false; -} - -void SlimButtonBox::SetCurrentButton(int index) { - for (int i=0 ; isetChecked(i == index); - } -}