[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdepim/akonadi/libakonadi
From: Volker Krause <volker.krause () rwth-aachen ! de>
Date: 2006-09-17 9:47:03
Message-ID: 1158486423.404119.6844.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 585474 by vkrause:
Add DND support to the collection model.
It's now possible to drag eg. a message from KDE3's Kontact into Akonadi.
M +100 -5 collectionmodel.cpp
M +27 -0 collectionmodel.h
M +25 -2 collectionview.cpp
M +11 -0 collectionview.h
M +1 -1 tests/collectionbrowser.cpp
M +4 -1 tests/messagebrowser.cpp
--- trunk/KDE/kdepim/akonadi/libakonadi/collectionmodel.cpp #585473:585474
@@ -23,6 +23,7 @@
#include "collectionlistjob.h"
#include "collectionmodel.h"
#include "collectionrenamejob.h"
+#include "itemappendjob.h"
#include "jobqueue.h"
#include "monitor.h"
@@ -33,6 +34,7 @@
#include <QDebug>
#include <QHash>
+#include <QMimeData>
#include <QPixmap>
#include <QQueue>
@@ -49,6 +51,18 @@
QString editOldName;
Monitor* monitor;
JobQueue *queue;
+ QStringList mimeTypes;
+
+ void updateSupportedMimeTypes( Collection *col )
+ {
+ QList<QByteArray> l = col->contentTypes();
+ for ( QList<QByteArray>::ConstIterator it = l.constBegin(); it != \
l.constEnd(); ++it ) { + if ( (*it) == Collection::collectionMimeType() )
+ continue;
+ if ( !mimeTypes.contains( QString::fromLatin1( *it ) ) )
+ mimeTypes << QString::fromLatin1( *it );
+ }
+ }
};
PIM::CollectionModel::CollectionModel( QObject * parent ) :
@@ -262,6 +276,8 @@
foreach ( CollectionAttribute* attr, csjob->attributes() )
col->addAttribute( attr );
+ d->updateSupportedMimeTypes( col );
+
QModelIndex startIndex = indexForPath( path );
QModelIndex endIndex = indexForPath( path, columnCount( parent( startIndex ) ) \
- 1 ); emit dataChanged( startIndex, endIndex );
@@ -312,6 +328,8 @@
d->childCollections[ col->parent() ].append( col->path() );
}
+ d->updateSupportedMimeTypes( col );
+
// start a status job for every collection to get message counts, etc.
if ( col->type() != Collection::VirtualParent ) {
CollectionStatusJob* csjob = new CollectionStatusJob( col->path(), d->queue \
); @@ -350,12 +368,24 @@
Qt::ItemFlags PIM::CollectionModel::flags( const QModelIndex & index ) const
{
- if ( index.column() == 0 ) {
- Collection *col = static_cast<Collection*>( index.internalPointer() );
- if ( col->type() != Collection::VirtualParent && d->currentEdit == Private::None \
)
- return QAbstractItemModel::flags( index ) | Qt::ItemIsEditable;
+ Qt::ItemFlags flags = QAbstractItemModel::flags( index );
+
+ Collection *col = 0;
+ if ( index.isValid() ) {
+ col = static_cast<Collection*>( index.internalPointer() );
+ Q_ASSERT( col );
}
- return QAbstractItemModel::flags( index );
+
+ if ( col ) {
+ if ( col->type() != Collection::VirtualParent ) {
+ if ( d->currentEdit == Private::None && index.column() == 0 )
+ flags = flags | Qt::ItemIsEditable;
+ if ( col->type() != Collection::Virtual )
+ flags = flags | Qt::ItemIsDropEnabled;
+ }
+ }
+
+ return flags;
}
void PIM::CollectionModel::editDone( PIM::Job * job )
@@ -436,4 +466,69 @@
return QByteArray();
}
+Qt::DropActions PIM::CollectionModel::supportedDropActions() const
+{
+ return Qt::CopyAction; // | Qt::MoveAction;
+}
+
+QStringList PIM::CollectionModel::mimeTypes() const
+{
+ return d->mimeTypes;
+}
+
+bool PIM::CollectionModel::supportsContentType(const QModelIndex & index, const \
QStringList & contentTypes) +{
+ if ( !index.isValid() )
+ return false;
+ Collection *col = static_cast<Collection*>( index.internalPointer() );
+ Q_ASSERT( col );
+ QList<QByteArray> ct = col->contentTypes();
+ foreach ( QByteArray a, ct ) {
+ if ( contentTypes.contains( QString::fromLatin1( a ) ) )
+ return true;
+ }
+ return false;
+}
+
+bool PIM::CollectionModel::dropMimeData(const QMimeData * data, Qt::DropAction \
action, int row, int column, const QModelIndex & parent) +{
+ if ( !(action & supportedDropActions()) )
+ return false;
+
+ // handle drops onto items as well as drops between items
+ QModelIndex idx;
+ if ( row >= 0 && column >= 0 )
+ idx = index( row, column, parent );
+ else
+ idx = parent;
+
+ if ( !idx.isValid() )
+ return false;
+
+ // find a type the target collection supports
+ foreach ( QString type, data->formats() ) {
+ if ( !supportsContentType( idx, QStringList( type ) ) )
+ continue;
+ QByteArray path = pathForIndex( idx );
+ QByteArray item = data->data( type );
+ // HACK for some unknown reason the data is sometimes 0-terminated...
+ if ( !item.isEmpty() && item.at( item.size() - 1 ) == 0 )
+ item.resize( item.size() - 1 );
+ ItemAppendJob *job = new ItemAppendJob( path, item, type.toLatin1(), d->queue );
+ d->queue->addJob( job );
+ return true;
+ }
+
+ return false;
+}
+
+void PIM::CollectionModel::appendDone(PIM::Job * job)
+{
+ if ( job->error() ) {
+ kWarning() << "Append failed: " << job->errorText() << endl;
+ // TODO: error handling
+ }
+ job->deleteLater();
+}
+
#include "collectionmodel.moc"
--- trunk/KDE/kdepim/akonadi/libakonadi/collectionmodel.h #585473:585474
@@ -94,6 +94,21 @@
Qt::ItemFlags flags( const QModelIndex &index ) const;
/**
+ Reimplemented.
+ */
+ virtual Qt::DropActions supportedDropActions() const;
+
+ /**
+ Reimplemented.
+ */
+ virtual QStringList mimeTypes() const;
+
+ /**
+ Reimplemented.
+ */
+ virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int \
row, int column, const QModelIndex &parent ); +
+ /**
Add a new collection to the model and try to save it into the backend.
@param parent The parent model index.
@param name The name of the new collection.
@@ -113,6 +128,13 @@
*/
QByteArray pathForIndex( const QModelIndex &index ) const;
+ /**
+ Returns wether the specified collection supports <em>any</em> of the given \
mime-types. + @param index The model index.
+ @param contentTypes The content types to check.
+ */
+ bool supportsContentType( const QModelIndex &index, const QStringList \
&contentTypes ); +
private:
/**
Helper function to generate a model index for a given collection reference.
@@ -152,6 +174,11 @@
*/
void editDone( PIM::Job *job );
+ /**
+ Connected to item append jobs used for DND.
+ */
+ void appendDone( PIM::Job *job );
+
private:
class Private;
Private *d;
--- trunk/KDE/kdepim/akonadi/libakonadi/collectionview.cpp #585473:585474
@@ -23,6 +23,7 @@
#include <klocale.h>
#include <QDebug>
+#include <QDragMoveEvent>
#include <QHeaderView>
#include <QInputDialog>
#include <QSortFilterProxyModel>
@@ -49,6 +50,9 @@
setSortingEnabled( true );
setEditTriggers( QAbstractItemView::EditKeyPressed );
+ setAcceptDrops( true );
+ setDropIndicatorShown( true );
+ setDragDropMode( DropOnly );
// temporary for testing
connect( this, SIGNAL(doubleClicked(QModelIndex)), \
SLOT(createCollection(QModelIndex)) ); @@ -70,13 +74,32 @@
void PIM::CollectionView::createCollection( const QModelIndex & parent )
{
- if ( !d->model->canCreateCollection( parent ) )
+ QModelIndex index =sourceIndex( parent );
+ if ( !d->model->canCreateCollection( index ) )
return;
QString name = QInputDialog::getText( this, i18n("New Folder"), i18n("Name") );
if ( name.isEmpty() )
return;
- if ( !d->model->createCollection( parent, name ) )
+ if ( !d->model->createCollection( index, name ) )
qWarning() << "Collection creation failed immediately!";
}
+void PIM::CollectionView::dragMoveEvent(QDragMoveEvent * event)
+{
+ QModelIndex index = sourceIndex( indexAt( event->pos() ) );
+ QStringList mimeTypes = event->mimeData()->formats();
+ if ( !d->model->supportsContentType( index, mimeTypes ) ) {
+ event->setDropAction( Qt::IgnoreAction );
+ return;
+ }
+ QTreeView::dragMoveEvent( event );
+}
+
+QModelIndex PIM::CollectionView::sourceIndex(const QModelIndex & index)
+{
+ if ( index.model() == d->filterModel )
+ return d->filterModel->mapToSource( index );
+ return index;
+}
+
#include "collectionview.moc"
--- trunk/KDE/kdepim/akonadi/libakonadi/collectionview.h #585473:585474
@@ -23,6 +23,8 @@
#include <QTreeView>
#include <kdepim_export.h>
+class QDragMoveEvent;
+
namespace PIM {
/**
@@ -56,6 +58,15 @@
*/
void createCollection( const QModelIndex &index );
+ protected:
+ virtual void dragMoveEvent( QDragMoveEvent *event );
+
+ /**
+ Translates a QModelIndex from the sort proxy model into a QModelIndex
+ from the CollectionModel if necessary.
+ */
+ QModelIndex sourceIndex( const QModelIndex &index );
+
private:
class Private;
Private *d;
--- trunk/KDE/kdepim/akonadi/libakonadi/tests/collectionbrowser.cpp #585473:585474
@@ -42,7 +42,7 @@
void PIM::CollectionBrowser::slotItemActivated( const QModelIndex & index )
{
- QByteArray path = model->pathForIndex( index );
+ QByteArray path = model->pathForIndex( sourceIndex( index ) );
if ( path.isNull() )
return;
MessageBrowser *mb = new MessageBrowser( path );
--- trunk/KDE/kdepim/akonadi/libakonadi/tests/messagebrowser.cpp #585473:585474
@@ -49,10 +49,13 @@
void PIM::MessageBrowser::slotFetchDone( PIM::Job * job )
{
+ MessageFetchJob *fetch = static_cast<MessageFetchJob*>( job );
if ( job->error() ) {
qWarning() << "Message fetch failed: " << job->errorText();
+ } else if ( fetch->messages().isEmpty() ) {
+ qWarning() << "No message found!";
} else {
- Message *msg = static_cast<MessageFetchJob*>( job )->messages().first();
+ Message *msg = fetch->messages().first();
QTextEdit *te = new QTextEdit();
te->setReadOnly( true );
te->setPlainText( msg->mime()->encodedContent() );
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic