void LovedTracksItem::activate() { if ( !m_lovedTracksPage ) { SourceItem* par = dynamic_cast< SourceItem* >( parent() ); PlaylistViewPage* pv = new PlaylistViewPage( ViewManager::instance()->widget() ); pv->setPixmap( TomahawkUtils::defaultPixmap( TomahawkUtils::LovedPlaylist, TomahawkUtils::Original, QSize( 128, 128 ) ) ); TopLovedTracksModel* raModel = new TopLovedTracksModel( pv ); raModel->setTitle( text() ); TrackItemDelegate* del = new TrackItemDelegate( TrackItemDelegate::LovedTracks, pv->view()->trackView(), pv->view()->trackView()->proxyModel() ); pv->view()->trackView()->setPlaylistItemDelegate( del ); pv->view()->trackView()->setEmptyTip( tr( "Sorry, we could not find any of your Favorites!" ) ); if ( !par ) { raModel->setDescription( tr( "The most loved tracks from all your friends" ) ); pv->view()->setGuid( QString( "lovedtracks" ) ); } else { if ( par->source()->isLocal() ) raModel->setDescription( tr( "All of your loved tracks" ) ); else raModel->setDescription( tr( "All of %1's loved tracks" ).arg( par->source()->friendlyName() ) ); pv->view()->setGuid( QString( "lovedtracks/%1" ).arg( par->source()->nodeId() ) ); } pv->view()->trackView()->setPlayableModel( raModel ); raModel->setSource( !par ? source_ptr() : par->source() ); m_lovedTracksPage = pv; } ViewManager::instance()->show( m_lovedTracksPage ); model()->linkSourceItemToPage( this, m_lovedTracksPage ); }
QSize SourceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const { SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >(); SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() ); if ( type == SourcesModel::Source || type == SourcesModel::ScriptCollection ) { SourceItem* colItem = qobject_cast< SourceItem* >( item ); return QSize( option.rect.width(), ( colItem && colItem->source() && colItem->source()->isLocal() ) ? 0 : option.fontMetrics.height() * 3.2 ); } else if ( type == SourcesModel::Divider ) { return QSize( option.rect.width(), TomahawkUtils::DpiScaler::scaledY( m_parent, 6 ) ); } else if ( type == SourcesModel::Group ) { const int groupSpacer = index.row() > 0 ? option.fontMetrics.height() * 2.5 : option.fontMetrics.height() * 1.8; return QSize( option.rect.width(), option.fontMetrics.height() + groupSpacer ); } else return QSize( option.rect.width(), option.fontMetrics.height() * 1.8 ); //QStyledItemDelegate::sizeHint( option, index ) ); }
void SourceTreeView::setupMenus() { m_playlistMenu.clear(); m_roPlaylistMenu.clear(); m_latchMenu.clear(); m_privacyMenu.clear(); bool readonly = true; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); if ( type == SourcesModel::StaticPlaylist || type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { const PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); const playlist_ptr playlist = item->playlist(); if ( !playlist.isNull() ) { readonly = !playlist->author()->isLocal(); } } QAction* latchOnAction = ActionCollection::instance()->getAction( "latchOn" ); m_latchMenu.addAction( latchOnAction ); m_privacyMenu.addAction( ActionCollection::instance()->getAction( "togglePrivacy" ) ); if ( type == SourcesModel::Collection ) { SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex ); source_ptr source = item->source(); if ( !source.isNull() ) { if ( m_latchManager->isLatched( source ) ) { QAction *latchOffAction = ActionCollection::instance()->getAction( "latchOff" ); m_latchMenu.addAction( latchOffAction ); connect( latchOffAction, SIGNAL( triggered() ), SLOT( latchOff() ) ); m_latchMenu.addSeparator(); QAction *latchRealtimeAction = ActionCollection::instance()->getAction( "realtimeFollowingAlong" ); latchRealtimeAction->setChecked( source->playlistInterface()->latchMode() == Tomahawk::PlaylistModes::RealTime ); m_latchMenu.addAction( latchRealtimeAction ); connect( latchRealtimeAction, SIGNAL( toggled( bool ) ), SLOT( latchModeToggled( bool ) ) ); } } } QAction *loadPlaylistAction = ActionCollection::instance()->getAction( "loadPlaylist" ); m_playlistMenu.addAction( loadPlaylistAction ); QAction *renamePlaylistAction = ActionCollection::instance()->getAction( "renamePlaylist" ); m_playlistMenu.addAction( renamePlaylistAction ); m_playlistMenu.addSeparator(); QAction *copyPlaylistAction = m_playlistMenu.addAction( tr( "&Copy Link" ) ); QAction *deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) ); QString addToText; if ( type == SourcesModel::StaticPlaylist ) addToText = tr( "Add to my Playlists" ); if ( type == SourcesModel::AutomaticPlaylist ) addToText = tr( "Add to my Automatic Playlists" ); else if ( type == SourcesModel::Station ) addToText = tr( "Add to my Stations" ); QAction *addToLocalAction = m_roPlaylistMenu.addAction( addToText ); m_roPlaylistMenu.addAction( copyPlaylistAction ); deletePlaylistAction->setEnabled( !readonly ); renamePlaylistAction->setEnabled( !readonly ); addToLocalAction->setEnabled( readonly ); // Handle any custom actions registered for playlists if ( type == SourcesModel::StaticPlaylist && !readonly && !ActionCollection::instance()->getAction( ActionCollection::LocalPlaylists ).isEmpty() ) { m_playlistMenu.addSeparator(); const PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); const playlist_ptr playlist = item->playlist(); foreach ( QAction* action, ActionCollection::instance()->getAction( ActionCollection::LocalPlaylists ) ) { if ( QObject* notifier = ActionCollection::instance()->actionNotifier( action ) ) { QMetaObject::invokeMethod( notifier, "aboutToShow", Qt::DirectConnection, Q_ARG( QAction*, action ), Q_ARG( Tomahawk::playlist_ptr, playlist ) ); } action->setProperty( "payload", QVariant::fromValue< playlist_ptr >( playlist ) ); m_playlistMenu.addAction( action ); }
void SourceTreeView::setupMenus() { m_playlistMenu.clear(); m_roPlaylistMenu.clear(); m_latchMenu.clear(); m_privacyMenu.clear(); bool readonly = true; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); if ( type == SourcesModel::StaticPlaylist || type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); playlist_ptr playlist = item->playlist(); if ( !playlist.isNull() ) { readonly = !playlist->author()->isLocal(); } } QAction* latchOnAction = ActionCollection::instance()->getAction( "latchOn" ); m_latchMenu.addAction( latchOnAction ); m_privacyMenu.addAction( ActionCollection::instance()->getAction( "togglePrivacy" ) ); if ( type == SourcesModel::Collection ) { SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex ); source_ptr source = item->source(); if ( !source.isNull() ) { if ( m_latchManager->isLatched( source ) ) { QAction *latchOffAction = ActionCollection::instance()->getAction( "latchOff" ); m_latchMenu.addAction( latchOffAction ); connect( latchOffAction, SIGNAL( triggered() ), SLOT( latchOff() ) ); m_latchMenu.addSeparator(); QAction *latchRealtimeAction = ActionCollection::instance()->getAction( "realtimeFollowingAlong" ); latchRealtimeAction->setChecked( source->playlistInterface()->latchMode() == Tomahawk::PlaylistInterface::RealTime ); m_latchMenu.addAction( latchRealtimeAction ); connect( latchRealtimeAction, SIGNAL( toggled( bool ) ), SLOT( latchModeToggled( bool ) ) ); } } } QAction *loadPlaylistAction = ActionCollection::instance()->getAction( "loadPlaylist" ); m_playlistMenu.addAction( loadPlaylistAction ); QAction *renamePlaylistAction = ActionCollection::instance()->getAction( "renamePlaylist" ); m_playlistMenu.addAction( renamePlaylistAction ); m_playlistMenu.addSeparator(); QAction *copyPlaylistAction = m_playlistMenu.addAction( tr( "&Copy Link" ) ); QAction *deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) ); QString addToText = QString( "Add to my %1" ); if ( type == SourcesModel::StaticPlaylist ) addToText = addToText.arg( "Playlists" ); if ( type == SourcesModel::AutomaticPlaylist ) addToText = addToText.arg( "Automatic Playlists" ); else if ( type == SourcesModel::Station ) addToText = addToText.arg( "Stations" ); QAction *addToLocalAction = m_roPlaylistMenu.addAction( tr( addToText.toUtf8(), "Adds the given playlist, dynamic playlist, or station to the users's own list" ) ); m_roPlaylistMenu.addAction( copyPlaylistAction ); deletePlaylistAction->setEnabled( !readonly ); renamePlaylistAction->setEnabled( !readonly ); addToLocalAction->setEnabled( readonly ); if ( type == SourcesModel::StaticPlaylist ) copyPlaylistAction->setText( tr( "&Export Playlist" ) ); connect( loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) ); connect( renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) ); connect( deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) ); connect( copyPlaylistAction, SIGNAL( triggered() ), SLOT( copyPlaylistLink() ) ); connect( addToLocalAction, SIGNAL( triggered() ), SLOT( addToLocal() ) ); connect( latchOnAction, SIGNAL( triggered() ), SLOT( latchOnOrCatchUp() ), Qt::QueuedConnection ); }
bool SourceDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ) { QMouseEvent* mEvent = 0; switch ( event->type() ) { // case QEvent::MouseTrackingChange: case QEvent::MouseButtonDblClick: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: mEvent = static_cast< QMouseEvent* >( event ); default: break; } bool hoveringTrack = false; if ( m_trackRects.contains( index ) && mEvent ) { const QRect trackRect = m_trackRects[ index ]; hoveringTrack = trackRect.contains( mEvent->pos() ); if ( hoveringTrack ) { if ( m_trackHovered != index ) { m_trackHovered = index; QMetaObject::invokeMethod( m_parent, "update", Qt::QueuedConnection, Q_ARG( QModelIndex, index ) ); } } } if ( !hoveringTrack ) { if ( m_trackHovered.isValid() ) QMetaObject::invokeMethod( m_parent, "update", Qt::QueuedConnection, Q_ARG( QModelIndex, m_trackHovered ) ); m_trackHovered = QPersistentModelIndex(); } bool lockRectContainsClick = false, headphonesRectContainsClick = false; if ( m_headphoneRects.contains( index ) && mEvent ) { const QRect headphoneRect = m_headphoneRects[ index ]; headphonesRectContainsClick = headphoneRect.contains( mEvent->pos() ); } if ( m_lockRects.contains( index ) && mEvent ) { const QRect lockRect = m_lockRects[ index ]; lockRectContainsClick = lockRect.contains( mEvent->pos() ); } if ( event->type() == QEvent::MouseMove ) { if ( hoveringTrack || lockRectContainsClick || headphonesRectContainsClick ) m_parent->setCursor( Qt::PointingHandCursor ); else m_parent->setCursor( Qt::ArrowCursor ); } if ( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonPress ) { SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() ); if ( type == SourcesModel::TemporaryPage || type == SourcesModel::DeletablePage || type == SourcesModel::RemovablePage ) { SourceTreeItem* gpi = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >(); Q_ASSERT( gpi ); QStyleOptionViewItemV4 o = option; initStyleOption( &o, index ); const int padding = m_margin / 8; const QRect r( o.rect.right() - padding - m_iconHeight, padding + o.rect.y(), m_iconHeight, m_iconHeight ); if ( r.contains( mEvent->pos() ) ) { if ( event->type() == QEvent::MouseButtonRelease && mEvent->button() == Qt::LeftButton ) { gpi->removeFromList(); // Send a new mouse event to the view, since if the mouse is now over another item's delete area we want it to show up QMouseEvent* ev = new QMouseEvent( QEvent::MouseMove, m_parent->viewport()->mapFromGlobal( QCursor::pos() ), Qt::NoButton, Qt::NoButton, Qt::NoModifier ); QApplication::postEvent( m_parent->viewport(), ev ); } return true; } } else if ( type == SourcesModel::Source ) { SourceItem* colItem = qobject_cast< SourceItem* >( index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() ); Q_ASSERT( colItem ); if ( hoveringTrack && colItem->source() && colItem->source()->currentTrack() ) { if ( event->type() == QEvent::MouseButtonRelease && mEvent->button() == Qt::LeftButton ) { ViewManager::instance()->show( colItem->source()->currentTrack() ); return true; } else if ( event->type() == QEvent::MouseButtonPress && mEvent->button() == Qt::RightButton ) { Tomahawk::ContextMenu* contextMenu = new Tomahawk::ContextMenu( m_parent ); contextMenu->setQuery( colItem->source()->currentTrack() ); contextMenu->exec( QCursor::pos() ); return true; } } if ( !colItem->source().isNull() && !colItem->source()->currentTrack().isNull() && !colItem->source()->isLocal() ) { if ( headphonesRectContainsClick || lockRectContainsClick ) { if ( event->type() == QEvent::MouseButtonRelease && mEvent->button() == Qt::LeftButton ) { if ( headphonesRectContainsClick ) { if ( index.data( SourcesModel::LatchedOnRole ).toBool() ) // unlatch emit latchOff( colItem->source() ); else emit latchOn( colItem->source() ); } else // it's in the lock rect emit toggleRealtimeLatch( colItem->source(), !index.data( SourcesModel::LatchedRealtimeRole ).toBool() ); } return true; } } } else if ( event->type() == QEvent::MouseButtonRelease && mEvent->button() == Qt::LeftButton && type == SourcesModel::StaticPlaylist ) { PlaylistItem* plItem = qobject_cast< PlaylistItem* >( index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() ); Q_ASSERT( plItem ); if ( plItem->canSubscribe() && !plItem->subscribedIcon().isNull() ) { const int padding = m_margin / 16; const int imgWidth = option.rect.height() - 2 * padding; const QRect subRect( option.rect.right() - padding - imgWidth, option.rect.top() + padding, imgWidth, imgWidth ); if ( subRect.contains( mEvent->pos() ) ) { // Toggle playlist subscription plItem->setSubscribed( !plItem->subscribed() ); } } } } // We emit our own clicked() signal instead of relying on QTreeView's, because that is fired whether or not a delegate accepts // a mouse press event. Since we want to swallow click events when they are on headphones other action items, here we make sure we only // emit if we really want to if ( event->type() == QEvent::MouseButtonRelease && mEvent->button() == Qt::LeftButton ) { if ( m_lastClicked == -1 ) { m_lastClicked = QDateTime::currentMSecsSinceEpoch(); emit clicked( index ); } else { qint64 elapsed = QDateTime::currentMSecsSinceEpoch() - m_lastClicked; if ( elapsed < QApplication::doubleClickInterval() ) { m_lastClicked = -1; emit doubleClicked( index ); } else { m_lastClicked = QDateTime::currentMSecsSinceEpoch(); emit clicked( index ); } } } return QStyledItemDelegate::editorEvent( event, model, option, index ); }
void SourceDelegate::paintSource( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { painter->save(); painter->setPen( Qt::black ); QFont font = painter->font(); font.setPointSize( TomahawkUtils::defaultFontSize() ); painter->setFont( font ); SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >(); SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() ); const int iconRectVertMargin = m_margin / 4; const QRect iconRect = option.rect.adjusted( m_margin / 2 + m_margin / 4, iconRectVertMargin, -option.rect.width() + option.rect.height() + m_margin / 4, -iconRectVertMargin ); QString name = index.data().toString(); QPixmap avatar; int figWidth = 0; bool isPlaying = false; QString desc; QString tracks; bool shouldDrawDropHint = false; if ( type == SourcesModel::Source ) { // If the user is about to drop a track on a peer QRect itemsRect = option.rect; QPoint cursorPos = m_parent->mapFromGlobal( QCursor::pos() ); bool cursorInRect = itemsRect.contains( cursorPos ); if ( cursorInRect && m_dropHoverIndex.isValid() && m_dropHoverIndex == index ) shouldDrawDropHint = true; SourceItem* colItem = qobject_cast< SourceItem* >( item ); Q_ASSERT( colItem ); bool status = !( !colItem->source() || !colItem->source()->isOnline() ); if ( colItem->source() && !colItem->source()->isLocal() ) { if ( status ) { tracks = QString::number( colItem->source()->trackCount() ); if ( shouldDrawDropHint ) figWidth = iconRect.width(); name = colItem->source()->friendlyName(); } avatar = colItem->pixmap( iconRect.size() ); isPlaying = !colItem->source()->currentTrack().isNull(); desc = colItem->source()->textStatus(); if ( colItem->source().isNull() ) desc = tr( "All available tracks" ); } } else if ( type == SourcesModel::ScriptCollection ) { ScriptCollectionItem* scItem = qobject_cast< ScriptCollectionItem* >( item ); Q_ASSERT( scItem ); if ( !scItem->collection().isNull() ) { int trackCount = scItem->collection()->trackCount(); if ( trackCount >= 0 ) { tracks = QString::number( trackCount ); figWidth = painter->fontMetrics().width( tracks ); } name = scItem->collection()->itemName(); } avatar = scItem->icon().pixmap( iconRect.size() ); desc = qobject_cast< Tomahawk::ScriptCollection* >( scItem->collection().data() )->description(); } painter->setOpacity( 1.0 ); painter->drawPixmap( iconRect, avatar ); QRect textRect = option.rect.adjusted( iconRect.width() + m_margin, m_margin / 6 + m_margin / 32, -figWidth - ( figWidth ? m_margin : 0 ), 0 ); QString text = painter->fontMetrics().elidedText( name, Qt::ElideRight, textRect.width() ); { QTextOption to; to.setWrapMode( QTextOption::NoWrap ); painter->setOpacity( 0.7 ); painter->drawText( textRect, text, to ); } textRect = option.rect.adjusted( iconRect.width() + m_margin, option.rect.height() / 2, -figWidth - ( figWidth ? m_margin : 0 ), -m_margin / 4 ); if ( type == SourcesModel::Source ) { SourceItem* colItem = qobject_cast< SourceItem* >( item ); Q_ASSERT( colItem ); bool privacyOn = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::FullyPrivate; if ( !colItem->source().isNull() && colItem->source()->isLocal() && privacyOn ) { QRect pmRect = textRect; pmRect.setRight( pmRect.left() + pmRect.height() ); ActionCollection::instance()->getAction( "togglePrivacy" )->icon().paint( painter, pmRect ); textRect.adjust( pmRect.width() + m_margin / 8, 0, 0, 0 ); } if ( ( isPlaying || ( !colItem->source().isNull() && colItem->source()->isLocal() ) ) && !shouldDrawDropHint ) { // Show a listen icon TomahawkUtils::ImageType listenAlongPixmap = TomahawkUtils::Invalid; TomahawkUtils::ImageType realtimeListeningAlongPixmap = TomahawkUtils::Invalid; if ( index.data( SourcesModel::LatchedOnRole ).toBool() ) { // Currently listening along listenAlongPixmap = TomahawkUtils::HeadphonesOn; if ( !colItem->source()->isLocal() ) { realtimeListeningAlongPixmap = colItem->source()->playlistInterface()->latchMode() == Tomahawk::PlaylistModes::RealTime ? TomahawkUtils::PadlockClosed : TomahawkUtils::PadlockOpen; } } else if ( !colItem->source()->isLocal() ) { listenAlongPixmap = TomahawkUtils::HeadphonesOff; } if ( listenAlongPixmap != TomahawkUtils::Invalid ) { QRect pmRect = textRect; pmRect.setRight( pmRect.left() + pmRect.height() ); painter->drawPixmap( pmRect, TomahawkUtils::defaultPixmap( listenAlongPixmap, TomahawkUtils::Original, pmRect.size() ) ); textRect.adjust( pmRect.width() + m_margin / 8, 0, 0, 0 ); m_headphoneRects[ index ] = pmRect; } else m_headphoneRects.remove( index ); if ( realtimeListeningAlongPixmap != TomahawkUtils::Invalid ) { QRect pmRect = textRect; pmRect.setRight( pmRect.left() + pmRect.height() ); painter->drawPixmap( pmRect, TomahawkUtils::defaultPixmap( realtimeListeningAlongPixmap, TomahawkUtils::Original, pmRect.size() ) ); textRect.adjust( pmRect.width() + m_margin / 8, 0, 0, 0 ); m_lockRects[ index ] = pmRect; } else m_lockRects.remove( index ); } } painter->save(); if ( m_trackHovered == index ) { QFont font = painter->font(); font.setUnderline( true ); painter->setFont( font ); } textRect.adjust( 0, 0, 0, m_margin / 16 ); if ( shouldDrawDropHint ) { desc = tr( "Drop to send tracks" ); } text = painter->fontMetrics().elidedText( desc, Qt::ElideRight, textRect.width() - m_margin / 4 ); { QTextOption to( Qt::AlignVCenter ); to.setWrapMode( QTextOption::NoWrap ); painter->setOpacity( 0.4 ); painter->drawText( textRect, text, to ); } painter->restore(); bool shouldPaintTrackCount = false; if ( type == SourcesModel::Source ) { SourceItem* colItem = qobject_cast< SourceItem* >( item ); Q_ASSERT( colItem ); if ( colItem->source() && colItem->source()->currentTrack() && colItem->source()->state() == Tomahawk::SYNCED ) m_trackRects[ index ] = textRect.adjusted( 0, 0, -textRect.width() + painter->fontMetrics().width( text ), 0 ); else m_trackRects.remove( index ); } else if ( type == SourcesModel::ScriptCollection ) { if ( !tracks.isEmpty() ) shouldPaintTrackCount = true; } if ( shouldPaintTrackCount || shouldDrawDropHint ) { if ( shouldDrawDropHint ) { const QRect figRect = option.rect.adjusted( option.rect.width() - figWidth - iconRectVertMargin, iconRectVertMargin, -iconRectVertMargin, -iconRectVertMargin ); painter->drawPixmap( figRect, TomahawkUtils::defaultPixmap( TomahawkUtils::Inbox, TomahawkUtils::Original, figRect.size() ) ); } else { const QRect figRect = option.rect.adjusted( option.rect.width() - figWidth - m_margin / 2, 0, -m_margin / 2, 0 ); painter->drawText( figRect, tracks, QTextOption( Qt::AlignVCenter | Qt::AlignRight ) ); } } painter->restore(); }