~ubuntu-branches/ubuntu/karmic/kdepim/karmic-backports

« back to all changes in this revision

Viewing changes to akonadi/akonadi_next/entitytreeview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2009-07-10 06:34:50 UTC
  • mfrom: (1.1.40 upstream)
  • Revision ID: james.westby@ubuntu.com-20090710063450-neojgew2fh0n3y0u
Tags: 4:4.2.96-0ubuntu1
* New upstream release
* Bump kde build-deps to 4.2.96

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
3
 
    Copyright (c) 2008 Stephen Kelly <steveire@gmail.com>
4
 
 
5
 
    This library is free software; you can redistribute it and/or modify it
6
 
    under the terms of the GNU Library General Public License as published by
7
 
    the Free Software Foundation; either version 2 of the License, or (at your
8
 
    option) any later version.
9
 
 
10
 
    This library is distributed in the hope that it will be useful, but WITHOUT
11
 
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
13
 
    License for more details.
14
 
 
15
 
    You should have received a copy of the GNU Library General Public License
16
 
    along with this library; see the file COPYING.LIB.  If not, write to the
17
 
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
 
    02110-1301, USA.
19
 
*/
20
 
 
21
 
#include "entitytreeview.h"
22
 
 
23
 
#include <QtCore/QDebug>
24
 
#include <QtCore/QTimer>
25
 
#include <QtGui/QApplication>
26
 
#include <QtGui/QDragMoveEvent>
27
 
#include <QtGui/QHeaderView>
28
 
#include <QtGui/QMenu>
29
 
 
30
 
#include <KAction>
31
 
#include <KLocale>
32
 
#include <KMessageBox>
33
 
#include <KUrl>
34
 
#include <KXMLGUIFactory>
35
 
 
36
 
#include <kxmlguiclient.h>
37
 
 
38
 
#include <akonadi/collection.h>
39
 
#include <akonadi/control.h>
40
 
#include <akonadi/item.h>
41
 
#include "entitytreemodel.h"
42
 
 
43
 
#include <kdebug.h>
44
 
 
45
 
using namespace Akonadi;
46
 
 
47
 
/**
48
 
 * @internal
49
 
 */
50
 
class EntityTreeView::Private
51
 
{
52
 
public:
53
 
  Private( EntityTreeView *parent )
54
 
      : mParent( parent ),
55
 
      xmlGuiClient( 0 ), showChildCollectionTree(false) {
56
 
  }
57
 
 
58
 
  void init();
59
 
  void dragExpand();
60
 
  void itemClicked( const QModelIndex& );
61
 
  void itemDoubleClicked( const QModelIndex& );
62
 
  void itemCurrentChanged( const QModelIndex& );
63
 
  bool hasParent( const QModelIndex& idx, Collection::Id parentId );
64
 
 
65
 
  EntityTreeView *mParent;
66
 
  QModelIndex dragOverIndex;
67
 
  QTimer dragExpandTimer;
68
 
 
69
 
  KXMLGUIClient *xmlGuiClient;
70
 
  bool showChildCollectionTree;
71
 
};
72
 
 
73
 
void EntityTreeView::showChildCollectionTree( bool include )
74
 
{
75
 
  d->showChildCollectionTree = include;
76
 
}
77
 
 
78
 
bool EntityTreeView::childCollectionTreeShown() const
79
 
{
80
 
  return d->showChildCollectionTree;
81
 
}
82
 
 
83
 
void EntityTreeView::Private::init()
84
 
{
85
 
  mParent->header()->setClickable( true );
86
 
  mParent->header()->setStretchLastSection( false );
87
 
//   mParent->setRootIsDecorated( false );
88
 
 
89
 
//   mParent->setAutoExpandDelay ( QApplication::startDragTime() );
90
 
 
91
 
  mParent->setSortingEnabled( true );
92
 
  mParent->sortByColumn( 0, Qt::AscendingOrder );
93
 
  mParent->setEditTriggers( QAbstractItemView::EditKeyPressed );
94
 
  mParent->setAcceptDrops( true );
95
 
  mParent->setDropIndicatorShown( true );
96
 
  mParent->setDragDropMode( DragDrop );
97
 
  mParent->setDragEnabled( true );
98
 
 
99
 
  dragExpandTimer.setSingleShot( true );
100
 
  mParent->connect( &dragExpandTimer, SIGNAL( timeout() ), SLOT( dragExpand() ) );
101
 
 
102
 
  mParent->connect( mParent, SIGNAL( clicked( const QModelIndex& ) ),
103
 
                    mParent, SLOT( itemClicked( const QModelIndex& ) ) );
104
 
  mParent->connect( mParent, SIGNAL( doubleClicked( const QModelIndex& ) ),
105
 
                    mParent, SLOT( itemDoubleClicked( const QModelIndex& ) ) );
106
 
 
107
 
  Control::widgetNeedsAkonadi( mParent );
108
 
}
109
 
 
110
 
bool EntityTreeView::Private::hasParent( const QModelIndex& idx, Collection::Id parentId )
111
 
{
112
 
  QModelIndex idx2 = idx;
113
 
  while ( idx2.isValid() ) {
114
 
    if ( mParent->model()->data( idx2, EntityTreeModel::CollectionIdRole ).toLongLong() == parentId )
115
 
      return true;
116
 
 
117
 
    idx2 = idx2.parent();
118
 
  }
119
 
  return false;
120
 
}
121
 
 
122
 
void EntityTreeView::Private::dragExpand()
123
 
{
124
 
  mParent->setExpanded( dragOverIndex, true );
125
 
  dragOverIndex = QModelIndex();
126
 
}
127
 
 
128
 
void EntityTreeView::Private::itemClicked( const QModelIndex &index )
129
 
{
130
 
  if ( !index.isValid() )
131
 
    return;
132
 
 
133
 
  const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
134
 
  if ( collection.isValid() ) {
135
 
    emit mParent->clicked( collection );
136
 
  } else {
137
 
    const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
138
 
    if ( item.isValid() )
139
 
      emit mParent->clicked( item );
140
 
  }
141
 
}
142
 
 
143
 
void EntityTreeView::Private::itemDoubleClicked( const QModelIndex &index )
144
 
{
145
 
  if ( !index.isValid() )
146
 
    return;
147
 
 
148
 
  const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
149
 
  if ( collection.isValid() ) {
150
 
    emit mParent->doubleClicked( collection );
151
 
  } else {
152
 
    const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
153
 
    if ( item.isValid() )
154
 
      emit mParent->doubleClicked( item );
155
 
  }
156
 
}
157
 
 
158
 
void EntityTreeView::Private::itemCurrentChanged( const QModelIndex &index )
159
 
{
160
 
  if ( !index.isValid() )
161
 
    return;
162
 
 
163
 
  const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
164
 
  if ( collection.isValid() ) {
165
 
    emit mParent->currentChanged( collection );
166
 
  } else {
167
 
    const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
168
 
    if ( item.isValid() )
169
 
      emit mParent->currentChanged( item );
170
 
  }
171
 
}
172
 
 
173
 
EntityTreeView::EntityTreeView( QWidget * parent ) :
174
 
    QTreeView( parent ),
175
 
    d( new Private( this ) )
176
 
{
177
 
 
178
 
  setSelectionMode( QAbstractItemView::SingleSelection );
179
 
  d->init();
180
 
}
181
 
 
182
 
EntityTreeView::EntityTreeView( KXMLGUIClient *xmlGuiClient, QWidget * parent ) :
183
 
    QTreeView( parent ),
184
 
    d( new Private( this ) )
185
 
{
186
 
  d->xmlGuiClient = xmlGuiClient;
187
 
  d->init();
188
 
}
189
 
 
190
 
EntityTreeView::~EntityTreeView()
191
 
{
192
 
  delete d;
193
 
}
194
 
 
195
 
void EntityTreeView::setRootIndex(const QModelIndex &idx)
196
 
{
197
 
  QAbstractItemView::setRootIndex(idx);
198
 
  if (!d->showChildCollectionTree)
199
 
  {
200
 
    QModelIndex rowIndex = idx.child( 0, 0);
201
 
    while (rowIndex.isValid())
202
 
    {
203
 
      if ( model()->data( rowIndex, EntityTreeModel::MimeTypeRole ) == Collection::mimeType() )
204
 
      {
205
 
        setRowHidden( rowIndex.row(), idx, true );
206
 
      }
207
 
      rowIndex = rowIndex.sibling( rowIndex.row() + 1, rowIndex.column() );
208
 
    }
209
 
  }
210
 
}
211
 
 
212
 
void EntityTreeView::setModel( QAbstractItemModel * model )
213
 
{
214
 
  QTreeView::setModel( model );
215
 
  header()->setStretchLastSection( true );
216
 
 
217
 
  connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
218
 
           this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
219
 
}
220
 
 
221
 
void EntityTreeView::dragMoveEvent( QDragMoveEvent * event )
222
 
