/src/sipconfigdelegate.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 282 lines · 207 code · 40 blank · 35 comment · 21 complexity · a061bcc0d9efb1ee5a0bb0bd70c0fcf2 MD5 · raw file

  1. /*
  2. Copyright (C) 2011 Leo Franchi <leo.franchi@kdab.com>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #include "sipconfigdelegate.h"
  15. #include <QApplication>
  16. #include <QPainter>
  17. #include "sip/SipModel.h"
  18. #include "sip/SipPlugin.h"
  19. #include "utils/tomahawkutils.h"
  20. #include "utils/logger.h"
  21. #define ICONSIZE 24
  22. #define CHECK_LEFT_EDGE 8
  23. SipConfigDelegate::SipConfigDelegate( QObject* parent )
  24. : ConfigDelegateBase ( parent )
  25. {
  26. connect( this, SIGNAL( configPressed( QModelIndex ) ), this, SLOT( askedForEdit( QModelIndex ) ) );
  27. }
  28. bool
  29. SipConfigDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
  30. {
  31. return ConfigDelegateBase::editorEvent( event, model, option, index );
  32. }
  33. void
  34. SipConfigDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
  35. {
  36. QStyleOptionViewItemV4 opt = option;
  37. initStyleOption( &opt, index );
  38. QRect itemRect = opt.rect;
  39. int top = itemRect.top();
  40. int mid = itemRect.height() / 2;
  41. // one line bold for account name
  42. // space below it fro an error
  43. // checkbox, icon, name, online/offline status, config icon
  44. QFont name = opt.font;
  45. name.setPointSize( name.pointSize() + 2 );
  46. name.setBold( true );
  47. QFont error = opt.font;
  48. error.setItalic( true );
  49. error.setPointSize( error.pointSize() - 2 );
  50. // draw the background
  51. const QWidget* w = opt.widget;
  52. QStyle* style = w ? w->style() : QApplication::style();
  53. style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
  54. int iconLeftEdge = CHECK_LEFT_EDGE + ICONSIZE + PADDING;
  55. int textLeftEdge = iconLeftEdge + ICONSIZE + PADDING;
  56. if( index.data( SipModel::FactoryRole ).toBool() ) { // this is the "add new account" row
  57. // draw a border and background
  58. painter->save();
  59. painter->setRenderHints( QPainter::Antialiasing );
  60. painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 150 ) );
  61. QPainterPath roundedRect;
  62. roundedRect.addRoundedRect( itemRect.adjusted( 1, 1, -1, -1 ), 3, 3 );
  63. painter->drawPath( roundedRect );
  64. painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 170 ) );
  65. painter->fillPath( roundedRect, painter->brush() );
  66. painter->restore();
  67. // draw "+" icon in checkbox column
  68. int rectW = 18;
  69. int diff = ( ICONSIZE/ 2 ) - ( rectW / 2) ;
  70. int pos = ( mid ) - ( rectW / 2 );
  71. QRect plusRect = QRect( CHECK_LEFT_EDGE + diff, pos + top, rectW, rectW );
  72. QPixmap p( RESPATH "images/list-add.png" );
  73. painter->drawPixmap( plusRect, p );
  74. // draw text
  75. QFont f = opt.font;
  76. f.setPointSize( f.pointSize() );
  77. f.setBold( true );
  78. QFontMetrics fm( f );
  79. QString text = index.data( Qt::DisplayRole ).toString();
  80. QRect textR = fm.boundingRect( text );
  81. textR.moveLeft( textLeftEdge );
  82. textR.moveTop( mid - ( textR.height() / 2 ) + top );
  83. textR.setRight( itemRect.right() );
  84. painter->setFont( f );
  85. painter->drawText( textR, text );
  86. } else if( index.data( SipModel::FactoryItemRole ).toBool() ) { // this is an account type
  87. // ConfigDelegateBase::paint( painter, opt, index );
  88. // int indent = 10;
  89. // draw a border and background
  90. painter->save();
  91. painter->setRenderHints( QPainter::Antialiasing );
  92. painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 170 ) );
  93. QPainterPath roundedRect;
  94. roundedRect.addRoundedRect( itemRect.adjusted( 1, 1, -1, -1 ), 3, 3 );
  95. painter->drawPath( roundedRect );
  96. painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 180 ) );
  97. painter->fillPath( roundedRect, painter->brush() );
  98. painter->restore();
  99. QIcon icon = index.data( SipModel::FactoryItemIcon ).value< QIcon >();
  100. if( !icon.isNull() ) {
  101. int rectW = 18;
  102. int diff = ( ICONSIZE/ 2 ) - ( rectW / 2) ;
  103. int pos = ( mid ) - ( rectW / 2 );
  104. QRect rect = QRect( CHECK_LEFT_EDGE + diff, pos + top, rectW, rectW );
  105. QPixmap p( icon.pixmap( rect.size() ) );
  106. painter->drawPixmap( rect, p );
  107. }
  108. // draw text
  109. QFont f = opt.font;
  110. f.setPointSize( f.pointSize() );
  111. f.setBold( true );
  112. QFontMetrics fm( f );
  113. QString text = index.data( Qt::DisplayRole ).toString();
  114. QRect textR = fm.boundingRect( text );
  115. textR.moveLeft( textLeftEdge );
  116. textR.moveTop( mid - ( textR.height() / 2 ) + top );
  117. textR.setRight( itemRect.right() );
  118. painter->setFont( f );
  119. painter->drawText( textR, text );
  120. } else { // this is an existing account to show
  121. // draw checkbox first
  122. int pos = ( mid ) - ( ICONSIZE / 2 );
  123. QRect checkRect = QRect( CHECK_LEFT_EDGE, pos + top, ICONSIZE, ICONSIZE );
  124. opt.rect = checkRect;
  125. drawCheckBox( opt, painter, w );
  126. // draw the icon if it exists
  127. pos = ( mid ) - ( ICONSIZE / 2 );
  128. if( !index.data( Qt::DecorationRole ).value< QIcon >().isNull() ) {
  129. QRect prect = QRect( iconLeftEdge, pos + top, ICONSIZE, ICONSIZE );
  130. painter->save();
  131. painter->drawPixmap( prect, index.data( Qt::DecorationRole ).value< QIcon >().pixmap( prect.size() ) );
  132. painter->restore();
  133. }
  134. // from the right edge--config status and online/offline
  135. QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, mid - ICONSIZE / 2 + top, ICONSIZE, ICONSIZE );
  136. if( index.data( SipModel::HasConfig ).toBool() ) {
  137. QStyleOptionToolButton topt;
  138. topt.rect = confRect;
  139. topt.pos = confRect.topLeft();
  140. drawConfigWrench( painter, opt, topt );
  141. }
  142. // draw the online/offline status
  143. int statusIconSize = 18;
  144. int statusX = confRect.left() - 2*PADDING - statusIconSize;
  145. QFont statusF = opt.font;
  146. statusF.setPointSize( statusF.pointSize() - 2 );
  147. QFontMetrics statusFM( statusF );
  148. QPixmap p;
  149. QString statusText;
  150. SipPlugin::ConnectionState state = static_cast< SipPlugin::ConnectionState >( index.data( SipModel::ConnectionStateRole ).toInt() );
  151. if( state == SipPlugin::Connected ) {
  152. p = QPixmap( RESPATH "images/sipplugin-online.png" );
  153. statusText = tr( "Online" );
  154. } else if( state == SipPlugin::Connecting ) {
  155. p = QPixmap( RESPATH "images/sipplugin-offline.png" );
  156. statusText = tr( "Connecting..." );
  157. } else {
  158. p = QPixmap( RESPATH "images/sipplugin-offline.png" );
  159. statusText = tr( "Offline" );
  160. }
  161. p = p.scaled( statusIconSize, statusIconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
  162. painter->drawPixmap( statusX, mid - statusIconSize / 2 + top, statusIconSize, statusIconSize, p );
  163. int width = statusFM.width( statusText );
  164. statusX = statusX - PADDING - width;
  165. painter->save();
  166. painter->setFont( statusF );
  167. painter->drawText( QRect( statusX, mid - statusFM.height() / 2 + top, width, statusFM.height() ), statusText );
  168. painter->restore();
  169. // name
  170. painter->save();
  171. QFontMetrics namefm( name );
  172. int nameHeight = namefm.boundingRect( "test" ).height();
  173. // pos will the top-left point of the text rect
  174. pos = mid - ( nameHeight / 2 );
  175. // TODO bound with config icon and offline/online status
  176. width = itemRect.width() - textLeftEdge;
  177. if( !index.data( SipModel::ErrorString ).toString().isEmpty() ) { // error, show that too
  178. QRect errorRect( textLeftEdge, mid + top, width, mid - PADDING + 1 );
  179. QFontMetrics errorFm( error );
  180. QString str = errorFm.elidedText( index.data( SipModel::ErrorString ).toString(), Qt::ElideRight, errorRect.width() );
  181. painter->setFont( error );
  182. painter->drawText( errorRect, str );
  183. pos = mid - errorRect.height() - 2; // move the name rect up
  184. }
  185. QString nameStr = namefm.elidedText( index.data( Qt::DisplayRole ).toString(), Qt::ElideRight, width );
  186. painter->setFont( name );
  187. painter->drawText( QRect( textLeftEdge, pos + top, width, nameHeight + 1 ), nameStr );
  188. painter->restore();
  189. }
  190. }
  191. QRect
  192. SipConfigDelegate::checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx ) const
  193. {
  194. if( !idx.data( SipModel::FactoryItemRole ).toBool() && !idx.data( SipModel::FactoryRole ).toBool() )
  195. {
  196. QStyleOptionViewItemV4 opt = option;
  197. initStyleOption( &opt, idx );
  198. int mid = opt.rect.height() / 2;
  199. int pos = ( mid ) - ( ICONSIZE / 2 );
  200. QRect checkRect = QRect( CHECK_LEFT_EDGE, pos + opt.rect.top(), ICONSIZE, ICONSIZE );
  201. return checkRect;
  202. }
  203. return QRect();
  204. }
  205. QRect
  206. SipConfigDelegate::configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
  207. {
  208. if( !idx.data( SipModel::FactoryItemRole ).toBool() && !idx.data( SipModel::FactoryRole ).toBool() )
  209. {
  210. QStyleOptionViewItemV4 opt = option;
  211. initStyleOption( &opt, idx );
  212. QRect itemRect = opt.rect;
  213. QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, (opt.rect.height() / 2) - ICONSIZE / 2 + opt.rect.top(), ICONSIZE, ICONSIZE );
  214. return confRect;
  215. }
  216. return QRect();
  217. }
  218. QSize
  219. SipConfigDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
  220. {
  221. if( index.data( SipModel::FactoryRole ).toBool() || index.data( SipModel::FactoryItemRole ).toBool() ) { // this is the "add new account" row
  222. // enough space for one line of text
  223. QStyleOptionViewItemV4 opt = option;
  224. initStyleOption( &opt, index );
  225. int width = QStyledItemDelegate::sizeHint( option, index ).width();
  226. QFont name = opt.font;
  227. name.setPointSize( name.pointSize() + 1 );
  228. name.setBold( true );
  229. QFontMetrics sfm( name );
  230. return QSize( width, 3 * PADDING + sfm.height() );
  231. } else { // this is an existing account to show
  232. return ConfigDelegateBase::sizeHint( option, index );
  233. }
  234. }
  235. void
  236. SipConfigDelegate::askedForEdit( const QModelIndex& idx )
  237. {
  238. emit openConfig( qobject_cast< SipPlugin* >( idx.data( SipModel::SipPluginData ).value< QObject* >() ) );
  239. }