From 53772c052ba8d0de1bb82b22249895e4737cfdf6 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Wed, 31 May 2017 16:19:58 +0200 Subject: [PATCH] Allow WidgetTab to use artwork tabs (@StCyr) (#3569) * First version of artwork tabs for the InstrumentTrackWindow. This version can only display & manage artwork tabs, which breaks the InstrumentSoundShapingView as it still uses text tabs. I'm planing to improve this implementation to let these artwork tabs fall back to text mode when no artwork is given. This would solve the problem of the InstrumentSoundShapingView. * Second version of artwork tabs for the InstrumentTrackWindow. This version will draw an artwork tab when the TabWidget::addTab function is given a pixmapName. Otherwise, when pixmapName is NULL, it will fall back drawing a text tab. * Created artwork for the artwork tabs. * 1st PoC for autosizeable artwork tabs. * TabWidget is 20 pixels tall when it's going to display artwork tabs. * Added tooltip support for the TabWidget class. Atm, tooltips are simply tabs' name. * Imported artworks from RebeccaDeField * Reverted to 12px tall TabWidget * Fine tuning for the positioning of artwork tabs: Take into account the caption 'space. * New artwork for the ENV/LFO tab (has now an ADSR-based look) * 1) Tabs in TabWidget class have now a "tooltip" attribute. So that they can now show more meaningfull information then simply the tab's name. 2) Fixed the compilation problem with QT5 * Fine tuning the positioning of highlighted artwork tabs. * Fixed an issue in TabWidget's artwork tabs autosize function that makes gdb crash with SIGFPE. * TabWidget is 17 pixels tall when it's going to display artwork tabs. * Removed underscore prefix for function parameters as coding convention has changed. (Request at https://github.com/LMMS/lmms/pull/2599/files/dccf9f411996c8c866ff1086b65f15020ef08cd9#r61165005) Cyrille * Removed background gradient for TabWidget as LMMS is going to a more flat design. Cyrille * Increased the graphical TabWidget's height by 2 pixels for eye-candy. The InstrumentTrackWindow's height has been increased by the same amount. Cyrille * Removed gradient in GrouBox widgets as LMMS is going for a more flattened design. Cyrille * Made the background of TabWidget themeable Cyrille * The highlighting color for a TabWidget'selected tab is now themeable. * Made TabWidget's Title text and tab text themeable. * Added a darker background to the TabWidget's tab bar. * Further flatened the design of TabWidget * Flatened the design of the GroupBox widget * Fine tuning the placement of TabWidgets' highlighting background + some code cleaning in TabWidgets * Made the TabWidget's title background and borders themeable * TabWidget - Artwork tabs: Do not change the icon color when it is highlighted * TabWidget: Made the artworks' color themeable * Adapted format to follow LMMS coding conventions * Some more blank spaces to tabs translation to comply with LMMS coding standards. * Some more blank spaces to tabs translation to comply with LMMS coding standards. * Revert "TabWidget: Made the artworks' color themeable" This reverts commit 5b162c07e2ee26796b6e9408364eba19142acd71. Conflicts: src/gui/widgets/TabWidget.cpp Reason: Artwork's color themeability had the side-effect that it removed the artworks' alpha channel, thus making them ugly. * Made GroupBox's background color themeable * Update background color, only use one set of images * Use name as tooltip, more descriptive names * Update icons and colors * more things * formatting fixes * Remove update() from constructor --- data/themes/default/env_lfo_tab.png | Bin 0 -> 255 bytes data/themes/default/func_tab.png | Bin 0 -> 179 bytes data/themes/default/fx_tab.png | Bin 0 -> 292 bytes data/themes/default/midi_tab.png | Bin 0 -> 170 bytes data/themes/default/misc_tab.png | Bin 0 -> 188 bytes data/themes/default/plugin_tab.png | Bin 0 -> 210 bytes data/themes/default/style.css | 13 + include/GroupBox.h | 2 +- include/TabWidget.h | 50 ++- src/gui/widgets/EffectRackView.cpp | 2 +- src/gui/widgets/GroupBox.cpp | 54 +--- .../widgets/InstrumentSoundShapingView.cpp | 3 +- src/gui/widgets/TabWidget.cpp | 296 +++++++++++++----- src/tracks/InstrumentTrack.cpp | 16 +- 14 files changed, 287 insertions(+), 149 deletions(-) create mode 100644 data/themes/default/env_lfo_tab.png create mode 100644 data/themes/default/func_tab.png create mode 100644 data/themes/default/fx_tab.png create mode 100644 data/themes/default/midi_tab.png create mode 100644 data/themes/default/misc_tab.png create mode 100644 data/themes/default/plugin_tab.png diff --git a/data/themes/default/env_lfo_tab.png b/data/themes/default/env_lfo_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..8916ea44a1af88f64c10fa6052ac9ae3dfa43e6e GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt(m4E{-7@ z6PNa#=5=roalP+jvVc=iDxg7Xi^9czttkr_c{?%=T#8C6%yBdNICDm!d4BQv-R@8P z8`MPZG#at6L^P_fu*_(*U}1UDctSkpOm6K#rW+OhWk$E^7EFmdKI;Vst0D8DqVE_OC literal 0 HcmV?d00001 diff --git a/data/themes/default/func_tab.png b/data/themes/default/func_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..8776571cd21de849fb239deaf33ed4cfacc65505 GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt%?gE{-7@ z6O$7bm?s=j{rLa?|Mfpii~{fLZeh}>Q+cBA=H`|sQLXWFqDZ}Bv*HtXhPl(Y|0I97 RxE`pN!PC{xWt~$(697a{HYET6 literal 0 HcmV?d00001 diff --git a/data/themes/default/fx_tab.png b/data/themes/default/fx_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..58fbcb9bd5968c506db94da0957948a02a5f001c GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt&5ZT^vI+ zCLW!1miLeWPwW163o$W=r#%m5#0m(dTM64MZ}8ggpu@o2;w)RRIP4*de^<)>Bj>88 zJ=E`DHrThdL^kC$HP(j&)CT3XaS zz4)$avGXH!*8asWL{A;O*xSwje!FLu))}3Unl|MGPxCqMp0DI)Fo#=~}U&Kt<}FE{-7@ z6O$7bu>5If3OX|5#MYb;<&9E_j=eIxH;$}GfBfK@hZzHd1)uu+N!yrL0<|!By85}S Ib4q9e03mZQXaE2J literal 0 HcmV?d00001 diff --git a/data/themes/default/misc_tab.png b/data/themes/default/misc_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..efb0d8f411da0b4502e4692382ca80270cab3a1f GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8!3Q zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-0GE{-7@ z6W^Xv~}U&Kt=wZE{-7@ z6VFcYs~LXFM5P^t%AjNr)4Ir`<#NN6{^a1?=^YsHAy9^qMFNdTd_s9 xjnJ!YTn#4NdDc-HyXJ466l)uGQ`K%ELyG?nyE_LKmIIAu@O1TaS?83{1ONdYJs|)9 literal 0 HcmV?d00001 diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 035ed7a5f..a4fd6abd9 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -136,6 +136,19 @@ PianoRoll { qproperty-textShadow: #fff; } +TabWidget { + background-color: #262b30; + qproperty-tabText: rgba(255, 255, 255, 180); + qproperty-tabTitleText: #fff; + qproperty-tabSelected: #323940; + qproperty-tabBackground: #181b1f; + qproperty-tabBorder: #181b1f; +} + +GroupBox { + background-color: #262b30; +} + /* main toolbar oscilloscope - can have transparent bg now */ VisualizationWidget { diff --git a/include/GroupBox.h b/include/GroupBox.h index 6b4a1e98b..39d9a522a 100644 --- a/include/GroupBox.h +++ b/include/GroupBox.h @@ -57,7 +57,7 @@ public: protected: virtual void mousePressEvent( QMouseEvent * _me ); - virtual void resizeEvent( QResizeEvent * _re ); + virtual void paintEvent( QPaintEvent * _pe ); private: diff --git a/include/TabWidget.h b/include/TabWidget.h index f4888f0cc..402d7c9cc 100644 --- a/include/TabWidget.h +++ b/include/TabWidget.h @@ -29,25 +29,47 @@ #include #include +const int TEXT_TAB_HEIGHT = 14; +const int GRAPHIC_TAB_HEIGHT = 17; class TabWidget : public QWidget { Q_OBJECT public: - TabWidget( const QString & _caption, QWidget * _parent ); + TabWidget( const QString & _caption, QWidget * _parent, bool usePixmap = false ); virtual ~TabWidget(); - void addTab( QWidget * _w, const QString & _name, int _idx = -1 ); + void addTab( QWidget * w, const QString & name, const char *pixmap = NULL, int idx = -1 ); - void setActiveTab( int _idx ); + void setActiveTab( int idx ); + + int findTabAtPos( const QPoint *pos ); inline int activeTab() const { return( m_activeTab ); } + // Themeability + Q_PROPERTY( QColor tabText READ tabText WRITE setTabText) + Q_PROPERTY( QColor tabTitleText READ tabTitleText WRITE setTabTitleText) + Q_PROPERTY( QColor tabSelected READ tabSelected WRITE setTabSelected) + Q_PROPERTY( QColor tabBackground READ tabBackground WRITE setTabBackground) + Q_PROPERTY( QColor tabBorder READ tabBorder WRITE setTabBorder) + + QColor tabText() const; + void setTabText( const QColor & c ); + QColor tabTitleText() const; + void setTabTitleText( const QColor & c ); + QColor tabSelected() const; + void setTabSelected( const QColor & c ); + QColor tabBackground() const; + void setTabBackground( const QColor & c ); + QColor tabBorder() const; + void setTabBorder( const QColor & c ); protected: + virtual bool event( QEvent * event ); virtual void mousePressEvent( QMouseEvent * _me ); virtual void paintEvent( QPaintEvent * _pe ); virtual void resizeEvent( QResizeEvent * _re ); @@ -57,16 +79,26 @@ protected: private: struct widgetDesc { - QWidget * w; // ptr to widget - QString name; // name for widget - int nwidth; // width of name when painting + QWidget * w; // ptr to widget + const char * pixmap; // artwork for the widget + QString name; // name for widget + int nwidth; // width of name when painting (only valid for text tab) } ; typedef QMap widgetStack; widgetStack m_widgets; - int m_activeTab; - QString m_caption; - quint8 m_tabheight; + + int m_activeTab; + QString m_caption; // Tab caption, used as the tooltip text on icon tabs + quint8 m_tabbarHeight; // The height of the tab bar + quint8 m_tabheight; // The height of the tabs + bool m_usePixmap; // true if the tabs are to be displayed with icons. False for text tabs. + + QColor m_tabText; // The color of the tabs' text. + QColor m_tabTitleText; // The color of the TabWidget's title text. + QColor m_tabSelected; // The highlighting color for the selected tab. + QColor m_tabBackground; // The TabWidget's background color. + QColor m_tabBorder; // The TabWidget's borders color. } ; #endif diff --git a/src/gui/widgets/EffectRackView.cpp b/src/gui/widgets/EffectRackView.cpp index 2fa25d575..b3f468d0e 100644 --- a/src/gui/widgets/EffectRackView.cpp +++ b/src/gui/widgets/EffectRackView.cpp @@ -39,7 +39,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) : ModelView( NULL, this ) { QVBoxLayout* mainLayout = new QVBoxLayout( this ); - mainLayout->setMargin( 0 ); + mainLayout->setMargin( 5 ); m_effectsGroupBox = new GroupBox( tr( "EFFECTS CHAIN" ) ); mainLayout->addWidget( m_effectsGroupBox ); diff --git a/src/gui/widgets/GroupBox.cpp b/src/gui/widgets/GroupBox.cpp index fbcf88ed7..158390bb5 100644 --- a/src/gui/widgets/GroupBox.cpp +++ b/src/gui/widgets/GroupBox.cpp @@ -41,8 +41,6 @@ GroupBox::GroupBox( const QString & _caption, QWidget * _parent ) : m_caption( _caption ), m_titleBarHeight( 11 ) { - updatePixmap(); - m_led = new PixmapButton( this, _caption ); m_led->setCheckable( true ); m_led->move( 3, 0 ); @@ -84,60 +82,22 @@ void GroupBox::mousePressEvent( QMouseEvent * _me ) -void GroupBox::resizeEvent( QResizeEvent * _ev ) +void GroupBox::paintEvent( QPaintEvent * pe ) { - updatePixmap(); - QWidget::resizeEvent( _ev ); -} + QPainter p( this ); - - -void GroupBox::updatePixmap() -{ - QColor bg_color = QApplication::palette().color( QPalette::Active, - QPalette::Background ); - QPixmap pm( size() ); - pm.fill( bg_color/*.dark( 132 )*/ ); - - QPainter p( &pm ); + // Draw background + p.fillRect( 0, 0, width() - 1, height() - 1, p.background() ); // outer rect - p.setPen( bg_color.dark( 150 ) ); + p.setPen( p.background().color().dark( 150 ) ); p.drawRect( 0, 0, width() - 1, height() - 1 ); - // brighter line at bottom/right - p.setPen( bg_color.light( 150 ) ); - p.drawLine( width() - 1, 0, width() - 1, height() - 1 ); - p.drawLine( 0, height() - 1, width() - 1, height() - 1 ); - - // draw groupbox-titlebar - QLinearGradient g( 0, 0, 0, m_titleBarHeight ); - g.setColorAt( 0, bg_color.darker( 250 ) ); - g.setColorAt( 0.1, bg_color.lighter( 120 ) ); - g.setColorAt( 1, bg_color.darker( 250 ) ); - p.fillRect( 2, 2, width() - 4, m_titleBarHeight, g ); - // draw line below titlebar - p.setPen( bg_color.dark( 400 ) ); - p.drawLine( 1, m_titleBarHeight + 1, width() - 3, m_titleBarHeight + 1 ); + p.fillRect( 1, 1, width() - 2, m_titleBarHeight + 1, p.background().color().darker( 150 ) ); - // black inner rect - p.drawRect( 1, 1, width() - 3, height() - 3 ); - - - //p.setPen( QColor( 255, 255, 255 ) ); + // draw text p.setPen( palette().color( QPalette::Active, QPalette::Text ) ); p.setFont( pointSize<8>( font() ) ); p.drawText( 22, m_titleBarHeight, m_caption ); - - QPalette pal = palette(); - pal.setBrush( backgroundRole(), QBrush( pm ) ); - setPalette( pal ); } - - - - - - - diff --git a/src/gui/widgets/InstrumentSoundShapingView.cpp b/src/gui/widgets/InstrumentSoundShapingView.cpp index 20eaaba5e..aa64b5596 100644 --- a/src/gui/widgets/InstrumentSoundShapingView.cpp +++ b/src/gui/widgets/InstrumentSoundShapingView.cpp @@ -76,7 +76,8 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : { m_envLfoViews[i] = new EnvelopeAndLfoView( m_targetsTabWidget ); m_targetsTabWidget->addTab( m_envLfoViews[i], - tr( InstrumentSoundShaping::targetNames[i][0].toUtf8().constData() ) ); + tr( InstrumentSoundShaping::targetNames[i][0].toUtf8().constData() ), + NULL ); } diff --git a/src/gui/widgets/TabWidget.cpp b/src/gui/widgets/TabWidget.cpp index 8048ecc0e..6fde217c1 100644 --- a/src/gui/widgets/TabWidget.cpp +++ b/src/gui/widgets/TabWidget.cpp @@ -2,7 +2,7 @@ * TabWidget.cpp - tabwidget for LMMS * * Copyright (c) 2005-2014 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -27,53 +27,71 @@ #include #include +#include +#include +#include #include "gui_templates.h" +#include "embed.h" - - -TabWidget::TabWidget( const QString & _caption, QWidget * _parent ) : - QWidget( _parent ), +TabWidget::TabWidget( const QString & caption, QWidget * parent, bool usePixmap ) : + QWidget( parent ), m_activeTab( 0 ), - m_caption( _caption ), - m_tabheight( _caption.isEmpty() ? 11: 10 ) + m_caption( caption ), + m_usePixmap( usePixmap ), + m_tabText( 0, 0, 0 ), + m_tabTitleText( 0, 0, 0 ), + m_tabSelected( 0, 0, 0 ), + m_tabBackground( 0, 0, 0 ), + m_tabBorder( 0, 0, 0 ) { + + // Create taller tabbar when it's to display artwork tabs + m_tabbarHeight = usePixmap ? GRAPHIC_TAB_HEIGHT : TEXT_TAB_HEIGHT; + + m_tabheight = caption.isEmpty() ? m_tabbarHeight - 3 : m_tabbarHeight - 4; + setFont( pointSize<8>( font() ) ); setAutoFillBackground( true ); - QColor bg_color = QApplication::palette().color( QPalette::Active, - QPalette::Background ). - darker( 132 ); + QColor bg_color = QApplication::palette().color( QPalette::Active, QPalette::Background ). darker( 132 ); QPalette pal = palette(); pal.setColor( QPalette::Background, bg_color ); setPalette( pal ); + } - - TabWidget::~TabWidget() { } - - -void TabWidget::addTab( QWidget * _w, const QString & _name, int _idx ) +void TabWidget::addTab( QWidget * w, const QString & name, const char *pixmap, int idx ) { setFont( pointSize<8>( font() ) ); - widgetDesc d = { _w, _name, fontMetrics().width( _name ) + 10 } ; - if( _idx < 0/* || m_widgets.contains( _idx ) == true*/ ) + + // Append tab when position is not given + if( idx < 0/* || m_widgets.contains( idx ) == true*/ ) { - while( m_widgets.contains( ++_idx ) == true ) + while( m_widgets.contains( ++idx ) == true ) { } } - m_widgets[_idx] = d; - _w->setFixedSize( width() - 4, height() - 14 ); - _w->move( 2, 13 ); - _w->hide(); + // Tab's width when it is a text tab. This isn't correct for artwork tabs, but it's fixed later during the PaintEvent + int tab_width = fontMetrics().width( name ) + 10; + + // Register new tab + widgetDesc d = { w, pixmap, name, tab_width }; + m_widgets[idx] = d; + + // Position tab's window + w->setFixedSize( width() - 4, height() - m_tabbarHeight ); + w->move( 2, m_tabbarHeight - 1 ); + w->hide(); + + // Show tab's window if it's active if( m_widgets.contains( m_activeTab ) ) { // make sure new tab doesn't overlap current widget @@ -85,15 +103,15 @@ void TabWidget::addTab( QWidget * _w, const QString & _name, int _idx ) -void TabWidget::setActiveTab( int _idx ) +void TabWidget::setActiveTab( int idx ) { - if( m_widgets.contains( _idx ) ) + if( m_widgets.contains( idx ) ) { int old_active = m_activeTab; - m_activeTab = _idx; + m_activeTab = idx; m_widgets[m_activeTab].w->raise(); m_widgets[m_activeTab].w->show(); - if( old_active != _idx && m_widgets.contains( old_active ) ) + if( old_active != idx && m_widgets.contains( old_active ) ) { m_widgets[old_active].w->hide(); } @@ -102,27 +120,74 @@ void TabWidget::setActiveTab( int _idx ) } - - -void TabWidget::mousePressEvent( QMouseEvent * _me ) +// Return the index of the tab at position "pos" +int TabWidget::findTabAtPos( const QPoint *pos ) { - if( _me->y() > 1 && _me->y() < 13 ) + + if( pos->y() > 1 && pos->y() < m_tabbarHeight - 1 ) { - int cx = ( ( m_caption == "" ) ? 4 : 14 ) + - fontMetrics().width( m_caption ); - for( widgetStack::iterator it = m_widgets.begin(); - it != m_widgets.end(); ++it ) + int cx = ( ( m_caption == "" ) ? 4 : 14 ) + fontMetrics().width( m_caption ); + + for( widgetStack::iterator it = m_widgets.begin(); it != m_widgets.end(); ++it ) { - if( _me->x() >= cx && - _me->x() <= cx + ( *it ).nwidth ) + if( pos->x() >= cx && pos->x() <= cx + ( *it ).nwidth ) { - setActiveTab( it.key() ); - update(); - return; + return( it.key() ); } cx += ( *it ).nwidth; } } + + // Haven't found any tab at position "pos" + return( -1 ); +} + + +// Overload the QWidget::event handler to display tooltips (from https://doc.qt.io/qt-4.8/qt-widgets-tooltips-example.html) +bool TabWidget::event(QEvent *event) +{ + + if ( event->type() == QEvent::ToolTip ) + { + QHelpEvent *helpEvent = static_cast(event); + + int idx = findTabAtPos( & helpEvent->pos() ); + + if ( idx != -1 ) + { + // Display tab's tooltip + QToolTip::showText( helpEvent->globalPos(), m_widgets[idx].name ); + } + else + { + // The tooltip event doesn't relate to any tab, let's ignore it + QToolTip::hideText(); + event->ignore(); + } + + return true; + } + + // not a Tooltip event, let's propagate it to the other event handlers + return QWidget::event(event); +} + + +// Activate tab when clicked +void TabWidget::mousePressEvent( QMouseEvent * me ) +{ + + // Find index of tab that has been clicked + QPoint pos = me->pos(); + int idx = findTabAtPos( &pos ); + + // When found, activate tab that has been clicked + if ( idx != -1 ) + { + setActiveTab( idx ); + update(); + return; + } } @@ -133,7 +198,7 @@ void TabWidget::resizeEvent( QResizeEvent * ) for( widgetStack::iterator it = m_widgets.begin(); it != m_widgets.end(); ++it ) { - ( *it ).w->setFixedSize( width() - 4, height() - 14 ); + ( *it ).w->setFixedSize( width() - 4, height() - m_tabbarHeight ); } } @@ -141,66 +206,77 @@ void TabWidget::resizeEvent( QResizeEvent * ) -void TabWidget::paintEvent( QPaintEvent * _pe ) +void TabWidget::paintEvent( QPaintEvent * pe ) { - setFont( pointSize<8>( font() ) ); QPainter p( this ); + p.setFont( pointSize<7>( font() ) ); - QColor bg_color = QApplication::palette().color( QPalette::Active, - QPalette::Background ); - QLinearGradient g( 0, 0, 0, m_tabheight ); - g.setColorAt( 0, bg_color.darker( 250 ) ); - g.setColorAt( 0.1, bg_color.lighter( 120 ) ); - g.setColorAt( 1, bg_color.darker( 250 ) ); + // Draw background + QBrush bg_color = p.background(); p.fillRect( 0, 0, width() - 1, height() - 1, bg_color ); - bool big_tab_captions = ( m_caption == "" ); - - p.setPen( bg_color.darker( 150 ) ); + // Draw external borders + p.setPen( tabBorder() ); p.drawRect( 0, 0, width() - 1, height() - 1 ); - p.setPen( bg_color.light( 150 ) ); - p.drawLine( width() - 1, 0, width() - 1, height() - 1 ); - p.drawLine( 0, height() - 1, width() - 1, height() - 1 ); - - p.setPen( QColor( 0, 0, 0 ) ); - p.drawRect( 1, 1, width() - 3, height() - 3 ); - - p.fillRect( 2, 2, width() - 4, m_tabheight, g ); - p.drawLine( 2, m_tabheight + 2, width() - 3, m_tabheight + 2); + // Draw tabs' bar background + p.fillRect( 1, 1, width() - 2, m_tabheight + 2, tabBackground() ); + // Draw title, if any if( ! m_caption.isEmpty() ) { - p.setPen( QColor( 255, 255, 255 ) ); + p.setFont( pointSize<8>( p.font() ) ); + p.setPen( tabTitleText() ); p.drawText( 5, 11, m_caption ); } // Calculate the tabs' x (tabs are painted next to the caption) int tab_x_offset = m_caption.isEmpty() ? 4 : 14 + fontMetrics().width( m_caption ); - QColor cap_col( 160, 160, 160 ); - if( big_tab_captions ) + // Compute tabs' width depending on the number of tabs (only applicable for artwork tabs) + widgetStack::iterator first = m_widgets.begin(); + widgetStack::iterator last = m_widgets.end(); + int tab_width = width(); + if ( first != last ) { - p.setFont( pointSize<8>( p.font() ) ); - cap_col = QColor( 224, 224, 224 ); + tab_width = ( width() - tab_x_offset ) / std::distance( first, last ); } - else - { - p.setFont( pointSize<7>( p.font() ) ); - } - p.setPen( cap_col ); - - for( widgetStack::iterator it = m_widgets.begin(); - it != m_widgets.end(); ++it ) + // Draw all tabs + p.setPen( tabText() ); + for( widgetStack::iterator it = first ; it != last ; ++it ) { - if( it.key() == m_activeTab ) + // Draw a text tab or a artwork tab. + if( m_usePixmap ) { - p.setPen( QColor( 32, 48, 64 ) ); - p.fillRect( tab_x_offset, 2, ( *it ).nwidth - 6, 10, cap_col ); + // Fixes tab's width, because original size is only correct for text tabs + ( *it ).nwidth = tab_width; + + // Get artwork + QPixmap artwork( embed::getIconPixmap( ( *it ).pixmap ) ); + + // Highlight active tab + if( it.key() == m_activeTab ) + { + p.fillRect( tab_x_offset, 0, ( *it ).nwidth, m_tabbarHeight - 1, tabSelected() ); + } + + // Draw artwork + p.drawPixmap(tab_x_offset + ( ( *it ).nwidth - artwork.width() ) / 2, 1, artwork ); } - p.drawText( tab_x_offset + 3, m_tabheight, ( *it ).name ); - p.setPen( cap_col ); + else + { + // Highlight tab when active + if( it.key() == m_activeTab ) + { + p.fillRect( tab_x_offset, 2, ( *it ).nwidth - 6, m_tabbarHeight - 4, tabSelected() ); + } + + // Draw text + p.drawText( tab_x_offset + 3, m_tabheight + 1, ( *it ).name ); + } + + // Next tab's horizontal position tab_x_offset += ( *it ).nwidth; } } @@ -208,13 +284,16 @@ void TabWidget::paintEvent( QPaintEvent * _pe ) -void TabWidget::wheelEvent( QWheelEvent * _we ) +// Switch between tabs with mouse wheel +void TabWidget::wheelEvent( QWheelEvent * we ) { - if (_we->y() > m_tabheight) + if( we->y() > m_tabheight ) + { return; + } - _we->accept(); - int dir = ( _we->delta() < 0 ) ? 1 : -1; + we->accept(); + int dir = ( we->delta() < 0 ) ? 1 : -1; int tab = m_activeTab; while( tab > -1 && static_cast( tab ) < m_widgets.count() ) { @@ -227,9 +306,62 @@ void TabWidget::wheelEvent( QWheelEvent * _we ) setActiveTab( tab ); } +// Return the color to be used to draw a TabWidget's title text (if any) +QColor TabWidget::tabTitleText() const +{ + return m_tabTitleText; +} +// Set the color to be used to draw a TabWidget's title text (if any) +void TabWidget::setTabTitleText( const QColor & c ) +{ + m_tabTitleText = c; +} +// Return the color to be used to draw a TabWidget's text (if any) +QColor TabWidget::tabText() const +{ + return m_tabText; +} +// Set the color to be used to draw a TabWidget's text (if any) +void TabWidget::setTabText( const QColor & c ) +{ + m_tabText = c; +} +// Return the color to be used to highlight a TabWidget'selected tab (if any) +QColor TabWidget::tabSelected() const +{ + return m_tabSelected; +} +// Set the color to be used to highlight a TabWidget'selected tab (if any) +void TabWidget::setTabSelected( const QColor & c ) +{ + m_tabSelected = c; +} +// Return the color to be used for the TabWidget's background +QColor TabWidget::tabBackground() const +{ + return m_tabBackground; +} + +// Set the color to be used for the TabWidget's background +void TabWidget::setTabBackground( const QColor & c ) +{ + m_tabBackground = c; +} + +// Return the color to be used for the TabWidget's borders +QColor TabWidget::tabBorder() const +{ + return m_tabBorder; +} + +// Set the color to be used for the TabWidget's borders +void TabWidget::setTabBorder( const QColor & c ) +{ + m_tabBorder = c; +} diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 80b5427b1..b847c85e6 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1411,8 +1411,8 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : generalSettingsLayout->addLayout( basicControlsLayout ); - m_tabWidget = new TabWidget( "", this ); - m_tabWidget->setFixedHeight( INSTRUMENT_HEIGHT + 10 ); + m_tabWidget = new TabWidget( "", this, true ); + m_tabWidget->setFixedHeight( INSTRUMENT_HEIGHT + GRAPHIC_TAB_HEIGHT - 4 ); // create tab-widgets @@ -1439,11 +1439,11 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : m_miscView = new InstrumentMiscView( m_track, m_tabWidget ); - m_tabWidget->addTab( m_ssView, tr( "ENV/LFO" ), 1 ); - m_tabWidget->addTab( instrumentFunctions, tr( "FUNC" ), 2 ); - m_tabWidget->addTab( m_effectView, tr( "FX" ), 3 ); - m_tabWidget->addTab( m_midiView, tr( "MIDI" ), 4 ); - m_tabWidget->addTab( m_miscView, tr( "MISC" ), 5 ); + m_tabWidget->addTab( m_ssView, tr( "Envelope, filter & LFO" ), "env_lfo_tab", 1 ); + m_tabWidget->addTab( instrumentFunctions, tr( "Chord stacking & arpeggio" ), "func_tab", 2 ); + m_tabWidget->addTab( m_effectView, tr( "Effects" ), "fx_tab", 3 ); + m_tabWidget->addTab( m_midiView, tr( "MIDI settings" ), "midi_tab", 4 ); + m_tabWidget->addTab( m_miscView, tr( "Miscellaneous" ), "misc_tab", 5 ); // setup piano-widget m_pianoView = new PianoView( this ); @@ -1617,7 +1617,7 @@ void InstrumentTrackWindow::updateInstrumentView() if( m_track->m_instrument != NULL ) { m_instrumentView = m_track->m_instrument->createView( m_tabWidget ); - m_tabWidget->addTab( m_instrumentView, tr( "PLUGIN" ), 0 ); + m_tabWidget->addTab( m_instrumentView, tr( "Plugin" ), "plugin_tab", 0 ); m_tabWidget->setActiveTab( 0 ); m_ssView->setFunctionsHidden( m_track->m_instrument->flags().testFlag( Instrument::IsSingleStreamed ) );