File indexing completed on 2024-05-19 04:48:39
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * Copyright (c) 2010 Bart Cerneels <bart.cerneels@kde.org> * 0004 * Copyright (c) 2011 Ralf Engels <ralf-engels@gmx.de> * 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 #define DEBUG_PREFIX "DynamicView" 0020 0021 #include "DynamicView.h" 0022 #include "DynamicBiasDelegate.h" 0023 #include "DynamicBiasDialog.h" 0024 0025 #include "core/support/Debug.h" 0026 #include "dynamic/Bias.h" 0027 #include "dynamic/DynamicModel.h" 0028 #include "dynamic/DynamicPlaylist.h" 0029 #include "dynamic/biases/SearchQueryBias.h" 0030 #include "playlist/PlaylistActions.h" 0031 0032 #include "PopupDropperFactory.h" 0033 // #include "context/popupdropper/libpud/PopupDropperItem.h" 0034 // #include "context/popupdropper/libpud/PopupDropper.h" 0035 0036 #include "PaletteHandler.h" 0037 0038 #include <QAction> 0039 #include <QMenu> 0040 0041 #include <QKeyEvent> 0042 #include <QMouseEvent> 0043 #include <QModelIndex> 0044 #include <QToolTip> 0045 0046 PlaylistBrowserNS::DynamicView::DynamicView( QWidget *parent ) 0047 : Amarok::PrettyTreeView( parent ) 0048 { 0049 DEBUG_BLOCK 0050 setHeaderHidden( true ); 0051 setSelectionMode( QAbstractItemView::SingleSelection ); 0052 setModel( Dynamic::DynamicModel::instance() ); 0053 setItemDelegate( new PlaylistBrowserNS::DynamicBiasDelegate(this) ); 0054 0055 setSelectionBehavior( QAbstractItemView::SelectItems ); 0056 setDragDropMode( QAbstractItemView::DragDrop /*| QAbstractItemView::InternalMove*/ ); 0057 setDragEnabled( true ); 0058 setAcceptDrops( true ); 0059 setDropIndicatorShown( true ); 0060 0061 setEditTriggers( QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed ); 0062 0063 // -- expanding the playlist should expand the whole tree 0064 connect( this, &DynamicView::expanded, 0065 this, &DynamicView::expandRecursive ); 0066 connect( this, &DynamicView::collapsed, 0067 this, &DynamicView::collapseRecursive ); 0068 } 0069 0070 PlaylistBrowserNS::DynamicView::~DynamicView() 0071 { 0072 } 0073 0074 void 0075 PlaylistBrowserNS::DynamicView::addPlaylist() 0076 { 0077 DEBUG_BLOCK; 0078 QModelIndex newIndex = Dynamic::DynamicModel::instance()->newPlaylist(); 0079 selectionModel()->select( newIndex, QItemSelectionModel::ClearAndSelect ); 0080 } 0081 0082 void 0083 PlaylistBrowserNS::DynamicView::addToSelected() 0084 { 0085 DEBUG_BLOCK; 0086 QModelIndexList indexes = selectionModel()->selectedIndexes(); 0087 if( indexes.isEmpty() ) 0088 return; 0089 0090 QModelIndex newIndex = Dynamic::DynamicModel::instance()->insertBias( 0, indexes.first(), Dynamic::BiasPtr( new Dynamic::SearchQueryBias() ) ); 0091 selectionModel()->select( newIndex, QItemSelectionModel::ClearAndSelect ); 0092 } 0093 0094 void 0095 PlaylistBrowserNS::DynamicView::cloneSelected() 0096 { 0097 DEBUG_BLOCK; 0098 QModelIndexList indexes = selectionModel()->selectedIndexes(); 0099 if( indexes.isEmpty() ) 0100 return; 0101 0102 QModelIndex newIndex = Dynamic::DynamicModel::instance()->cloneAt( indexes.first() ); 0103 selectionModel()->select( newIndex, QItemSelectionModel::ClearAndSelect ); 0104 } 0105 0106 void 0107 PlaylistBrowserNS::DynamicView::editSelected() 0108 { 0109 DEBUG_BLOCK; 0110 0111 QModelIndexList indexes = selectionModel()->selectedIndexes(); 0112 if( indexes.isEmpty() ) 0113 return; 0114 0115 QVariant v = model()->data( indexes.first(), Dynamic::DynamicModel::PlaylistRole ); 0116 if( v.isValid() ) 0117 { 0118 edit( indexes.first() ); // call the normal editor 0119 return; 0120 } 0121 0122 v = model()->data( indexes.first(), Dynamic::DynamicModel::BiasRole ); 0123 if( v.isValid() ) 0124 { 0125 Dynamic::AbstractBias* bias = qobject_cast<Dynamic::AbstractBias*>(v.value<QObject*>() ); 0126 PlaylistBrowserNS::BiasDialog dialog( Dynamic::BiasPtr(bias), this); 0127 dialog.exec(); 0128 return; 0129 } 0130 } 0131 0132 void 0133 PlaylistBrowserNS::DynamicView::removeSelected() 0134 { 0135 DEBUG_BLOCK; 0136 0137 QModelIndexList indexes = selectionModel()->selectedIndexes(); 0138 0139 if( indexes.isEmpty() ) 0140 return; 0141 0142 Dynamic::DynamicModel::instance()->removeAt( indexes.first() ); 0143 } 0144 0145 void 0146 PlaylistBrowserNS::DynamicView::expandRecursive(const QModelIndex &index) 0147 { 0148 for( int i = 0; i < index.model()->rowCount( index ); i++ ) 0149 expand( index.model()->index( i, 0, index ) ); 0150 } 0151 0152 void 0153 PlaylistBrowserNS::DynamicView::collapseRecursive(const QModelIndex &index) 0154 { 0155 for( int i = 0; i < index.model()->rowCount( index ); i++ ) 0156 collapse( index.model()->index( i, 0, index ) ); 0157 } 0158 0159 0160 void 0161 PlaylistBrowserNS::DynamicView::keyPressEvent( QKeyEvent *event ) 0162 { 0163 switch( event->key() ) 0164 { 0165 case Qt::Key_Delete: 0166 removeSelected(); 0167 return; 0168 case Qt::Key_Enter: 0169 case Qt::Key_Return: 0170 editSelected(); 0171 return; 0172 } 0173 Amarok::PrettyTreeView::keyPressEvent( event ); 0174 } 0175 0176 void 0177 PlaylistBrowserNS::DynamicView::mouseDoubleClickEvent( QMouseEvent *event ) 0178 { 0179 QModelIndex index = indexAt( event->pos() ); 0180 if( index.isValid() ) 0181 { 0182 // if the click was on a playlist 0183 QVariant v = model()->data( index, Dynamic::DynamicModel::PlaylistRole ); 0184 if( v.isValid() ) 0185 { 0186 Dynamic::DynamicModel *model = Dynamic::DynamicModel::instance(); 0187 model->setActivePlaylist( model->playlistIndex( qobject_cast<Dynamic::DynamicPlaylist*>(v.value<QObject*>() ) ) ); 0188 The::playlistActions()->enableDynamicMode( true ); 0189 event->accept(); 0190 return; 0191 } 0192 0193 // if the click was on a bias 0194 v = model()->data( index, Dynamic::DynamicModel::BiasRole ); 0195 if( v.isValid() ) 0196 { 0197 editSelected(); 0198 event->accept(); 0199 return; 0200 } 0201 } 0202 0203 Amarok::PrettyTreeView::mouseDoubleClickEvent( event ); 0204 } 0205 0206 void 0207 PlaylistBrowserNS::DynamicView::contextMenuEvent( QContextMenuEvent *event ) 0208 { 0209 QModelIndex index = indexAt( event->pos() ); 0210 if( !index.isValid() ) 0211 return; 0212 0213 QList<QAction*> actions; 0214 0215 // if the click was on a playlist 0216 QVariant v = model()->data( index, Dynamic::DynamicModel::PlaylistRole ); 0217 if( v.isValid() ) 0218 { 0219 Dynamic::DynamicPlaylist* playlist = qobject_cast<Dynamic::DynamicPlaylist*>(v.value<QObject*>() ); 0220 Q_UNUSED( playlist ); 0221 QAction* action; 0222 0223 action = new QAction( QIcon::fromTheme( QStringLiteral("document-properties-amarok") ), i18n( "&Rename playlist" ), this ); 0224 connect( action, &QAction::triggered, this, &DynamicView::editSelected ); 0225 actions.append( action ); 0226 0227 action = new QAction( QIcon::fromTheme( QStringLiteral("document-new") ), i18n( "&Add new Bias" ), this ); 0228 connect( action, &QAction::triggered, this, &DynamicView::addToSelected ); 0229 actions.append( action ); 0230 0231 action = new QAction( QIcon::fromTheme( QStringLiteral("edit-copy") ), i18n( "&Clone Playlist" ), this ); 0232 connect( action, &QAction::triggered, this, &DynamicView::cloneSelected ); 0233 actions.append( action ); 0234 0235 action = new QAction( QIcon::fromTheme( QStringLiteral("edit-delete") ), i18n( "&Delete playlist" ), this ); 0236 connect( action, &QAction::triggered, this, &DynamicView::removeSelected ); 0237 actions.append( action ); 0238 } 0239 0240 // if the click was on a bias 0241 v = model()->data( index, Dynamic::DynamicModel::BiasRole ); 0242 if( v.isValid() ) 0243 { 0244 Dynamic::AbstractBias* bias = qobject_cast<Dynamic::AbstractBias*>(v.value<QObject*>() ); 0245 Q_UNUSED( bias ); 0246 Dynamic::AndBias* aBias = qobject_cast<Dynamic::AndBias*>(v.value<QObject*>() ); 0247 QAction* action; 0248 0249 action = new QAction( QIcon::fromTheme( QStringLiteral("document-properties-amarok") ), i18n( "&Edit bias..." ), this ); 0250 connect( action, &QAction::triggered, this, &DynamicView::editSelected ); 0251 actions.append( action ); 0252 0253 action = new QAction( QIcon::fromTheme( QStringLiteral("edit-copy") ), i18n( "&Clone bias" ), this ); 0254 connect( action, &QAction::triggered, this, &DynamicView::cloneSelected ); 0255 actions.append( action ); 0256 0257 // don't allow deleting a top bias unless it'a an and-bias containing at least one 0258 // other bias 0259 QModelIndex parentIndex = index.parent(); 0260 QVariant parentV = model()->data( parentIndex, Dynamic::DynamicModel::PlaylistRole ); 0261 if( !parentV.isValid() || (aBias && aBias->biases().count() > 0) ) 0262 { 0263 action = new QAction( QIcon::fromTheme( QStringLiteral("edit-delete") ), i18n( "&Delete bias" ), this ); 0264 connect( action, &QAction::triggered, this, &DynamicView::removeSelected ); 0265 actions.append( action ); 0266 } 0267 0268 if( aBias ) 0269 { 0270 action = new QAction( QIcon::fromTheme( QStringLiteral("document-new") ), i18n( "&Add new bias" ), this ); 0271 connect( action, &QAction::triggered, this, &DynamicView::addToSelected ); 0272 actions.append( action ); 0273 } 0274 } 0275 0276 if( actions.isEmpty() ) 0277 return; 0278 0279 QMenu menu; 0280 foreach( QAction *action, actions ) 0281 { 0282 if( action ) 0283 menu.addAction( action ); 0284 } 0285 0286 menu.exec( mapToGlobal( event->pos() ) ); 0287 } 0288