• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

dragdropmanager.cpp

00001 /*
00002     Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "dragdropmanager_p.h"
00021 
00022 #include <QtGui/QApplication>
00023 #include <QtGui/QDropEvent>
00024 #include <QtGui/QMenu>
00025 
00026 #include <KDE/KIcon>
00027 #include <KDE/KLocale>
00028 #include <KDE/KUrl>
00029 
00030 #include "akonadi/collection.h"
00031 #include "akonadi/entitytreemodel.h"
00032 
00033 using namespace Akonadi;
00034 
00035 DragDropManager::DragDropManager( QAbstractItemView *view )
00036     : m_view( view )
00037 {
00038 }
00039 
00040 Collection DragDropManager::currentDropTarget( QDropEvent *event ) const
00041 {
00042   const QModelIndex index = m_view->indexAt( event->pos() );
00043 
00044   Collection collection = m_view->model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00045   if ( !collection.isValid() ) {
00046     const Item item = m_view->model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00047     if ( item.isValid() )
00048       collection = m_view->model()->data( index.parent(), EntityTreeModel::CollectionRole ).value<Collection>();
00049   }
00050 
00051   return collection;
00052 }
00053 
00054 bool DragDropManager::dropAllowed( QDragMoveEvent *event ) const
00055 {
00056   // Check if the collection under the cursor accepts this data type
00057   const Collection targetCollection = currentDropTarget( event );
00058   if ( targetCollection.isValid() ) {
00059     const QStringList supportedContentTypes = targetCollection.contentMimeTypes();
00060 
00061     const QMimeData *data = event->mimeData();
00062     const KUrl::List urls = KUrl::List::fromMimeData( data );
00063     foreach ( const KUrl &url, urls ) {
00064       const Collection collection = Collection::fromUrl( url );
00065       if ( collection.isValid() ) {
00066         if ( !supportedContentTypes.contains( Collection::mimeType() ) )
00067           break;
00068 
00069         // Check if we don't try to drop on one of the children
00070         if ( hasAncestor( m_view->indexAt( event->pos() ), collection.id() ) )
00071           break;
00072       } else { // This is an item.
00073         const QString type = url.queryItems()[ QString::fromLatin1( "type" ) ];
00074         if ( !supportedContentTypes.contains( type ) )
00075           break;
00076       }
00077 
00078       return true;
00079     }
00080   }
00081 
00082   return false;
00083 }
00084 
00085 bool DragDropManager::hasAncestor( const QModelIndex &_index, Collection::Id parentId ) const
00086 {
00087   QModelIndex index( _index );
00088   while ( index.isValid() ) {
00089     if ( m_view->model()->data( index, EntityTreeModel::CollectionIdRole ).toLongLong() == parentId )
00090       return true;
00091 
00092     index = index.parent();
00093   }
00094 
00095   return false;
00096 }
00097 
00098 bool DragDropManager::processDropEvent( QDropEvent *event )
00099 {
00100   const Collection targetCollection = currentDropTarget( event );
00101   if ( !targetCollection.isValid() )
00102     return false;
00103 
00104   int actionCount = 0;
00105   Qt::DropAction defaultAction;
00106   // TODO check if the source supports moving
00107 
00108   bool moveAllowed, copyAllowed, linkAllowed;
00109   moveAllowed = copyAllowed = linkAllowed = false;
00110 
00111   if ( (targetCollection.rights() & (Collection::CanCreateCollection | Collection::CanCreateItem))
00112         && (event->possibleActions() & Qt::MoveAction) ) {
00113     moveAllowed = true;
00114   }
00115 
00116   if ( (targetCollection.rights() & (Collection::CanCreateCollection | Collection::CanCreateItem))
00117         && (event->possibleActions() & Qt::CopyAction) ) {
00118     copyAllowed = true;
00119   }
00120 
00121   if ( (targetCollection.rights() & Collection::CanLinkItem) && (event->possibleActions() & Qt::LinkAction) ) {
00122     linkAllowed = true;
00123   }
00124 
00125   if ( !moveAllowed && !copyAllowed && !linkAllowed ) {
00126     kDebug() << "Cannot drop here:" << event->possibleActions() << m_view->model()->supportedDragActions() << m_view->model()->supportedDropActions();
00127     return false;
00128   }
00129 
00130   // first check whether the user pressed a modifier key to select a specific action
00131   if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) &&
00132        (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
00133     if ( linkAllowed ) {
00134       defaultAction = Qt::LinkAction;
00135       actionCount = 1;
00136     } else
00137       return false;
00138   } else if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) ) {
00139     if ( copyAllowed ) {
00140       defaultAction = Qt::CopyAction;
00141       actionCount = 1;
00142     } else
00143       return false;
00144   } else if ( (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
00145     if ( moveAllowed ) {
00146       defaultAction = Qt::MoveAction;
00147       actionCount = 1;
00148     } else
00149       return false;
00150   }
00151 
00152   if ( actionCount == 1 ) {
00153     kDebug() << "Selecting drop action" << defaultAction << ", there are no other possibilities";
00154     event->setDropAction( defaultAction );
00155     return true;
00156   }
00157 
00158   // otherwise show up a menu to allow the user to select an action
00159   QMenu popup( m_view );
00160   QAction* moveDropAction = 0;
00161   QAction* copyDropAction = 0;
00162   QAction* linkAction = 0;
00163   QString sequence;
00164 
00165   if ( moveAllowed ) {
00166     sequence = QKeySequence( Qt::ShiftModifier ).toString();
00167     sequence.chop( 1 ); // chop superfluous '+'
00168     moveDropAction = popup.addAction( KIcon( QString::fromLatin1( "go-jump" ) ), i18n( "&Move Here" ) + QLatin1Char( '\t' ) + sequence );
00169   }
00170 
00171   if ( copyAllowed ) {
00172     sequence = QKeySequence( Qt::ControlModifier ).toString();
00173     sequence.chop( 1 ); // chop superfluous '+'
00174     copyDropAction = popup.addAction( KIcon( QString::fromLatin1( "edit-copy" ) ), i18n( "&Copy Here" ) + QLatin1Char( '\t' ) + sequence );
00175   }
00176 
00177   if ( linkAllowed ) {
00178     sequence = QKeySequence( Qt::ControlModifier + Qt::ShiftModifier ).toString();
00179     sequence.chop( 1 ); // chop superfluous '+'
00180     linkAction = popup.addAction( KIcon( QLatin1String( "edit-link" ) ), i18n( "&Link Here" ) + QLatin1Char( '\t' ) + sequence );
00181   }
00182 
00183   popup.addSeparator();
00184   popup.addAction( KIcon( QString::fromLatin1( "process-stop" ) ), i18n( "C&ancel" ) + QLatin1Char( '\t' ) + QKeySequence( Qt::Key_Escape ).toString() );
00185 
00186   QAction *activatedAction = popup.exec( QCursor::pos() );
00187 
00188   if ( !activatedAction ) {
00189     return false;
00190   } else if ( activatedAction == moveDropAction ) {
00191     event->setDropAction( Qt::MoveAction );
00192   } else if ( activatedAction == copyDropAction ) {
00193     event->setDropAction( Qt::CopyAction );
00194   } else if ( activatedAction == linkAction ) {
00195     event->setDropAction( Qt::LinkAction );
00196   } else {
00197     return false;
00198   }
00199 
00200   return true;
00201 }
00202 
00203 void DragDropManager::startDrag( Qt::DropActions supportedActions )
00204 {
00205   QModelIndexList indexes;
00206   bool sourceDeletable = true;
00207   foreach ( const QModelIndex &index, m_view->selectionModel()->selectedRows() ) {
00208     if ( !m_view->model()->flags( index ) & Qt::ItemIsDragEnabled )
00209       continue;
00210 
00211     if ( sourceDeletable ) {
00212       Collection source = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
00213       if ( !source.isValid() ) {
00214         // index points to an item
00215         source = index.data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
00216         sourceDeletable = source.rights() & Collection::CanDeleteItem;
00217       } else {
00218         // index points to a collection
00219         sourceDeletable = source.rights() & Collection::CanDeleteCollection;
00220       }
00221     }
00222 
00223     indexes.append( index );
00224   }
00225 
00226   if ( indexes.isEmpty() )
00227     return;
00228 
00229   QMimeData *mimeData = m_view->model()->mimeData( indexes );
00230   if ( !mimeData )
00231     return;
00232 
00233   QDrag *drag = new QDrag( m_view );
00234   drag->setMimeData( mimeData );
00235   if ( indexes.size() > 1 ) {
00236     drag->setPixmap( KIcon( QLatin1String( "document-multiple" ) ).pixmap( QSize( 22, 22 ) ) );
00237   } else {
00238     QPixmap pixmap = indexes.first().data( Qt::DecorationRole ).value<QIcon>().pixmap( QSize( 22, 22 ) );
00239     if ( pixmap.isNull() )
00240       pixmap = KIcon( QLatin1String( "text-plain" ) ).pixmap( QSize( 22, 22 ) );
00241     drag->setPixmap( pixmap );
00242   }
00243 
00244   if ( !sourceDeletable )
00245     supportedActions &= ~Qt::MoveAction;
00246 
00247   Qt::DropAction defaultAction = Qt::IgnoreAction;
00248   if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) &&
00249        (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
00250     defaultAction = Qt::LinkAction;
00251   } else if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) ) {
00252     defaultAction = Qt::CopyAction;
00253   } else if ( (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
00254     defaultAction = Qt::MoveAction;
00255   }
00256 
00257   drag->exec( supportedActions, defaultAction );
00258 }

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal