00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "collectiondialog.h"
00022
00023 #include "asyncselectionhandler_p.h"
00024
00025 #include <akonadi/changerecorder.h>
00026 #include <akonadi/collectionfetchscope.h>
00027 #include <akonadi/collectionfilterproxymodel.h>
00028 #include <akonadi/entityrightsfiltermodel.h>
00029 #include <akonadi/entitytreemodel.h>
00030 #include <akonadi/entitytreeview.h>
00031 #include <akonadi/session.h>
00032 #include <akonadi/collectioncreatejob.h>
00033 #include <akonadi/collectionutils_p.h>
00034
00035 #include <QtGui/QHeaderView>
00036 #include <QtGui/QLabel>
00037 #include <QtGui/QVBoxLayout>
00038
00039 #include <KLineEdit>
00040 #include <KLocale>
00041 #include <KInputDialog>
00042 #include <KMessageBox>
00043
00044 using namespace Akonadi;
00045
00046 class CollectionDialog::Private
00047 {
00048 public:
00049 Private( QAbstractItemModel *customModel, CollectionDialog *parent, CollectionDialogOptions options )
00050 : mParent( parent ),
00051 mMonitor( 0 )
00052 {
00053
00054 QWidget *widget = mParent->mainWidget();
00055 QVBoxLayout *layout = new QVBoxLayout( widget );
00056
00057 changeCollectionDialogOptions( options );
00058
00059 mTextLabel = new QLabel;
00060 layout->addWidget( mTextLabel );
00061 mTextLabel->hide();
00062
00063 KLineEdit* filterCollectionLineEdit = new KLineEdit( widget );
00064 filterCollectionLineEdit->setClearButtonShown( true );
00065 filterCollectionLineEdit->setClickMessage( i18nc( "@info/plain Displayed grayed-out inside the "
00066 "textbox, verb to search", "Search" ) );
00067 layout->addWidget( filterCollectionLineEdit );
00068
00069 mView = new EntityTreeView;
00070 mView->setDragDropMode( QAbstractItemView::NoDragDrop );
00071 mView->header()->hide();
00072 layout->addWidget( mView );
00073
00074
00075 mParent->enableButton( KDialog::Ok, false );
00076
00077
00078 QAbstractItemModel *baseModel;
00079
00080 if ( customModel ) {
00081 baseModel = customModel;
00082 } else {
00083 mMonitor = new Akonadi::ChangeRecorder( mParent );
00084 mMonitor->fetchCollection( true );
00085 mMonitor->setCollectionMonitored( Akonadi::Collection::root() );
00086
00087 EntityTreeModel *model = new EntityTreeModel( mMonitor, mParent );
00088 model->setItemPopulationStrategy( EntityTreeModel::NoItemPopulation );
00089 baseModel = model;
00090 }
00091
00092 mMimeTypeFilterModel = new CollectionFilterProxyModel( mParent );
00093 mMimeTypeFilterModel->setSourceModel( baseModel );
00094
00095 mRightsFilterModel = new EntityRightsFilterModel( mParent );
00096 mRightsFilterModel->setSourceModel( mMimeTypeFilterModel );
00097
00098 mSelectionHandler = new AsyncSelectionHandler( mRightsFilterModel, mParent );
00099 mParent->connect( mSelectionHandler, SIGNAL( collectionAvailable( const QModelIndex& ) ),
00100 mParent, SLOT( slotCollectionAvailable( const QModelIndex& ) ) );
00101
00102 KRecursiveFilterProxyModel* filterCollection = new KRecursiveFilterProxyModel( mParent );
00103 filterCollection->setDynamicSortFilter( true );
00104 filterCollection->setSourceModel( mRightsFilterModel );
00105 filterCollection->setFilterCaseSensitivity( Qt::CaseInsensitive );
00106 mView->setModel( filterCollection );
00107
00108 mParent->connect( filterCollectionLineEdit, SIGNAL( textChanged( const QString& ) ),
00109 filterCollection, SLOT( setFilterFixedString( const QString& ) ) );
00110
00111 mParent->connect( mView->selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00112 mParent, SLOT( slotSelectionChanged() ) );
00113
00114 mParent->connect( mView, SIGNAL( doubleClicked( const QModelIndex& ) ),
00115 mParent, SLOT( accept() ) );
00116
00117 }
00118
00119 ~Private()
00120 {
00121 }
00122
00123 void slotCollectionAvailable( const QModelIndex &index )
00124 {
00125 mView->expandAll();
00126 mView->setCurrentIndex( index );
00127 }
00128
00129 CollectionDialog *mParent;
00130
00131 ChangeRecorder *mMonitor;
00132 CollectionFilterProxyModel *mMimeTypeFilterModel;
00133 EntityRightsFilterModel *mRightsFilterModel;
00134 EntityTreeView *mView;
00135 AsyncSelectionHandler *mSelectionHandler;
00136 QLabel *mTextLabel;
00137 bool mAllowToCreateNewChildCollection;
00138
00139 void slotSelectionChanged();
00140 void slotAddChildCollection();
00141 void slotCollectionCreationResult( KJob* job );
00142 bool canCreateCollection( const Akonadi::Collection &parentCollection ) const;
00143 void changeCollectionDialogOptions( CollectionDialogOptions options );
00144
00145 };
00146
00147 void CollectionDialog::Private::slotSelectionChanged()
00148 {
00149 mParent->enableButton( KDialog::Ok, mView->selectionModel()->selectedIndexes().count() > 0 );
00150 if ( mAllowToCreateNewChildCollection ) {
00151 const Akonadi::Collection parentCollection = mParent->selectedCollection();
00152 const bool canCreateChildCollections = canCreateCollection( parentCollection );
00153 const bool isVirtual = Akonadi::CollectionUtils::isVirtual( parentCollection );
00154
00155 mParent->enableButton( KDialog::User1, (canCreateChildCollections && !isVirtual) );
00156 if ( parentCollection.isValid() ) {
00157 const bool canCreateItems = (parentCollection.rights() & Akonadi::Collection::CanCreateItem);
00158 mParent->enableButton( KDialog::Ok, canCreateItems );
00159 }
00160 }
00161 }
00162
00163 void CollectionDialog::Private::changeCollectionDialogOptions( CollectionDialogOptions options )
00164 {
00165 mAllowToCreateNewChildCollection = ( options & AllowToCreateNewChildCollection );
00166 if ( mAllowToCreateNewChildCollection ) {
00167 mParent->setButtons( Ok | Cancel | User1 );
00168 mParent->setButtonGuiItem( User1, KGuiItem( i18n( "&New Subfolder..." ), QLatin1String( "folder-new" ),
00169 i18n( "Create a new subfolder under the currently selected folder" ) ) );
00170 mParent->enableButton( KDialog::User1, false );
00171 connect( mParent, SIGNAL( user1Clicked() ), mParent, SLOT( slotAddChildCollection() ) );
00172 }
00173 }
00174
00175
00176
00177 bool CollectionDialog::Private::canCreateCollection( const Akonadi::Collection &parentCollection ) const
00178 {
00179 if ( !parentCollection.isValid() )
00180 return false;
00181
00182 if ( ( parentCollection.rights() & Akonadi::Collection::CanCreateCollection ) ) {
00183 const QStringList dialogMimeTypeFilter = mParent->mimeTypeFilter();
00184 const QStringList parentCollectionMimeTypes = parentCollection.contentMimeTypes();
00185 Q_FOREACH ( const QString& mimetype, dialogMimeTypeFilter ) {
00186 if ( parentCollectionMimeTypes.contains( mimetype ) )
00187 return true;
00188 }
00189 return true;
00190 }
00191 return false;
00192 }
00193
00194
00195 void CollectionDialog::Private::slotAddChildCollection()
00196 {
00197 const Akonadi::Collection parentCollection = mParent->selectedCollection();
00198 if ( canCreateCollection( parentCollection ) ) {
00199 const QString name = KInputDialog::getText( i18nc( "@title:window", "New Folder" ),
00200 i18nc( "@label:textbox, name of a thing", "Name" ),
00201 QString(), 0, mParent );
00202 if ( name.isEmpty() )
00203 return;
00204
00205 Akonadi::Collection collection;
00206 collection.setName( name );
00207 collection.setParentCollection( parentCollection );
00208 Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob( collection );
00209 connect( job, SIGNAL( result( KJob* ) ), mParent, SLOT( slotCollectionCreationResult( KJob* ) ) );
00210 }
00211 }
00212
00213 void CollectionDialog::Private::slotCollectionCreationResult( KJob* job )
00214 {
00215 if ( job->error() ) {
00216 KMessageBox::error( mParent, i18n( "Could not create folder: %1", job->errorString() ),
00217 i18n( "Folder creation failed" ) );
00218 }
00219 }
00220
00221
00222
00223 CollectionDialog::CollectionDialog( QWidget *parent )
00224 : KDialog( parent ),
00225 d( new Private( 0, this, CollectionDialog::None ) )
00226 {
00227 }
00228
00229 CollectionDialog::CollectionDialog( QAbstractItemModel *model, QWidget *parent )
00230 : KDialog( parent ),
00231 d( new Private( model, this, CollectionDialog::None ) )
00232 {
00233 }
00234
00235 CollectionDialog::CollectionDialog( CollectionDialogOptions options, QAbstractItemModel *model, QWidget *parent )
00236 : KDialog( parent ),
00237 d( new Private( model, this, options ) )
00238 {
00239 }
00240
00241
00242 CollectionDialog::~CollectionDialog()
00243 {
00244 delete d;
00245 }
00246
00247 Akonadi::Collection CollectionDialog::selectedCollection() const
00248 {
00249 if ( selectionMode() == QAbstractItemView::SingleSelection ) {
00250 const QModelIndex index = d->mView->currentIndex();
00251 if ( index.isValid() )
00252 return index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00253 }
00254
00255 return Collection();
00256 }
00257
00258 Akonadi::Collection::List CollectionDialog::selectedCollections() const
00259 {
00260 Collection::List collections;
00261 const QItemSelectionModel *selectionModel = d->mView->selectionModel();
00262 const QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
00263 foreach ( const QModelIndex &index, selectedIndexes ) {
00264 if ( index.isValid() ) {
00265 const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00266 if ( collection.isValid() )
00267 collections.append( collection );
00268 }
00269 }
00270
00271 return collections;
00272 }
00273
00274 void CollectionDialog::setMimeTypeFilter( const QStringList &mimeTypes )
00275 {
00276 d->mMimeTypeFilterModel->clearFilters();
00277 d->mMimeTypeFilterModel->addMimeTypeFilters( mimeTypes );
00278
00279 if ( d->mMonitor )
00280 foreach ( const QString &mimetype, mimeTypes )
00281 d->mMonitor->setMimeTypeMonitored( mimetype );
00282 }
00283
00284 QStringList CollectionDialog::mimeTypeFilter() const
00285 {
00286 return d->mMimeTypeFilterModel->mimeTypeFilters();
00287 }
00288
00289 void CollectionDialog::setAccessRightsFilter( Collection::Rights rights )
00290 {
00291 d->mRightsFilterModel->setAccessRights( rights );
00292 }
00293
00294 Akonadi::Collection::Rights CollectionDialog::accessRightsFilter() const
00295 {
00296 return d->mRightsFilterModel->accessRights();
00297 }
00298
00299 void CollectionDialog::setDescription( const QString &text )
00300 {
00301 d->mTextLabel->setText( text );
00302 d->mTextLabel->show();
00303 }
00304
00305 void CollectionDialog::setDefaultCollection( const Collection &collection )
00306 {
00307 d->mSelectionHandler->waitForCollection( collection );
00308 }
00309
00310 void CollectionDialog::setSelectionMode( QAbstractItemView::SelectionMode mode )
00311 {
00312 d->mView->setSelectionMode( mode );
00313 }
00314
00315 QAbstractItemView::SelectionMode CollectionDialog::selectionMode() const
00316 {
00317 return d->mView->selectionMode();
00318 }
00319
00320 void CollectionDialog::changeCollectionDialogOptions( CollectionDialogOptions options )
00321 {
00322 d->changeCollectionDialogOptions( options );
00323 }
00324
00325 #include "collectiondialog.moc"