mirror of
https://github.com/LMMS/lmms.git
synced 2026-03-03 21:56:45 -05:00
Co-authored-by: allejok96 <allejok96@gmail.com> Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
421 lines
9.6 KiB
C++
421 lines
9.6 KiB
C++
/*
|
|
* TabWidget.cpp - tabwidget for LMMS
|
|
*
|
|
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
|
*
|
|
* This file is part of LMMS - https://lmms.io
|
|
*
|
|
* This program 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 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This program 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 this program (see COPYING); if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "TabWidget.h"
|
|
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QPixmap>
|
|
#include <QToolTip>
|
|
#include <QWheelEvent>
|
|
|
|
#include "DeprecationHelper.h"
|
|
#include "embed.h"
|
|
#include "gui_templates.h"
|
|
|
|
namespace lmms::gui
|
|
{
|
|
|
|
TabWidget::TabWidget(const QString & caption, QWidget * parent, bool usePixmap,
|
|
bool resizable) :
|
|
QWidget( parent ),
|
|
m_resizable( resizable ),
|
|
m_activeTab( 0 ),
|
|
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 );
|
|
QPalette pal = palette();
|
|
pal.setColor( QPalette::Background, bg_color );
|
|
setPalette( pal );
|
|
|
|
}
|
|
|
|
void TabWidget::addTab( QWidget * w, const QString & name, const char *pixmap, int idx )
|
|
{
|
|
setFont( pointSize<8>( font() ) );
|
|
|
|
// Append tab when position is not given
|
|
if( idx < 0/* || m_widgets.contains( idx ) == true*/ )
|
|
{
|
|
while( m_widgets.contains( ++idx ) == true )
|
|
{
|
|
}
|
|
}
|
|
|
|
// 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 = horizontalAdvance(fontMetrics(), name) + 10;
|
|
|
|
// Register new tab
|
|
widgetDesc d = { w, pixmap, name, tab_width };
|
|
m_widgets[idx] = d;
|
|
|
|
// Position tab's window
|
|
if (!m_resizable)
|
|
{
|
|
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
|
|
m_widgets[m_activeTab].w->show();
|
|
m_widgets[m_activeTab].w->raise();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void TabWidget::setActiveTab( int idx )
|
|
{
|
|
if( m_widgets.contains( idx ) )
|
|
{
|
|
int old_active = m_activeTab;
|
|
m_activeTab = idx;
|
|
m_widgets[m_activeTab].w->raise();
|
|
m_widgets[m_activeTab].w->show();
|
|
if( old_active != idx && m_widgets.contains( old_active ) )
|
|
{
|
|
m_widgets[old_active].w->hide();
|
|
}
|
|
update();
|
|
}
|
|
}
|
|
|
|
|
|
// Return the index of the tab at position "pos"
|
|
int TabWidget::findTabAtPos( const QPoint *pos )
|
|
{
|
|
|
|
if( pos->y() > 1 && pos->y() < m_tabbarHeight - 1 )
|
|
{
|
|
int cx = ((m_caption == "") ? 4 : 14) + horizontalAdvance(fontMetrics(), m_caption);
|
|
|
|
for( widgetStack::iterator it = m_widgets.begin(); it != m_widgets.end(); ++it )
|
|
{
|
|
if( pos->x() >= cx && pos->x() <= cx + ( *it ).nwidth )
|
|
{
|
|
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 )
|
|
{
|
|
auto helpEvent = static_cast<QHelpEvent*>(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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void TabWidget::resizeEvent( QResizeEvent * )
|
|
{
|
|
if (!m_resizable)
|
|
{
|
|
for (const auto& widget : m_widgets)
|
|
{
|
|
widget.w->setFixedSize(width() - 4, height() - m_tabbarHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void TabWidget::paintEvent( QPaintEvent * pe )
|
|
{
|
|
QPainter p( this );
|
|
p.setFont( pointSize<7>( font() ) );
|
|
|
|
// Draw background
|
|
QBrush bg_color = p.background();
|
|
p.fillRect( 0, 0, width() - 1, height() - 1, bg_color );
|
|
|
|
// Draw external borders
|
|
p.setPen( tabBorder() );
|
|
p.drawRect( 0, 0, width() - 1, height() - 1 );
|
|
|
|
// Draw tabs' bar background
|
|
p.fillRect( 1, 1, width() - 2, m_tabheight + 2, tabBackground() );
|
|
|
|
// Draw title, if any
|
|
if( ! m_caption.isEmpty() )
|
|
{
|
|
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 + horizontalAdvance(fontMetrics(), m_caption);
|
|
|
|
// 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 )
|
|
{
|
|
tab_width = ( width() - tab_x_offset ) / std::distance( first, last );
|
|
}
|
|
|
|
// Draw all tabs
|
|
p.setPen( tabText() );
|
|
for( widgetStack::iterator it = first ; it != last ; ++it )
|
|
{
|
|
// Draw a text tab or a artwork tab.
|
|
if( m_usePixmap )
|
|
{
|
|
// 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 );
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// Switch between tabs with mouse wheel
|
|
void TabWidget::wheelEvent( QWheelEvent * we )
|
|
{
|
|
if(position(we).y() > m_tabheight)
|
|
{
|
|
return;
|
|
}
|
|
|
|
we->accept();
|
|
int dir = (we->angleDelta().y() < 0) ? 1 : -1;
|
|
int tab = m_activeTab;
|
|
while( tab > -1 && static_cast<int>( tab ) < m_widgets.count() )
|
|
{
|
|
tab += dir;
|
|
if( m_widgets.contains( tab ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
setActiveTab( tab );
|
|
}
|
|
|
|
|
|
|
|
|
|
// Let parent widgets know how much space this tab widget needs
|
|
QSize TabWidget::minimumSizeHint() const
|
|
{
|
|
if (m_resizable)
|
|
{
|
|
int maxWidth = 0, maxHeight = 0;
|
|
for (const auto& widget : m_widgets)
|
|
{
|
|
maxWidth = std::max(maxWidth, widget.w->minimumSizeHint().width());
|
|
maxHeight = std::max(maxHeight, widget.w->minimumSizeHint().height());
|
|
}
|
|
// "-1" :
|
|
// in "addTab", under "Position tab's window", the widget is
|
|
// moved up by 1 pixel
|
|
return QSize(maxWidth + 4, maxHeight + m_tabbarHeight - 1);
|
|
}
|
|
else { return QWidget::minimumSizeHint(); }
|
|
}
|
|
|
|
|
|
|
|
|
|
QSize TabWidget::sizeHint() const
|
|
{
|
|
if (m_resizable)
|
|
{
|
|
int maxWidth = 0, maxHeight = 0;
|
|
for (const auto& widget : m_widgets)
|
|
{
|
|
maxWidth = std::max(maxWidth, widget.w->sizeHint().width());
|
|
maxHeight = std::max(maxHeight, widget.w->sizeHint().height());
|
|
}
|
|
// "-1" :
|
|
// in "addTab", under "Position tab's window", the widget is
|
|
// moved up by 1 pixel
|
|
return QSize(maxWidth + 4, maxHeight + m_tabbarHeight - 1);
|
|
}
|
|
else { return QWidget::sizeHint(); }
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
} // namespace lmms::gui
|