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

akonadi

standardactionmanager.cpp

00001 /*
00002     Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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 "standardactionmanager.h"
00021 
00022 #include "agentmanager.h"
00023 #include "collectioncreatejob.h"
00024 #include "collectiondeletejob.h"
00025 #include "collectionmodel.h"
00026 #include "collectionutils_p.h"
00027 #include "collectionpropertiesdialog.h"
00028 #include "itemdeletejob.h"
00029 #include "itemmodel.h"
00030 #include "pastehelper.h"
00031 #include "subscriptiondialog.h"
00032 
00033 #include <KAction>
00034 #include <KActionCollection>
00035 #include <KDebug>
00036 #include <KInputDialog>
00037 #include <KLocale>
00038 #include <KMessageBox>
00039 
00040 #include <QApplication>
00041 #include <QClipboard>
00042 #include <QItemSelectionModel>
00043 #include <QMimeData>
00044 
00045 #include <boost/static_assert.hpp>
00046 
00047 using namespace Akonadi;
00048 
00049 static const struct {
00050   const char *name;
00051   const char *label;
00052   const char *icon;
00053   int shortcut;
00054   const char* slot;
00055 } actionData[] = {
00056   { "akonadi_collection_create", I18N_NOOP("&New Folder..."), "folder-new", 0, SLOT(slotCreateCollection()) },
00057   { "akonadi_collection_copy", 0, "edit-copy", 0, SLOT(slotCopyCollections()) },
00058   { "akonadi_collection_delete", I18N_NOOP("&Delete Folder"), "edit-delete", 0, SLOT(slotDeleteCollection()) },
00059   { "akonadi_collection_sync", I18N_NOOP("&Synchronize Folder"), "view-refresh", Qt::Key_F5, SLOT(slotSynchronizeCollection()) },
00060   { "akonadi_collection_properties", I18N_NOOP("Folder &Properties..."), "configure", 0, SLOT(slotCollectionProperties()) },
00061   { "akonadi_item_copy", 0, "edit-copy", 0, SLOT(slotCopyItems()) },
00062   { "akonadi_paste", I18N_NOOP("&Paste"), "edit-paste", Qt::CTRL + Qt::Key_V, SLOT(slotPaste()) },
00063   { "akonadi_item_delete", 0, "edit-delete", Qt::Key_Delete, SLOT(slotDeleteItems()) },
00064   { "akonadi_manage_local_subscriptions", I18N_NOOP("Manage Local &Subscriptions..."), 0, 0, SLOT(slotLocalSubscription()) }
00065 };
00066 static const int numActionData = sizeof actionData / sizeof *actionData;
00067 
00068 BOOST_STATIC_ASSERT( numActionData == StandardActionManager::LastType );
00069 
00070 static bool canCreateCollection( const Collection &collection )
00071 {
00072   if ( !( collection.rights() & Collection::CanCreateCollection ) )
00073     return false;
00074 
00075   if ( !collection.contentMimeTypes().contains( Collection::mimeType() ) )
00076     return false;
00077 
00078   return true;
00079 }
00080 
00084 class StandardActionManager::Private
00085 {
00086   public:
00087     Private( StandardActionManager *parent ) :
00088       q( parent ),
00089       collectionSelectionModel( 0 ),
00090       itemSelectionModel( 0 )
00091     {
00092       actions.fill( 0, StandardActionManager::LastType );
00093 
00094       pluralLabels.insert( StandardActionManager::CopyCollections, ki18np( "&Copy Folder", "&Copy %1 Folders" ) );
00095       pluralLabels.insert( StandardActionManager::CopyItems, ki18np( "&Copy Item", "&Copy %1 Items" ) );
00096       pluralLabels.insert( StandardActionManager::DeleteItems, ki18np( "&Delete Item", "&Delete %1 Items" ) );
00097     }
00098 
00099     void enableAction( StandardActionManager::Type type, bool enable )
00100     {
00101       Q_ASSERT( type >= 0 && type < StandardActionManager::LastType );
00102       if ( actions[type] )
00103         actions[type]->setEnabled( enable );
00104     }
00105 
00106     void updatePluralLabel( StandardActionManager::Type type, int count )
00107     {
00108       Q_ASSERT( type >= 0 && type < StandardActionManager::LastType );
00109       if ( actions[type] && pluralLabels.contains( type ) && !pluralLabels.value( type ).isEmpty() ) {
00110         actions[type]->setText( pluralLabels.value( type ).subs( qMax( count, 1 ) ).toString() );
00111       }
00112     }
00113 
00114     void copy( QItemSelectionModel* selModel )
00115     {
00116       Q_ASSERT( selModel );
00117       if ( selModel->selectedRows().count() <= 0 )
00118         return;
00119       QMimeData *mimeData = selModel->model()->mimeData( selModel->selectedRows() );
00120       QApplication::clipboard()->setMimeData( mimeData );
00121     }
00122 
00123     void updateActions()
00124     {
00125       bool singleColSelected = false;
00126       bool multiColSelected = false;
00127       int colCount = 0;
00128       QModelIndex selectedIndex;
00129       if ( collectionSelectionModel ) {
00130         colCount = collectionSelectionModel->selectedRows().count();
00131         singleColSelected = colCount == 1;
00132         multiColSelected = colCount > 0;
00133         if ( singleColSelected )
00134           selectedIndex = collectionSelectionModel->selectedRows().first();
00135       }
00136 
00137       enableAction( CopyCollections, multiColSelected );
00138       enableAction( CollectionProperties, singleColSelected );
00139 
00140       if ( singleColSelected && selectedIndex.isValid() ) {
00141         const Collection col = selectedIndex.data( CollectionModel::CollectionRole ).value<Collection>();
00142         enableAction( CreateCollection, canCreateCollection( col ) );
00143         enableAction( DeleteCollections, col.rights() & Collection::CanDeleteCollection );
00144         enableAction( SynchronizeCollections, CollectionUtils::isResource( col ) || CollectionUtils::isFolder( col ) );
00145         enableAction( Paste, PasteHelper::canPaste( QApplication::clipboard()->mimeData(), col ) );
00146       } else {
00147         enableAction( CreateCollection, false );
00148         enableAction( DeleteCollections, false );
00149         enableAction( SynchronizeCollections, false );
00150         enableAction( Paste, false );
00151       }
00152 
00153       bool multiItemSelected = false;
00154       int itemCount = 0;
00155       if ( itemSelectionModel ) {
00156         itemCount = itemSelectionModel->selectedRows().count();
00157         multiItemSelected = itemCount > 0;
00158       }
00159 
00160       enableAction( CopyItems, multiItemSelected );
00161       enableAction( DeleteItems, multiItemSelected );
00162 
00163       updatePluralLabel( CopyCollections, colCount );
00164       updatePluralLabel( CopyItems, itemCount );
00165       updatePluralLabel( DeleteItems, itemCount );
00166 
00167       emit q->actionStateUpdated();
00168     }
00169 
00170     void clipboardChanged( QClipboard::Mode mode )
00171     {
00172       if ( mode == QClipboard::Clipboard )
00173         updateActions();
00174     }
00175 
00176     void slotCreateCollection()
00177     {
00178       const QModelIndex index = collectionSelectionModel->currentIndex();
00179       const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
00180 
00181       if ( !canCreateCollection( collection ) )
00182         return;
00183 
00184       const QString name = KInputDialog::getText( i18nc( "@title:window", "New Folder"),
00185                                                   i18nc( "@label:textbox, name of a thing", "Name"),
00186                                                   QString(), 0, parentWidget );
00187       if ( name.isEmpty() )
00188         return;
00189       Collection::Id parentId = index.data( CollectionModel::CollectionIdRole ).toLongLong();
00190       if ( parentId <= 0 )
00191         return;
00192 
00193       Collection col;
00194       col.setName( name );
00195       col.setParent( parentId );
00196       CollectionCreateJob *job = new CollectionCreateJob( col );
00197       q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionCreationResult(KJob*)) );
00198     }
00199 
00200     void slotCopyCollections()
00201     {
00202       copy( collectionSelectionModel );
00203     }
00204 
00205     void slotDeleteCollection()
00206     {
00207       Q_ASSERT( collectionSelectionModel );
00208       const QModelIndex index = collectionSelectionModel->currentIndex();
00209       if ( !index.isValid() )
00210         return;
00211 
00212       const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
00213       QString text = i18n( "Do you really want to delete folder '%1' and all its sub-folders?", index.data().toString() );
00214       if ( CollectionUtils::isVirtual( collection ) )
00215         text = i18n( "Do you really want to delete the search view '%1'?", index.data().toString() );
00216 
00217       if ( KMessageBox::questionYesNo( parentWidget, text,
00218            i18n("Delete folder?"), KStandardGuiItem::del(), KStandardGuiItem::cancel(),
00219            QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
00220         return;
00221       const Collection::Id colId = index.data( CollectionModel::CollectionIdRole ).toLongLong();
00222       if ( colId <= 0 )
00223         return;
00224 
00225       CollectionDeleteJob *job = new CollectionDeleteJob( Collection( colId ), q );
00226       q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionDeletionResult(KJob*)) );
00227     }
00228 
00229     void slotSynchronizeCollection()
00230     {
00231       QModelIndex index = collectionSelectionModel->currentIndex();
00232       if ( !index.isValid() )
00233         return;
00234       const Collection col = index.data( CollectionModel::CollectionRole ).value<Collection>();
00235       AgentManager::self()->synchronizeCollection( col );
00236     }
00237 
00238     void slotCollectionProperties()
00239     {
00240       const QModelIndex index = collectionSelectionModel->currentIndex();
00241       if ( !index.isValid() )
00242         return;
00243       const Collection col = index.data( CollectionModel::CollectionRole ).value<Collection>();
00244       CollectionPropertiesDialog* dlg = new CollectionPropertiesDialog( col, parentWidget );
00245       dlg->show();
00246     }
00247 
00248     void slotCopyItems()
00249     {
00250       copy( itemSelectionModel );
00251     }
00252 
00253     void slotPaste()
00254     {
00255       const QModelIndex index = collectionSelectionModel->currentIndex();
00256       if ( !index.isValid() )
00257         return;
00258       const Collection col = index.data( CollectionModel::CollectionRole ).value<Collection>();
00259       KJob *job = PasteHelper::paste( QApplication::clipboard()->mimeData(), col );
00260       q->connect( job, SIGNAL(result(KJob*)), q, SLOT(pasteResult(KJob*)) );
00261     }
00262 
00263     void slotDeleteItems()
00264     {
00265       if ( KMessageBox::questionYesNo( parentWidget,
00266            i18n( "Do you really want to delete all selected items?" ),
00267            i18n("Delete?"), KStandardGuiItem::del(), KStandardGuiItem::cancel(),
00268            QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
00269         return;
00270 
00271       Q_ASSERT( itemSelectionModel );
00272 
00273       // TODO: fix this once ItemModifyJob can handle item lists
00274       foreach ( const QModelIndex &index, itemSelectionModel->selectedRows() ) {
00275         new ItemDeleteJob( Item( index.data( ItemModel::IdRole ).toLongLong() ), q );
00276       }
00277     }
00278 
00279     void slotLocalSubscription()
00280     {
00281       SubscriptionDialog* dlg = new SubscriptionDialog( parentWidget );
00282       dlg->show();
00283     }
00284 
00285     void collectionCreationResult( KJob *job )
00286     {
00287       if ( job->error() ) {
00288         KMessageBox::error( parentWidget, i18n("Could not create folder: %1", job->errorString()),
00289                             i18n("Folder creation failed") );
00290       }
00291     }
00292 
00293     void collectionDeletionResult( KJob *job )
00294     {
00295       if ( job->error() ) {
00296         KMessageBox::error( parentWidget, i18n("Could not delete folder: %1", job->errorString()),
00297                             i18n("Folder deletion failed") );
00298       }
00299     }
00300 
00301     void pasteResult( KJob *job )
00302     {
00303       if ( job->error() ) {
00304         KMessageBox::error( parentWidget, i18n("Could not paste data: %1", job->errorString()),
00305                             i18n("Paste failed") );
00306       }
00307     }
00308 
00309     StandardActionManager *q;
00310     KActionCollection *actionCollection;
00311     QWidget *parentWidget;
00312     QItemSelectionModel *collectionSelectionModel;
00313     QItemSelectionModel *itemSelectionModel;
00314     QVector<KAction*> actions;
00315     AgentManager *agentManager;
00316     QHash<StandardActionManager::Type, KLocalizedString> pluralLabels;
00317 };
00318 
00319 StandardActionManager::StandardActionManager( KActionCollection * actionCollection,
00320                                               QWidget * parent) :
00321     QObject( parent ),
00322     d( new Private( this ) )
00323 {
00324   d->parentWidget = parent;
00325   d->actionCollection = actionCollection;
00326   connect( QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), SLOT(clipboardChanged(QClipboard::Mode)) );
00327 }
00328 
00329 StandardActionManager::~ StandardActionManager()
00330 {
00331   delete d;
00332 }
00333 
00334 void StandardActionManager::setCollectionSelectionModel(QItemSelectionModel * selectionModel)
00335 {
00336   d->collectionSelectionModel = selectionModel;
00337   connect( selectionModel, SIGNAL(selectionChanged( const QItemSelection&, const QItemSelection& )),
00338            SLOT(updateActions()) );
00339 }
00340 
00341 void StandardActionManager::setItemSelectionModel(QItemSelectionModel * selectionModel)
00342 {
00343   d->itemSelectionModel = selectionModel;
00344   connect( selectionModel, SIGNAL(selectionChanged( const QItemSelection&, const QItemSelection& )),
00345            SLOT(updateActions()) );
00346 }
00347 
00348 KAction* StandardActionManager::createAction( Type type )
00349 {
00350   Q_ASSERT( type >= 0 && type < LastType );
00351   Q_ASSERT( actionData[type].name );
00352   if ( d->actions[type] )
00353     return d->actions[type];
00354   KAction *action = new KAction( d->parentWidget );
00355   if ( d->pluralLabels.contains( type ) && !d->pluralLabels.value( type ).isEmpty() )
00356     action->setText( d->pluralLabels.value( type ).subs( 1 ).toString() );
00357   else if ( actionData[type].label )
00358     action->setText( i18n( actionData[type].label ) );
00359   if ( actionData[type].icon )
00360     action->setIcon( KIcon( QString::fromLatin1( actionData[type].icon ) ) );
00361   action->setShortcut( actionData[type].shortcut );
00362   if ( actionData[type].slot )
00363     connect( action, SIGNAL(triggered()), actionData[type].slot );
00364   d->actionCollection->addAction( QString::fromLatin1(actionData[type].name), action );
00365   d->actions[type] = action;
00366   d->updateActions();
00367   return action;
00368 }
00369 
00370 void StandardActionManager::createAllActions()
00371 {
00372   for ( int i = 0; i < LastType; ++i )
00373     createAction( (Type)i );
00374 }
00375 
00376 KAction * StandardActionManager::action( Type type ) const
00377 {
00378   Q_ASSERT( type >= 0 && type < LastType );
00379   return d->actions[type];
00380 }
00381 
00382 void StandardActionManager::setActionText(Type type, const KLocalizedString & text)
00383 {
00384   Q_ASSERT( type >= 0 && type < LastType );
00385   d->pluralLabels.insert( type, text );
00386 }
00387 
00388 #include "standardactionmanager.moc"

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
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.6
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