File indexing completed on 2024-05-19 04:50:16
0001 /**************************************************************************************** 0002 * Copyright (c) 2009 Casey Link <unnamedrambler@gmail.com> * 0003 * Copyright (c) 2005-2007 Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> * 0004 * Copyright (c) 2005-2007 Max Howell, Last.fm Ltd <max@last.fm> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #include "LastFmTreeView.h" 0020 0021 #include "PopupDropperFactory.h" 0022 #include "context/ContextView.h" 0023 #include "core/meta/Meta.h" 0024 #include "core/support/Debug.h" 0025 #include "services/lastfm/LastFmTreeModel.h" // FIXME just for enums 0026 0027 #include <QContextMenuEvent> 0028 #include <QHeaderView> 0029 #include <QMenu> 0030 0031 #include <KLocalizedString> 0032 0033 #include <algorithm> 0034 0035 0036 LastFmTreeView::LastFmTreeView ( QWidget* parent ) 0037 : Amarok::PrettyTreeView ( parent ) 0038 , m_timer ( nullptr ) 0039 , m_pd( nullptr ) 0040 , m_appendAction ( nullptr ) 0041 , m_loadAction ( nullptr ) 0042 , m_dragMutex() 0043 , m_ongoingDrag( false ) 0044 { 0045 // connect ( this, SIGNAL (activated(QModelIndex)), SLOT (onActivated(QModelIndex)) ); 0046 0047 header()->hide(); 0048 // setRootIsDecorated( false ); 0049 } 0050 0051 0052 LastFmTreeView::~LastFmTreeView() 0053 {} 0054 0055 void 0056 LastFmTreeView::contextMenuEvent ( QContextMenuEvent* event ) 0057 { 0058 m_currentItems.clear(); 0059 foreach ( const QModelIndex &i, selectedIndexes() ) 0060 { 0061 if ( i.isValid() ) 0062 m_currentItems << i; 0063 } 0064 if ( m_currentItems.isEmpty() ) 0065 return; 0066 QAction separator ( this ); 0067 separator.setSeparator ( true ); 0068 0069 QActionList actions = createBasicActions( m_currentItems ); 0070 0071 actions += &separator; 0072 QMenu menu; 0073 foreach ( QAction * action, actions ) 0074 menu.addAction ( action ); 0075 0076 menu.exec ( event->globalPos() ); 0077 } 0078 0079 QActionList LastFmTreeView::createBasicActions( const QModelIndexList & indices ) 0080 { 0081 Q_UNUSED( indices ) 0082 QActionList actions; 0083 QModelIndex index = currentIndex(); 0084 QVariant type = model()->data(index, LastFm::TypeRole); 0085 switch ( type.toInt() ) 0086 { 0087 case LastFm::MyRecommendations: 0088 case LastFm::PersonalRadio: 0089 case LastFm::MixRadio: 0090 case LastFm::FriendsChild: 0091 case LastFm::MyTagsChild: 0092 case LastFm::ArtistsChild: 0093 case LastFm::UserChildPersonal: 0094 { 0095 if ( m_appendAction == nullptr ) 0096 { 0097 m_appendAction = new QAction ( QIcon::fromTheme( "media-track-add-amarok" ), i18n ( "&Add to Playlist" ), this ); 0098 m_appendAction->setProperty( "popupdropper_svg_id", "append" ); 0099 connect ( m_appendAction, &QAction::triggered, this, &LastFmTreeView::slotAppendChildTracks ); 0100 } 0101 0102 actions.append ( m_appendAction ); 0103 0104 if ( m_loadAction == nullptr ) 0105 { 0106 m_loadAction = new QAction ( QIcon::fromTheme( "folder-open" ), i18nc ( "Replace the currently loaded tracks with these", "&Replace Playlist" ), this ); 0107 m_appendAction->setProperty( "popupdropper_svg_id", "load" ); 0108 connect ( m_loadAction, &QAction::triggered, this, &LastFmTreeView::slotReplacePlaylistByChildTracks ); 0109 } 0110 actions.append ( m_loadAction ); 0111 } 0112 default: 0113 break; 0114 } 0115 return actions; 0116 } 0117 0118 void LastFmTreeView::mouseDoubleClickEvent( QMouseEvent *event ) 0119 { 0120 QModelIndex index; 0121 index = indexAt( event->pos() ); 0122 0123 if( index.isValid() && index.internalPointer() ) 0124 { 0125 playChildTracks( index, Playlist::OnDoubleClickOnSelectedItems ); 0126 } 0127 } 0128 0129 void 0130 LastFmTreeView::startDrag(Qt::DropActions supportedActions) 0131 { 0132 DEBUG_BLOCK 0133 0134 //setSelectionMode( QAbstractItemView::NoSelection ); 0135 0136 // When a parent item is dragged, startDrag() is called a bunch of times. Here we prevent that: 0137 m_dragMutex.lock(); 0138 if( m_ongoingDrag ) 0139 { 0140 m_dragMutex.unlock(); 0141 return; 0142 } 0143 m_ongoingDrag = true; 0144 m_dragMutex.unlock(); 0145 0146 if( !m_pd ) 0147 m_pd = The::popupDropperFactory()->createPopupDropper( Context::ContextView::self() ); 0148 0149 if( m_pd && m_pd->isHidden() ) 0150 { 0151 0152 QModelIndexList indices = selectedIndexes(); 0153 0154 QActionList actions = createBasicActions( indices ); 0155 0156 QFont font; 0157 font.setPointSize( 16 ); 0158 font.setBold( true ); 0159 0160 foreach( QAction * action, actions ) 0161 m_pd->addItem( The::popupDropperFactory()->createItem( action ) ); 0162 0163 0164 m_currentItems.clear(); 0165 foreach( const QModelIndex &index, indices ) 0166 { 0167 if( index.isValid() && index.internalPointer() ) 0168 m_currentItems << index; 0169 } 0170 0171 PopupDropperItem* subItem; 0172 0173 PopupDropper * morePud = nullptr; 0174 if ( actions.count() > 1 ) 0175 { 0176 morePud = The::popupDropperFactory()->createPopupDropper( nullptr, true ); 0177 0178 foreach( QAction * action, actions ) 0179 morePud->addItem( The::popupDropperFactory()->createItem( action ) ); 0180 } 0181 else 0182 m_pd->addItem( The::popupDropperFactory()->createItem( actions[0] ) ); 0183 0184 //TODO: Keep bugging i18n team about problems with 3 dots 0185 if ( actions.count() > 1 ) 0186 { 0187 subItem = m_pd->addSubmenu( &morePud, i18n( "More..." ) ); 0188 The::popupDropperFactory()->adjustItem( subItem ); 0189 } 0190 0191 m_pd->show(); 0192 } 0193 0194 QTreeView::startDrag( supportedActions ); 0195 debug() << "After the drag!"; 0196 0197 if( m_pd ) 0198 { 0199 debug() << "clearing PUD"; 0200 connect( m_pd, &PopupDropper::fadeHideFinished, m_pd, &PopupDropper::clear ); 0201 m_pd->hide(); 0202 } 0203 0204 m_dragMutex.lock(); 0205 m_ongoingDrag = false; 0206 m_dragMutex.unlock(); 0207 } 0208 0209 void 0210 LastFmTreeView::slotReplacePlaylistByChildTracks() 0211 { 0212 playChildTracks( m_currentItems, Playlist::OnReplacePlaylistAction ); 0213 } 0214 0215 void 0216 LastFmTreeView::slotAppendChildTracks() 0217 { 0218 playChildTracks( m_currentItems, Playlist::OnAppendToPlaylistAction ); 0219 } 0220 0221 void 0222 LastFmTreeView::playChildTracks( const QModelIndex &item, Playlist::AddOptions insertMode) 0223 { 0224 QModelIndexList items; 0225 items << item; 0226 0227 playChildTracks( items, insertMode ); 0228 } 0229 void 0230 LastFmTreeView::playChildTracks ( const QModelIndexList &items, Playlist::AddOptions insertMode ) 0231 { 0232 debug() << "LASTFM current items : " << items.size(); 0233 Meta::TrackList list; 0234 foreach ( const QModelIndex &item, items ) 0235 { 0236 Meta::TrackPtr track = model()->data(item, LastFm::TrackRole).value< Meta::TrackPtr >(); 0237 if ( track ) 0238 list << track; 0239 } 0240 std::stable_sort ( list.begin(), list.end(), Meta::Track::lessThan ); 0241 The::playlistController()->insertOptioned( list, insertMode ); 0242 }