/src/libtomahawk/widgets/Breadcrumb.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 174 lines · 108 code · 31 blank · 35 comment · 8 complexity · c544d1aa70dd10c65deff3ad3de860b1 MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
  4. *
  5. * Tomahawk is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Tomahawk is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "Breadcrumb.h"
  19. #include "BreadcrumbButton.h"
  20. #include "utils/TomahawkStyle.h"
  21. #include "utils/TomahawkUtilsGui.h"
  22. #include "utils/Logger.h"
  23. #include <QStylePainter>
  24. #include <QPushButton>
  25. #include <QHBoxLayout>
  26. #include <QPropertyAnimation>
  27. #include <QDebug>
  28. using namespace Tomahawk;
  29. Breadcrumb::Breadcrumb( QWidget* parent, Qt::WindowFlags f )
  30. : QWidget( parent, f )
  31. , m_model( 0 )
  32. , m_buttonlayout( new QHBoxLayout( this ) )
  33. {
  34. TomahawkUtils::unmarginLayout( m_buttonlayout );
  35. m_buttonlayout->setAlignment( Qt::AlignLeft );
  36. setAutoFillBackground( true );
  37. setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
  38. setLayoutDirection( Qt::LeftToRight );
  39. setLayout( m_buttonlayout );
  40. show();
  41. }
  42. Breadcrumb::~Breadcrumb()
  43. {
  44. }
  45. void
  46. Breadcrumb::setModel( QAbstractItemModel* model )
  47. {
  48. foreach ( BreadcrumbButton* b, m_buttons )
  49. b->deleteLater();;
  50. m_buttons.clear();
  51. m_model = model;
  52. updateButtons( QModelIndex() );
  53. }
  54. void
  55. Breadcrumb::setRootIcon( const QPixmap& pm )
  56. {
  57. m_rootIcon = TomahawkUtils::tinted( pm, Qt::white );
  58. QPushButton* button = new QPushButton( QIcon( m_rootIcon ), "", this );
  59. button->setFlat( true );
  60. button->setStyleSheet( "QPushButton{ background-color: transparent; border: none; width:36px; height:36px; }" );
  61. m_buttonlayout->insertWidget( 0, button );
  62. m_buttonlayout->insertSpacing( 0, 5 );
  63. m_buttonlayout->insertSpacing( 2, 5 );
  64. }
  65. void
  66. Breadcrumb::paintEvent( QPaintEvent* )
  67. {
  68. QStylePainter p( this );
  69. TomahawkStyle::horizontalHeader( &p, rect() );
  70. }
  71. // updateFrom is the item that has changed---all children must be recomputed
  72. // if invalid, redo the whole breadcrumb
  73. void
  74. Breadcrumb::updateButtons( const QModelIndex& updateFrom )
  75. {
  76. // qDebug() << "Updating buttons:" << updateFrom.data();
  77. int cur = 0;
  78. QModelIndex idx = updateFrom;
  79. for ( int i = 0; i < m_buttons.count(); i++ )
  80. {
  81. // qDebug() << "Checking if this breadcrumb item changed:" << m_buttons[ i ]->currentIndex().data() << updateFrom.data() << ( m_buttons[ i ]->currentIndex() != updateFrom);
  82. if ( m_buttons[ i ]->currentIndex() == updateFrom )
  83. {
  84. cur = i;
  85. break;
  86. }
  87. }
  88. // We set the parent index, so go up one
  89. idx = idx.parent();
  90. // Ok, changed all indices that are at cur or past it. lets update them
  91. // When we get to the "end" of the tree, the leaf node is the chart itself
  92. // qDebug() << "DONE and beginning iteration:" << idx.data();
  93. while ( m_model->rowCount( idx ) > 0 )
  94. {
  95. // qDebug() << "CHANGED AND iterating:" << idx.data();
  96. BreadcrumbButton* btn = 0;
  97. if ( m_buttons.size() <= cur )
  98. {
  99. // We have to create a new button, doesn't exist yet
  100. btn = new BreadcrumbButton( this, m_model );
  101. connect( btn, SIGNAL( currentIndexChanged( QModelIndex ) ), this, SLOT( breadcrumbComboChanged( QModelIndex ) ) );
  102. m_buttonlayout->addWidget( btn );
  103. btn->show();
  104. // Animate all buttons except the first
  105. if ( !m_buttons.isEmpty() && isVisible() )
  106. {
  107. QPropertyAnimation* animation = new QPropertyAnimation( btn, "pos" );
  108. animation->setDuration( 300 );
  109. animation->setStartValue( m_buttons.last()->pos() );
  110. animation->setEndValue( btn->pos() );
  111. animation->start( QAbstractAnimation::DeleteWhenStopped );
  112. }
  113. m_buttons.append( btn );
  114. }
  115. else
  116. {
  117. // Got a button already, we just want to change the contents
  118. btn = m_buttons[ cur ];
  119. }
  120. // The children of idx are what populates this combobox.
  121. // It takes care of setting the default/user-populated value.
  122. btn->setParentIndex( idx );
  123. // Repeat with children
  124. idx = btn->currentIndex();
  125. cur++;
  126. }
  127. // extra buttons to delete! (cur is 0-indexed)
  128. while ( m_buttons.size() > cur )
  129. {
  130. BreadcrumbButton* b = m_buttons.takeLast();
  131. m_buttonlayout->removeWidget( b );
  132. b->deleteLater();
  133. }
  134. // Now we're at the leaf, lets activate the chart
  135. emit activateIndex( idx );
  136. }
  137. void
  138. Breadcrumb::breadcrumbComboChanged( const QModelIndex& childSelected )
  139. {
  140. // Some breadcrumb buttons' combobox changed. lets update the child breadcrumbs
  141. tDebug() << "Combo changed:" << childSelected.data();
  142. updateButtons( childSelected );
  143. }