{
223
 
  QModelIndex index = indexAt( event->pos() );
224
 
  if ( d->dragOverIndex != index ) {
225
 
    d->dragExpandTimer.stop();
226
 
    if ( index.isValid() && !isExpanded( index ) && itemsExpandable() ) {
227
 
      d->dragExpandTimer.start( QApplication::startDragTime() );
228
 
      d->dragOverIndex = index;
229
 
    }
230
 
  }
231
 
 
232
 
  // Check if the collection under the cursor accepts this data type
233
 
  Collection col = model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
234
 
  if (!col.isValid())
235
 
  {
236
 
    Item item = model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
237
 
    if (item.isValid())
238
 
    {
239
 
      col = model()->data( index.parent(), EntityTreeModel::CollectionRole ).value<Collection>();
240
 
    }
241
 
  }
242
 
  if ( col.isValid() )
243
 
  {
244
 
    QStringList supportedContentTypes = col.contentMimeTypes();
245
 
    const QMimeData *data = event->mimeData();
246
 
    KUrl::List urls = KUrl::List::fromMimeData( data );
247
 
    foreach( const KUrl &url, urls ) {
248
 
      const Collection collection = Collection::fromUrl( url );
249
 
      if ( collection.isValid() ) {
250
 
        if ( !supportedContentTypes.contains( Collection::mimeType() ) )
251
 
          break;
252
 
 
253
 
        // Check if we don't try to drop on one of the children
254
 
        if ( d->hasParent( index, collection.id() ) )
255
 
          break;
256
 
      } else { // This is an item.
257
 
        QString type = url.queryItems()[ QString::fromLatin1( "type" )];
258
 
        if ( !supportedContentTypes.contains( type ) )
259
 
          break;
260
 
      }
261
 
      // All urls are supported. process the event.
262
 
      QTreeView::dragMoveEvent( event );
263
 
      return;
264
 
    }
265
 
  }
266
 
 
267
 
  event->setDropAction( Qt::IgnoreAction );
268
 
  return;
269
 
}
270
 
 
271
 
void EntityTreeView::dragLeaveEvent( QDragLeaveEvent * event )
272
 
{
273
 
  d->dragExpandTimer.stop();
274
 
  d->dragOverIndex = QModelIndex();
275
 
  QTreeView::dragLeaveEvent( event );
276
 
}
277
 
 
278
 
 
279
 
void EntityTreeView::dropEvent( QDropEvent * event )
280
 
{
281
 
  d->dragExpandTimer.stop();
282
 
  d->dragOverIndex = QModelIndex();
283
 
 
284
 
  QModelIndexList idxs = selectedIndexes();
285
 
 
286
 
 
287
 
  QMenu popup( this );
288
 
  QAction* moveDropAction;
289
 
  // TODO If possible, hide unavailable actions ...
290
 
  // Use the model to determine if a move is ok.
291
 
//   if (...)
292
 
//   {
293
 
  moveDropAction = popup.addAction( KIcon( QString::fromLatin1( "edit-rename" ) ), i18n( "&Move here" ) );
294
 
//   }
295
 
 
296
 
  //TODO: If dropping on one of the selectedIndexes, just return.
297
 
  // open a context menu offering different drop actions (move, copy and cancel)
298
 
  QAction* copyDropAction = popup.addAction( KIcon( QString::fromLatin1( "edit-copy" ) ), i18n( "&Copy here" ) );
299
 
  popup.addSeparator();
300
 
  popup.addAction( KIcon( QString::fromLatin1( "process-stop" ) ), i18n( "Cancel" ) );
301
 
 
302
 
  QAction *activatedAction = popup.exec( QCursor::pos() );
303
 
 
304
 
  if ( activatedAction == moveDropAction ) {
305
 
    event->setDropAction( Qt::MoveAction );
306
 
  } else if ( activatedAction == copyDropAction ) {
307
 
    event->setDropAction( Qt::CopyAction );
308
 
  }
309
 
  // TODO: Handle link action.
310
 
  else return;
311
 
 
312
 
  QTreeView::dropEvent( event );
313
 
}
314
 
 
315
 
void EntityTreeView::contextMenuEvent( QContextMenuEvent * event )
316
 
{
317
 
  if ( !d->xmlGuiClient )
318
 
    return;
319
 
 
320
 
  const QModelIndex index = indexAt( event->pos() );
321
 
 
322
 
  QMenu *popup = 0;
323
 
 
324
 
  // check if the index under the cursor is a collection or item
325
 
  const Item item = model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
326
 
  if ( item.isValid() )
327
 
    popup = static_cast<QMenu*>( d->xmlGuiClient->factory()->container(
328
 
                                 QLatin1String( "akonadi_itemview_contextmenu" ), d->xmlGuiClient ) );
329
 
  else
330
 
    popup = static_cast<QMenu*>( d->xmlGuiClient->factory()->container(
331
 
                                 QLatin1String( "akonadi_collectionview_contextmenu" ), d->xmlGuiClient ) );
332
 
  if ( popup )
333
 
    popup->exec( event->globalPos() );
334
 
}
335
 
 
336
 
void EntityTreeView::setXmlGuiClient( KXMLGUIClient * xmlGuiClient )
337
 
{
338
 
  d->xmlGuiClient = xmlGuiClient;
339
 
}
340
 
 
341
 
#include "entitytreeview.moc"