From 7690eddff33d12c2b61a1b2c2d49eaf9c09311e1 Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Sun, 22 Jul 2012 14:09:41 -0400 Subject: [PATCH] New source tree popup widget for playlist delete confirmation --- src/libtomahawk/CMakeLists.txt | 1 + src/libtomahawk/Playlist.cpp | 2 +- src/libtomahawk/utils/Closure.cpp | 3 +- .../widgets/SourceTreePopupDialog.cpp | 162 ++++++++++++++++++ .../widgets/SourceTreePopupDialog.h | 69 ++++++++ src/sourcetree/SourceTreeView.cpp | 39 ++++- src/sourcetree/SourceTreeView.h | 6 +- 7 files changed, 270 insertions(+), 12 deletions(-) create mode 100644 src/libtomahawk/widgets/SourceTreePopupDialog.cpp create mode 100644 src/libtomahawk/widgets/SourceTreePopupDialog.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 0a325c166..723730dc8 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -139,6 +139,7 @@ set( libGuiSources widgets/ToggleButton.cpp widgets/FadingPixmap.cpp widgets/SocialPlaylistWidget.cpp + widgets/SourceTreePopupDialog.cpp widgets/infowidgets/SourceInfoWidget.cpp widgets/infowidgets/ArtistInfoWidget.cpp widgets/infowidgets/AlbumInfoWidget.cpp diff --git a/src/libtomahawk/Playlist.cpp b/src/libtomahawk/Playlist.cpp index 1762b7b26..b7f9cc837 100644 --- a/src/libtomahawk/Playlist.cpp +++ b/src/libtomahawk/Playlist.cpp @@ -508,7 +508,7 @@ Playlist::setNewRevision( const QString& rev, tDebug() << "m_entries" << m_entries; tLog() << "Playlist error for playlist with guid" << guid() << "from source" << author()->friendlyName(); - Q_ASSERT( false ); // XXX +// Q_ASSERT( false ); // XXX } } diff --git a/src/libtomahawk/utils/Closure.cpp b/src/libtomahawk/utils/Closure.cpp index 2b2a608bb..8fec43b97 100644 --- a/src/libtomahawk/utils/Closure.cpp +++ b/src/libtomahawk/utils/Closure.cpp @@ -1,5 +1,6 @@ /* This file is part of Clementine. Copyright 2011, David Sansome + Copyright 2012, Leo Franchi Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +30,7 @@ Closure::Closure(QObject* sender, const ClosureArgumentWrapper* val3) : QObject(receiver), callback_(NULL), - autoDelete_( true ), + autoDelete_(true), val0_(val0), val1_(val1), val2_(val2), diff --git a/src/libtomahawk/widgets/SourceTreePopupDialog.cpp b/src/libtomahawk/widgets/SourceTreePopupDialog.cpp new file mode 100644 index 000000000..cabdc73a7 --- /dev/null +++ b/src/libtomahawk/widgets/SourceTreePopupDialog.cpp @@ -0,0 +1,162 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012 Leo Franchi + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#include "SourceTreePopupDialog.h" + +#include "sourcetree/SourceTreeView.h" + +#include +#include +#include +#include +#include +#include +#include + +SourceTreePopupDialog::SourceTreePopupDialog( SourceTreeView* parent ) + : QWidget( 0 ) + , m_result( false ) + , m_label( 0 ) + , m_buttons( 0 ) +{ + setWindowFlags( Qt::FramelessWindowHint ); + setWindowFlags( Qt::Popup ); + + setAutoFillBackground( false ); + setAttribute( Qt::WA_TranslucentBackground, true ); + + setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + + m_label = new QLabel( this ); + m_buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this ); + m_buttons->button( QDialogButtonBox::Ok )->setIcon( QIcon() ); + m_buttons->button( QDialogButtonBox::Cancel )->setIcon( QIcon() ); + + connect( m_buttons, SIGNAL( accepted() ), this, SLOT( onAccepted() ) ); + connect( m_buttons, SIGNAL( rejected() ), this, SLOT( onRejected() ) ); + + setLayout( new QVBoxLayout ); + + layout()->addWidget( m_label ); + layout()->addWidget( m_buttons ); +/* + m_buttons->button( QDialogButtonBox::Ok )->setStyleSheet( + "QPushButton { \ + background-color: #F15C5E; \ + border-style: solid; \ + border-width: 1px; \ + border-radius: 10px; \ + border-color: #B64547; \ + padding: 2px; \ + } \ + QPushButton:pressed { \ + border-style: solid; \ + border-width: 1px; \ + border-radius: 10px; \ + border-color: #B64547; \ + background-color: #D35052; \ + border-style: flat; \ + }" );*/ +} + + +void +SourceTreePopupDialog::setMainText( const QString& text ) +{ + m_label->setText( text ); +} + + +void +SourceTreePopupDialog::setOkButtonText( const QString& text ) +{ + if ( m_buttons && m_buttons->button( QDialogButtonBox::Ok ) ) + m_buttons->button( QDialogButtonBox::Ok )->setText( text ); +} + + +void +SourceTreePopupDialog::paintEvent( QPaintEvent* event ) +{ + // Constants for painting + const int leftTriangleWidth = 20; + const int cornerRounding = 8; + const int leftEdgeOffset = offset() - 6; + const QRect brect = rect().adjusted( 2, 3, -2, -3 ); + + QPainterPath outline; + // Left triangle top branch + outline.moveTo( brect.left(), brect.height() / 2 ); + outline.lineTo( leftEdgeOffset, brect.height() / 2 - leftTriangleWidth / 2 ); + + // main outline + outline.lineTo( leftEdgeOffset, cornerRounding ); + outline.quadTo( QPoint( leftEdgeOffset, brect.top() ), QPoint( leftEdgeOffset + cornerRounding, brect.top() ) ); + outline.lineTo( brect.width() - cornerRounding, brect.top() ); + outline.quadTo( QPoint( brect.width(), brect.top() ), QPoint( brect.width(), cornerRounding ) ); + outline.lineTo( brect.width(), brect.height() - cornerRounding ); + outline.quadTo( brect.bottomRight(), QPoint( brect.right() - cornerRounding, brect.height() ) ); + outline.lineTo( leftEdgeOffset + cornerRounding, brect.height() ); + outline.quadTo( QPoint( leftEdgeOffset, brect.height() ), QPoint( leftEdgeOffset, brect.height() - cornerRounding ) ); + + // Left triangle bottom branch + outline.lineTo( leftEdgeOffset, brect.height() / 2 + leftTriangleWidth / 2 ); + outline.lineTo( brect.left(), brect.height() / 2 ); + + QPainter p( this ); + p.setRenderHint( QPainter::Antialiasing ); + + QPen pen( QColor( "#3F4247" ) ); + pen.setWidth( 2 ); + p.setPen( pen ); + p.drawPath( outline ); + + p.fillPath( outline, QColor( "#D6E3F1" ) ); +} + + +void +SourceTreePopupDialog::focusOutEvent( QFocusEvent* ) +{ + hide(); +} + + +void +SourceTreePopupDialog::showEvent( QShowEvent* ) +{ + m_result = false; +} + + +void +SourceTreePopupDialog::onAccepted() +{ + hide(); + m_result = true; + emit result( m_result ); +} + + +void +SourceTreePopupDialog::onRejected() +{ + hide(); + m_result = false; + emit result( m_result ); +} diff --git a/src/libtomahawk/widgets/SourceTreePopupDialog.h b/src/libtomahawk/widgets/SourceTreePopupDialog.h new file mode 100644 index 000000000..f181dfe2a --- /dev/null +++ b/src/libtomahawk/widgets/SourceTreePopupDialog.h @@ -0,0 +1,69 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012 Leo Franchi + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#ifndef SOURCETREE_POPUP_DIALOG +#define SOURCETREE_POPUP_DIALOG + +#include "DllMacro.h" + +#include + +class QShowEvent; +class QLabel; +class QDialogButtonBox; +class QPushButton; +class QFocusEvent; +class SourceTreeView; + +/** + * Place me at offset() to the left of the right edge of the sourcetree. + */ +class DLLEXPORT SourceTreePopupDialog : public QWidget +{ + Q_OBJECT +public: + explicit SourceTreePopupDialog( SourceTreeView* parent ); + + int offset() const { return 14; } + + void setMainText( const QString& text ); + void setOkButtonText( const QString& text ); + + bool resultValue() const { return m_result; } + +signals: + void result( bool accepted ); + +protected: + virtual void paintEvent( QPaintEvent* ); + virtual void focusOutEvent( QFocusEvent* ); + virtual void showEvent( QShowEvent* ); + +private slots: + void onAccepted(); + void onRejected(); + +private: + QString m_text; + bool m_result; + + QLabel* m_label; + QDialogButtonBox* m_buttons; +}; + +#endif diff --git a/src/sourcetree/SourceTreeView.cpp b/src/sourcetree/SourceTreeView.cpp index 55a97a338..577b0649c 100644 --- a/src/sourcetree/SourceTreeView.cpp +++ b/src/sourcetree/SourceTreeView.cpp @@ -51,6 +51,8 @@ #include "LatchManager.h" #include "utils/TomahawkUtilsGui.h" #include "utils/Logger.h" +#include +#include "widgets/SourceTreePopupDialog.h" using namespace Tomahawk; @@ -362,29 +364,48 @@ SourceTreeView::deletePlaylist( const QModelIndex& idxIn ) Q_ASSERT( false ); } - QMessageBox askDelete( QMessageBox::Question, tr( "Delete %1?", "playlist/station/..." ).arg( typeDesc ), - tr( "Would you like to delete the %1 \"%2\"?", "e.g. Would you like to delete the playlist named Foobar?" ) - .arg( typeDesc ).arg( idx.data().toString() ), - QMessageBox::Yes | QMessageBox::No, this ); + if ( m_popupDialog.isNull() ) + { + m_popupDialog = QWeakPointer< SourceTreePopupDialog >( new SourceTreePopupDialog( this ) ); + connect( m_popupDialog.data(), SIGNAL( result( bool ) ), this, SLOT( onDeletePlaylistResult( bool ) ) ); + } -#ifdef Q_OS_MAC - askDelete.setWindowModality( Qt::WindowModal ); -#endif + m_popupDialog.data()->setMainText( tr( "Would you like to delete the %1 \"%2\"?", "e.g. Would you like to delete the playlist named Foobar?" ) + .arg( typeDesc ).arg( idx.data().toString() ) ); + m_popupDialog.data()->setOkButtonText( tr( "Delete" ) ); + m_popupDialog.data()->setProperty( "idx", QVariant::fromValue< QModelIndex >( idx ) ); - int r = askDelete.exec(); - if ( r != QMessageBox::Yes ) + const QPoint rightCenter = viewport()->mapToGlobal( visualRect( idx ).topRight() + QPoint( 0, visualRect( idx ).height() / 2 ) ); + m_popupDialog.data()->move( rightCenter.x() - m_popupDialog.data()->offset(), rightCenter.y() - m_popupDialog.data()->sizeHint().height() / 2. ); + m_popupDialog.data()->show(); +} + + +void +SourceTreeView::onDeletePlaylistResult( bool result ) +{ + Q_ASSERT( !m_popupDialog.isNull() ); + + const QModelIndex idx = m_popupDialog.data()->property( "idx" ).value< QModelIndex >(); + Q_ASSERT( idx.isValid() ); + + if ( !result ) return; + SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( idx, SourcesModel::SourceTreeItemTypeRole ).toInt(); + if ( type == SourcesModel::StaticPlaylist ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( idx ); playlist_ptr playlist = item->playlist(); + qDebug() << "Doing delete of playlist:" << playlist->title(); Playlist::remove( playlist ); } else if ( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( idx ); dynplaylist_ptr playlist = item->dynPlaylist(); + qDebug() << "Doing delete of playlist:" << playlist->title(); DynamicPlaylist::remove( playlist ); } } diff --git a/src/sourcetree/SourceTreeView.h b/src/sourcetree/SourceTreeView.h index 775ecb62b..9959b01c3 100644 --- a/src/sourcetree/SourceTreeView.h +++ b/src/sourcetree/SourceTreeView.h @@ -26,6 +26,7 @@ #include #include +class SourceTreePopupDialog; class CollectionModel; class PlaylistModel; class SourcesModel; @@ -84,6 +85,8 @@ private slots: void onCustomContextMenu( const QPoint& pos ); void onSelectionChanged(); + void onDeletePlaylistResult( bool result ); + protected: void drawRow( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; @@ -106,6 +109,7 @@ private: QModelIndex m_contextMenuIndex; SourceDelegate* m_delegate; Tomahawk::LatchManager* m_latchManager; + QWeakPointer m_popupDialog; QMenu m_playlistMenu; QMenu m_roPlaylistMenu; @@ -115,7 +119,7 @@ private: bool m_dragging; QRect m_dropRect; QPersistentModelIndex m_dropIndex; - + QPersistentModelIndex m_selectedIndex; };