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