mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-22 07:54:18 +01:00
Replace Nokia based FancyTabWidget with standard QTabWidget (#5956)
* Replace Nokia sidebar widget with QTabWidget The old sidebar widget was written by Nokia 10 years ago and was a hand made hardcoded mess of widgets trying to emulate a QTabWidget. This commit completely replaces it with a widget of the same name (FancyTabWidget) but is a much simpler subclass of the standard QTabWidget allowing for a 50% code reduction. There is still some manual draw code copied over to get the exact same look of the previous widget but this is not strictly necessary and can be later refactored with simpler drawControl code based on styling preferences. Benefits: - 50% code reduction - Easier to understand standard QTabWidget mechanics - Built-in support for re-arranging and closing tabs * Save and restore sidebar tab order Allow the user to rearrange the tab order by dragging tabs to a new location. Tab order is saved on exit and restored on start * Fix some code formatting issues
This commit is contained in:
parent
2e4a67b8da
commit
790fc2ff28
@ -255,37 +255,40 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
SLOT(AddToPlaylist(QMimeData*)));
|
||||
|
||||
// Add tabs to the fancy tab widget
|
||||
ui_->tabs->AddTab(global_search_view_,
|
||||
ui_->tabs->addTab(global_search_view_,
|
||||
IconLoader::Load("search", IconLoader::Base),
|
||||
tr("Search", "Global search settings dialog title."));
|
||||
ui_->tabs->AddTab(library_view_,
|
||||
ui_->tabs->addTab(library_view_,
|
||||
IconLoader::Load("folder-sound", IconLoader::Base),
|
||||
tr("Library"));
|
||||
ui_->tabs->AddTab(file_view_,
|
||||
ui_->tabs->addTab(file_view_,
|
||||
IconLoader::Load("document-open", IconLoader::Base),
|
||||
tr("Files"));
|
||||
ui_->tabs->AddTab(playlist_list_,
|
||||
ui_->tabs->addTab(playlist_list_,
|
||||
IconLoader::Load("view-media-playlist", IconLoader::Base),
|
||||
tr("Playlists"));
|
||||
ui_->tabs->AddTab(internet_view_,
|
||||
ui_->tabs->addTab(internet_view_,
|
||||
IconLoader::Load("applications-internet", IconLoader::Base),
|
||||
tr("Internet"));
|
||||
ui_->tabs->AddTab(
|
||||
ui_->tabs->addTab(
|
||||
device_view_container_,
|
||||
IconLoader::Load("multimedia-player-ipod-mini-blue", IconLoader::Base),
|
||||
tr("Devices"));
|
||||
ui_->tabs->AddSpacer();
|
||||
ui_->tabs->AddTab(song_info_view_,
|
||||
ui_->tabs->addSpacer();
|
||||
ui_->tabs->addTab(song_info_view_,
|
||||
IconLoader::Load("view-media-lyrics", IconLoader::Base),
|
||||
tr("Song info"));
|
||||
ui_->tabs->AddTab(artist_info_view_,
|
||||
ui_->tabs->addTab(artist_info_view_,
|
||||
IconLoader::Load("x-clementine-artist", IconLoader::Base),
|
||||
tr("Artist info"));
|
||||
|
||||
// Add the now playing widget to the fancy tab widget
|
||||
ui_->tabs->AddBottomWidget(ui_->now_playing);
|
||||
ui_->tabs->addBottomWidget(ui_->now_playing);
|
||||
|
||||
ui_->tabs->SetBackgroundPixmap(QPixmap(":/sidebar_background.png"));
|
||||
ui_->tabs->setBackgroundPixmap(QPixmap(":/sidebar_background.png"));
|
||||
|
||||
// Do this only after all default tabs have been added
|
||||
ui_->tabs->loadSettings(kSettingsGroup);
|
||||
|
||||
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
|
||||
connect(track_position_timer_, SIGNAL(timeout()),
|
||||
@ -979,7 +982,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
settings_.value("splitter_state").toByteArray())) {
|
||||
ui_->splitter->setSizes(QList<int>() << 300 << width() - 300);
|
||||
}
|
||||
ui_->tabs->SetCurrentIndex(
|
||||
ui_->tabs->setCurrentIndex(
|
||||
settings_.value("current_tab", 1 /* Library tab */).toInt());
|
||||
FancyTabWidget::Mode default_mode = FancyTabWidget::Mode_LargeSidebar;
|
||||
ui_->tabs->SetMode(
|
||||
@ -1265,8 +1268,10 @@ void MainWindow::SaveGeometry() {
|
||||
settings_.setValue("geometry", saveGeometry());
|
||||
}
|
||||
settings_.setValue("splitter_state", ui_->splitter->saveState());
|
||||
settings_.setValue("current_tab", ui_->tabs->current_index());
|
||||
settings_.setValue("current_tab", ui_->tabs->currentIndex());
|
||||
settings_.setValue("tab_mode", ui_->tabs->mode());
|
||||
|
||||
ui_->tabs->saveSettings(kSettingsGroup);
|
||||
}
|
||||
|
||||
void MainWindow::SavePlaybackStatus() {
|
||||
@ -2911,7 +2916,7 @@ void MainWindow::HandleNotificationPreview(OSD::Behaviour type, QString line1,
|
||||
|
||||
void MainWindow::ScrollToInternetIndex(const QModelIndex& index) {
|
||||
internet_view_->ScrollToIndex(index);
|
||||
ui_->tabs->SetCurrentWidget(internet_view_);
|
||||
ui_->tabs->setCurrentWidget(internet_view_);
|
||||
}
|
||||
|
||||
void MainWindow::AddPodcast() {
|
||||
@ -2919,11 +2924,11 @@ void MainWindow::AddPodcast() {
|
||||
}
|
||||
|
||||
void MainWindow::FocusLibraryTab() {
|
||||
ui_->tabs->SetCurrentWidget(library_view_);
|
||||
ui_->tabs->setCurrentWidget(library_view_);
|
||||
}
|
||||
|
||||
void MainWindow::FocusGlobalSearchField() {
|
||||
ui_->tabs->SetCurrentWidget(global_search_view_);
|
||||
ui_->tabs->setCurrentWidget(global_search_view_);
|
||||
global_search_view_->FocusSearchField();
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,233 +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.
|
||||
**
|
||||
**************************************************************************/
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2018, Vikram Ambrose <ambroseworks@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FANCYTABWIDGET_H
|
||||
#define FANCYTABWIDGET_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QProxyStyle>
|
||||
#include <QTabBar>
|
||||
#include <QTimer>
|
||||
#include <QTabWidget>
|
||||
#include <QWidget>
|
||||
|
||||
class QActionGroup;
|
||||
class QMenu;
|
||||
class QPainter;
|
||||
class QSignalMapper;
|
||||
class QStackedLayout;
|
||||
class QStatusBar;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
class FancyTabProxyStyle : public QProxyStyle {
|
||||
|
||||
class FancyTabWidget : public QTabWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void drawControl(ControlElement element, const QStyleOption* option,
|
||||
QPainter* painter, const QWidget* widget) const;
|
||||
void polish(QWidget* widget);
|
||||
void polish(QApplication* app);
|
||||
void polish(QPalette& palette);
|
||||
public:
|
||||
FancyTabWidget(QWidget* parent = 0);
|
||||
int addTab(QWidget * page, const QIcon & icon, const QString & label);
|
||||
int insertTab(int index, QWidget * page, const QIcon & icon, const QString & label);
|
||||
void addBottomWidget(QWidget* widget);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* o, QEvent* e);
|
||||
};
|
||||
void setBackgroundPixmap(const QPixmap& pixmap);
|
||||
void addSpacer();
|
||||
|
||||
class FancyTab : public QWidget {
|
||||
Q_OBJECT
|
||||
void loadSettings(const char *);
|
||||
void saveSettings(const char *);
|
||||
// Values are persisted - only add to the end
|
||||
enum Mode {
|
||||
Mode_None = 0,
|
||||
Mode_LargeSidebar,
|
||||
Mode_SmallSidebar,
|
||||
Mode_Tabs,
|
||||
Mode_IconOnlyTabs,
|
||||
Mode_PlainSidebar,
|
||||
};
|
||||
|
||||
Q_PROPERTY(float fader READ fader WRITE setFader)
|
||||
public:
|
||||
FancyTab(QWidget* tabbar);
|
||||
float fader() { return m_fader; }
|
||||
void setFader(float value);
|
||||
static const QSize TabSize_LargeSidebar;
|
||||
|
||||
QSize sizeHint() const;
|
||||
static const QSize IconSize_LargeSidebar;
|
||||
static const QSize IconSize_SmallSidebar;
|
||||
|
||||
void fadeIn();
|
||||
void fadeOut();
|
||||
Mode mode() { return mode_; }
|
||||
|
||||
QIcon icon;
|
||||
QString text;
|
||||
signals:
|
||||
void ModeChanged(FancyTabWidget::Mode mode);
|
||||
|
||||
protected:
|
||||
bool event(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
void leaveEvent(QEvent*);
|
||||
public slots:
|
||||
void setCurrentIndex(int index);
|
||||
void SetMode(Mode mode);
|
||||
// Mapper mapped signal needs this convenience function
|
||||
void SetMode(int mode) { SetMode(Mode(mode)); }
|
||||
|
||||
private:
|
||||
QPropertyAnimation animator;
|
||||
QWidget* tabbar;
|
||||
float m_fader;
|
||||
};
|
||||
private slots:
|
||||
void tabBarUpdateGeometry();
|
||||
void currentTabChanged(int);
|
||||
|
||||
class FancyTabBar : public QWidget {
|
||||
Q_OBJECT
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void contextMenuEvent(QContextMenuEvent* e);
|
||||
private:
|
||||
void addMenuItem(QSignalMapper* mapper, QActionGroup* group,
|
||||
const QString& text, Mode mode);
|
||||
|
||||
public:
|
||||
FancyTabBar(QWidget* parent = nullptr);
|
||||
~FancyTabBar();
|
||||
QPixmap background_pixmap_;
|
||||
QMenu* menu_;
|
||||
Mode mode_;
|
||||
QWidget *bottom_widget_;
|
||||
|
||||
void paintEvent(QPaintEvent* event);
|
||||
void paintTab(QPainter* painter, int tabIndex) const;
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
bool validIndex(int index) const {
|
||||
return index >= 0 && index < m_tabs.count();
|
||||
}
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
|
||||
void addTab(const QIcon& icon, const QString& label);
|
||||
void addSpacer(int size = 40);
|
||||
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, const QString& toolTip);
|
||||
QString tabToolTip(int index) const;
|
||||
|
||||
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;
|
||||
int m_currentIndex;
|
||||
QList<FancyTab*> m_tabs;
|
||||
QTimer m_triggerTimer;
|
||||
QSize tabSizeHint(bool minimum = false) const;
|
||||
};
|
||||
|
||||
class FancyTabWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FancyTabWidget(QWidget* parent = nullptr);
|
||||
|
||||
// Values are persisted - only add to the end
|
||||
enum Mode {
|
||||
Mode_None = 0,
|
||||
Mode_LargeSidebar = 1,
|
||||
Mode_SmallSidebar = 2,
|
||||
Mode_Tabs = 3,
|
||||
Mode_IconOnlyTabs = 4,
|
||||
Mode_PlainSidebar = 5,
|
||||
};
|
||||
|
||||
struct Item {
|
||||
Item(const QIcon& icon, const QString& label)
|
||||
: type_(Type_Tab),
|
||||
tab_label_(label),
|
||||
tab_icon_(icon),
|
||||
spacer_size_(0) {}
|
||||
Item(int size) : type_(Type_Spacer), spacer_size_(size) {}
|
||||
|
||||
enum Type { Type_Tab, Type_Spacer, };
|
||||
|
||||
Type type_;
|
||||
QString tab_label_;
|
||||
QIcon tab_icon_;
|
||||
int spacer_size_;
|
||||
};
|
||||
|
||||
void AddTab(QWidget* tab, const QIcon& icon, const QString& label);
|
||||
void AddSpacer(int size = 40);
|
||||
void SetBackgroundPixmap(const QPixmap& pixmap);
|
||||
|
||||
void AddBottomWidget(QWidget* widget);
|
||||
|
||||
int current_index() const;
|
||||
Mode mode() const { return mode_; }
|
||||
|
||||
public slots:
|
||||
void SetCurrentIndex(int index);
|
||||
void SetCurrentWidget(QWidget* widget);
|
||||
void SetMode(Mode mode);
|
||||
void SetMode(int mode) { SetMode(Mode(mode)); }
|
||||
|
||||
signals:
|
||||
void CurrentChanged(int index);
|
||||
void ModeChanged(FancyTabWidget::Mode mode);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event);
|
||||
void contextMenuEvent(QContextMenuEvent* e);
|
||||
|
||||
private slots:
|
||||
void ShowWidget(int index);
|
||||
|
||||
private:
|
||||
void MakeTabBar(QTabBar::Shape shape, bool text, bool icons, bool fancy);
|
||||
void AddMenuItem(QSignalMapper* mapper, QActionGroup* group,
|
||||
const QString& text, Mode mode);
|
||||
|
||||
Mode mode_;
|
||||
QList<Item> items_;
|
||||
|
||||
QWidget* tab_bar_;
|
||||
QStackedLayout* stack_;
|
||||
QPixmap background_pixmap_;
|
||||
QWidget* side_widget_;
|
||||
QVBoxLayout* side_layout_;
|
||||
QVBoxLayout* top_layout_;
|
||||
|
||||
bool use_background_;
|
||||
|
||||
QMenu* menu_;
|
||||
|
||||
std::unique_ptr<FancyTabProxyStyle> proxy_style_;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Core
|
||||
|
||||
Q_DECLARE_METATYPE(QPropertyAnimation*);
|
||||
|
||||
using Core::Internal::FancyTab;
|
||||
using Core::Internal::FancyTabBar;
|
||||
using Core::Internal::FancyTabWidget;
|
||||
|
||||
#endif // FANCYTABWIDGET_H
|
||||
|
Loading…
Reference in New Issue
Block a user