/src/libtomahawk/widgets/BreadcrumbButton.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 197 lines · 134 code · 39 blank · 24 comment · 13 complexity · 2c0fd87dfc89a213367cc3a1f996639c MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2011, Casey Link <unnamedrambler@gmail.com>
  4. * Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
  5. *
  6. * Tomahawk is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Tomahawk is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "BreadcrumbButton.h"
  20. #include "Breadcrumb.h"
  21. #include "ComboBox.h"
  22. #include "utils/TomahawkStyle.h"
  23. #include "utils/TomahawkUtilsGui.h"
  24. #include "utils/Logger.h"
  25. #include <QPaintEvent>
  26. #include <QPainter>
  27. #include <QHBoxLayout>
  28. using namespace Tomahawk;
  29. class BreadcrumbArrow : public QWidget
  30. {
  31. public:
  32. BreadcrumbArrow( QWidget* parent )
  33. : QWidget(parent)
  34. {
  35. setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
  36. }
  37. protected:
  38. virtual void paintEvent( QPaintEvent* ) {
  39. QPainter p( this );
  40. QStyleOption opt;
  41. opt.initFrom( this );
  42. QRect r = rect();
  43. const bool reverse = opt.direction == Qt::RightToLeft;
  44. const int menuButtonWidth = 12;
  45. const int rightSpacing = 10;
  46. const int right = !reverse ? r.right() - rightSpacing : r.left() + menuButtonWidth;
  47. const int height = r.height();
  48. QLine l1( 1, 0, right, height / 2 );
  49. QLine l2( 1, height, right, height / 2 );
  50. p.setRenderHint( QPainter::Antialiasing, true );
  51. // Draw the shadow
  52. QColor shadow( 0, 0, 0, 100 );
  53. p.translate( 0, 1 );
  54. p.setPen( shadow );
  55. p.drawLine( l1 );
  56. p.drawLine( l2 );
  57. // Draw the main arrow
  58. QColor foreGround( "#747474" );
  59. p.translate( 0, -1 );
  60. p.setPen( foreGround );
  61. p.drawLine( l1 );
  62. p.drawLine( l2 );
  63. }
  64. virtual QSize sizeHint() const
  65. {
  66. return QSize( 20, TomahawkUtils::defaultFontHeight() + 8 );
  67. }
  68. };
  69. BreadcrumbButton::BreadcrumbButton( Breadcrumb* parent, QAbstractItemModel* model )
  70. : QWidget( parent )
  71. , m_breadcrumb( parent )
  72. , m_model( model )
  73. , m_combo( new ComboBox( this ) )
  74. , m_arrow( new BreadcrumbArrow( this ) )
  75. {
  76. setLayout( new QHBoxLayout );
  77. TomahawkUtils::unmarginLayout( layout() );
  78. layout()->addWidget( m_combo );
  79. layout()->addWidget( m_arrow );
  80. setFixedHeight( TomahawkUtils::defaultFontHeight() + 8 );
  81. m_combo->setSizeAdjustPolicy( QComboBox::AdjustToContents );
  82. setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Expanding );
  83. connect( m_combo, SIGNAL( activated( int ) ), SLOT( comboboxActivated( int ) ) );
  84. }
  85. void
  86. BreadcrumbButton::paintEvent( QPaintEvent* )
  87. {
  88. QPainter p( this );
  89. TomahawkStyle::horizontalHeader( &p, rect() ); // draw the background
  90. m_arrow->setVisible( hasChildren() );
  91. }
  92. QSize
  93. BreadcrumbButton::sizeHint() const
  94. {
  95. // our width = width of combo + 20px for right-arrow and spacing
  96. const int padding = hasChildren() ? 20 : 8;
  97. return m_combo->sizeHint() + QSize( padding, 0 );
  98. }
  99. void
  100. BreadcrumbButton::setParentIndex( const QModelIndex& idx )
  101. {
  102. m_parentIndex = idx;
  103. // Populate listview with list of children.
  104. // Then try to find a default
  105. QStringList list;
  106. int count = m_model->rowCount( m_parentIndex );
  107. int defaultIndex = -1, userSelected = -1;
  108. for ( int i = 0; i < count; ++i )
  109. {
  110. QModelIndex idx = m_model->index( i, 0, m_parentIndex );
  111. if ( idx.isValid() )
  112. {
  113. list << idx.data().toString();
  114. if ( idx.data( Breadcrumb::DefaultRole ).toBool() )
  115. defaultIndex = i;
  116. if ( idx.data( Breadcrumb::UserSelectedRole ).toBool() )
  117. userSelected = i;
  118. }
  119. }
  120. if ( m_combo->count() && !list.isEmpty() )
  121. {
  122. // Check if it's the same, Don't change if it is, as it'll cause flickering
  123. QStringList old;
  124. for ( int i = 0; i < m_combo->count(); i++ )
  125. old << m_combo->itemText( i );
  126. if ( list == old )
  127. return;
  128. }
  129. m_combo->hide();
  130. m_combo->clear();
  131. m_combo->addItems( list );
  132. if ( userSelected > -1 )
  133. m_combo->setCurrentIndex( userSelected );
  134. else if ( defaultIndex > -1 )
  135. m_combo->setCurrentIndex( defaultIndex );
  136. m_curIndex = m_model->index( m_combo->currentIndex(), 0, m_parentIndex );
  137. m_combo->show();
  138. m_combo->adjustSize();
  139. }
  140. void
  141. BreadcrumbButton::comboboxActivated( int idx )
  142. {
  143. m_model->setData( m_curIndex, false, Breadcrumb::UserSelectedRole );
  144. QModelIndex selected = m_model->index( idx, 0, m_parentIndex );
  145. m_curIndex = selected;
  146. m_model->setData( selected, true, Breadcrumb::UserSelectedRole );
  147. emit currentIndexChanged( selected );
  148. }
  149. bool
  150. BreadcrumbButton::hasChildren() const
  151. {
  152. return m_model->rowCount( m_model->index( m_combo->currentIndex(), 0, m_parentIndex ) ) > 0;
  153. }
  154. QModelIndex
  155. BreadcrumbButton::currentIndex() const
  156. {
  157. return m_model->index( m_combo->currentIndex(), 0, m_parentIndex );
  158. }