akonadi
collectiondialog_mobile.cpp
00001 /* 00002 Copyright 2010 Tobias Koenig <tokoe@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 "collectiondialog.h" 00021 #include "collectiondialog_mobile_p.h" 00022 00023 #include "asyncselectionhandler_p.h" 00024 #include <kdescendantsproxymodel.h> 00025 00026 #include <akonadi/changerecorder.h> 00027 #include <akonadi/collectioncreatejob.h> 00028 #include <akonadi/collectionfilterproxymodel.h> 00029 #include <akonadi/collectionutils_p.h> 00030 #include <akonadi/entityrightsfiltermodel.h> 00031 #include <akonadi/entitytreemodel.h> 00032 00033 #include <KLocale> 00034 #include <KInputDialog> 00035 #include <KMessageBox> 00036 #include <KStandardDirs> 00037 00038 #include <QtDeclarative/QDeclarativeContext> 00039 #include <QtDeclarative/QDeclarativeEngine> 00040 #include <QtDeclarative/QDeclarativeView> 00041 00042 using namespace Akonadi; 00043 00044 CollectionDialog::Private::Private( QAbstractItemModel *customModel, CollectionDialog *parent, CollectionDialogOptions options ) 00045 : QObject( parent ), 00046 mParent( parent ), 00047 mSelectionMode( QAbstractItemView::SingleSelection ), 00048 mOkButtonEnabled( false ), 00049 mCancelButtonEnabled( true ), 00050 mCreateButtonEnabled( false ) 00051 { 00052 // setup GUI 00053 mView = new QDeclarativeView( mParent ); 00054 00055 mParent->setMainWidget( mView ); 00056 mParent->setButtons( KDialog::None ); 00057 00058 changeCollectionDialogOptions( options ); 00059 00060 QAbstractItemModel *baseModel; 00061 00062 if ( customModel ) { 00063 baseModel = customModel; 00064 } else { 00065 mMonitor = new Akonadi::ChangeRecorder( mParent ); 00066 mMonitor->fetchCollection( true ); 00067 mMonitor->setCollectionMonitored( Akonadi::Collection::root() ); 00068 00069 mModel = new EntityTreeModel( mMonitor, mParent ); 00070 mModel->setItemPopulationStrategy( EntityTreeModel::NoItemPopulation ); 00071 00072 baseModel = mModel; 00073 } 00074 00075 KDescendantsProxyModel *proxyModel = new KDescendantsProxyModel( parent ); 00076 proxyModel->setDisplayAncestorData( true ); 00077 proxyModel->setSourceModel( baseModel ); 00078 00079 mMimeTypeFilterModel = new CollectionFilterProxyModel( parent ); 00080 mMimeTypeFilterModel->setSourceModel( proxyModel ); 00081 00082 mRightsFilterModel = new EntityRightsFilterModel( parent ); 00083 mRightsFilterModel->setSourceModel( mMimeTypeFilterModel ); 00084 00085 mFilterModel = new QSortFilterProxyModel( parent ); 00086 mFilterModel->setFilterCaseSensitivity( Qt::CaseInsensitive ); 00087 mFilterModel->setSourceModel( mRightsFilterModel ); 00088 00089 mSelectionModel = new QItemSelectionModel( mFilterModel ); 00090 mParent->connect( mSelectionModel, SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), 00091 SLOT( slotSelectionChanged() ) ); 00092 mParent->connect( mSelectionModel, SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), 00093 this, SLOT( selectionChanged( const QItemSelection&, const QItemSelection& ) ) ); 00094 00095 mSelectionHandler = new AsyncSelectionHandler( mFilterModel, mParent ); 00096 mParent->connect( mSelectionHandler, SIGNAL( collectionAvailable( const QModelIndex& ) ), 00097 SLOT( slotCollectionAvailable( const QModelIndex& ) ) ); 00098 00099 foreach ( const QString &importPath, KGlobal::dirs()->findDirs( "module", QLatin1String( "imports" ) ) ) 00100 mView->engine()->addImportPath( importPath ); 00101 00102 mView->rootContext()->setContextProperty( QLatin1String( "dialogController" ), this ); 00103 mView->rootContext()->setContextProperty( QLatin1String( "collectionModel" ), mFilterModel ); 00104 00105 // QUICKHACK: since we have no KDE integration plugin available in kdelibs, we have to do the translation in C++ space 00106 mView->rootContext()->setContextProperty( QLatin1String( "okButtonText" ), KStandardGuiItem::ok().text().remove( QLatin1Char( '&' ) ) ); 00107 mView->rootContext()->setContextProperty( QLatin1String( "cancelButtonText" ), KStandardGuiItem::cancel().text().remove( QLatin1Char( '&' ) ) ); 00108 mView->rootContext()->setContextProperty( QLatin1String( "createButtonText" ), i18n( "&New Subfolder..." ).remove( QLatin1Char( '&' ) ) ); 00109 00110 mView->setSource( QUrl::fromLocalFile( KStandardDirs::locate( "data", QLatin1String( "akonadi-kde/qml/CollectionDialogMobile.qml" ) ) ) ); 00111 00112 #if defined (Q_WS_MAEMO_5) || defined (Q_OS_WINCE) 00113 mParent->setWindowState( Qt::WindowFullScreen ); 00114 #else 00115 // on the desktop start with a nice size 00116 mParent->resize( 800, 480 ); 00117 #endif 00118 } 00119 00120 CollectionDialog::Private::~Private() 00121 { 00122 } 00123 00124 void CollectionDialog::Private::slotCollectionAvailable( const QModelIndex &index ) 00125 { 00126 mSelectionModel->setCurrentIndex( index, QItemSelectionModel::ClearAndSelect ); 00127 } 00128 00129 void CollectionDialog::Private::slotSelectionChanged() 00130 { 00131 mOkButtonEnabled = mSelectionModel->hasSelection(); 00132 if ( mAllowToCreateNewChildCollection ) { 00133 const Akonadi::Collection parentCollection = mParent->selectedCollection(); 00134 const bool canCreateChildCollections = canCreateCollection( parentCollection ); 00135 const bool isVirtual = Akonadi::CollectionUtils::isVirtual( parentCollection ); 00136 00137 mCreateButtonEnabled = (canCreateChildCollections && !isVirtual); 00138 if ( parentCollection.isValid() ) { 00139 const bool canCreateItems = (parentCollection.rights() & Akonadi::Collection::CanCreateItem); 00140 mOkButtonEnabled = canCreateItems; 00141 } 00142 } 00143 00144 emit buttonStatusChanged(); 00145 } 00146 00147 void CollectionDialog::Private::changeCollectionDialogOptions( CollectionDialogOptions options ) 00148 { 00149 mAllowToCreateNewChildCollection = ( options & AllowToCreateNewChildCollection ); 00150 emit buttonStatusChanged(); 00151 } 00152 00153 bool CollectionDialog::Private::canCreateCollection( const Akonadi::Collection &parentCollection ) const 00154 { 00155 if ( !parentCollection.isValid() ) 00156 return false; 00157 00158 if ( ( parentCollection.rights() & Akonadi::Collection::CanCreateCollection ) ) { 00159 const QStringList dialogMimeTypeFilter = mParent->mimeTypeFilter(); 00160 const QStringList parentCollectionMimeTypes = parentCollection.contentMimeTypes(); 00161 Q_FOREACH ( const QString& mimetype, dialogMimeTypeFilter ) { 00162 if ( parentCollectionMimeTypes.contains( mimetype ) ) 00163 return true; 00164 } 00165 return true; 00166 } 00167 return false; 00168 } 00169 00170 void CollectionDialog::Private::slotAddChildCollection() 00171 { 00172 const Akonadi::Collection parentCollection = mParent->selectedCollection(); 00173 if ( canCreateCollection( parentCollection ) ) { 00174 const QString name = KInputDialog::getText( i18nc( "@title:window", "New Folder" ), 00175 i18nc( "@label:textbox, name of a thing", "Name" ), 00176 QString(), 0, mParent ); 00177 if ( name.isEmpty() ) 00178 return; 00179 00180 Akonadi::Collection collection; 00181 collection.setName( name ); 00182 collection.setParentCollection( parentCollection ); 00183 Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob( collection ); 00184 connect( job, SIGNAL( result( KJob* ) ), mParent, SLOT( slotCollectionCreationResult( KJob* ) ) ); 00185 } 00186 } 00187 00188 void CollectionDialog::Private::slotCollectionCreationResult( KJob* job ) 00189 { 00190 if ( job->error() ) { 00191 KMessageBox::error( mParent, i18n( "Could not create folder: %1", job->errorString() ), 00192 i18n( "Folder creation failed" ) ); 00193 } 00194 } 00195 00196 void CollectionDialog::Private::setDescriptionText( const QString &text ) 00197 { 00198 mDescriptionText = text; 00199 emit descriptionTextChanged(); 00200 } 00201 00202 QString CollectionDialog::Private::descriptionText() const 00203 { 00204 return mDescriptionText; 00205 } 00206 00207 bool CollectionDialog::Private::okButtonEnabled() const 00208 { 00209 return mOkButtonEnabled; 00210 } 00211 00212 bool CollectionDialog::Private::cancelButtonEnabled() const 00213 { 00214 return mCancelButtonEnabled; 00215 } 00216 00217 bool CollectionDialog::Private::createButtonEnabled() const 00218 { 00219 return mCreateButtonEnabled; 00220 } 00221 00222 bool CollectionDialog::Private::createButtonVisible() const 00223 { 00224 return mAllowToCreateNewChildCollection; 00225 } 00226 00227 void CollectionDialog::Private::okClicked() 00228 { 00229 mParent->accept(); 00230 } 00231 00232 void CollectionDialog::Private::cancelClicked() 00233 { 00234 mParent->reject(); 00235 } 00236 00237 void CollectionDialog::Private::createClicked() 00238 { 00239 slotAddChildCollection(); 00240 } 00241 00242 void CollectionDialog::Private::setCurrentIndex( int row ) 00243 { 00244 const QModelIndex index = mSelectionModel->model()->index( row, 0 ); 00245 mSelectionModel->select( index, QItemSelectionModel::ClearAndSelect ); 00246 } 00247 00248 void CollectionDialog::Private::setFilterText( const QString &text ) 00249 { 00250 mFilterModel->setFilterFixedString( text ); 00251 } 00252 00253 void CollectionDialog::Private::selectionChanged( const QItemSelection &selection, const QItemSelection& ) 00254 { 00255 if ( selection.isEmpty() ) 00256 return; 00257 00258 emit selectionChanged( selection.indexes().first().row() ); 00259 } 00260 00261 CollectionDialog::CollectionDialog( QWidget *parent ) 00262 : KDialog( parent, Qt::Window ), 00263 d( new Private( 0, this, CollectionDialog::None ) ) 00264 { 00265 } 00266 00267 CollectionDialog::CollectionDialog( QAbstractItemModel *model, QWidget *parent ) 00268 : KDialog( parent, Qt::Window ), 00269 d( new Private( model, this, CollectionDialog::None ) ) 00270 { 00271 } 00272 00273 CollectionDialog::CollectionDialog( CollectionDialogOptions options, QAbstractItemModel *model, QWidget *parent ) 00274 : KDialog( parent, Qt::Window ), 00275 d( new Private( model, this, options ) ) 00276 { 00277 } 00278 00279 00280 CollectionDialog::~CollectionDialog() 00281 { 00282 } 00283 00284 Akonadi::Collection CollectionDialog::selectedCollection() const 00285 { 00286 if ( !d->mSelectionModel->hasSelection() ) 00287 return Akonadi::Collection(); 00288 00289 return d->mSelectionModel->selectedRows().first().data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>(); 00290 } 00291 00292 Akonadi::Collection::List CollectionDialog::selectedCollections() const 00293 { 00294 if ( !d->mSelectionModel->hasSelection() ) 00295 return Akonadi::Collection::List(); 00296 00297 return (Akonadi::Collection::List() << d->mSelectionModel->selectedRows().first().data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>()); 00298 } 00299 00300 void CollectionDialog::setMimeTypeFilter( const QStringList &mimeTypes ) 00301 { 00302 d->mMimeTypeFilterModel->clearFilters(); 00303 d->mMimeTypeFilterModel->addMimeTypeFilters( mimeTypes ); 00304 } 00305 00306 QStringList CollectionDialog::mimeTypeFilter() const 00307 { 00308 return d->mMimeTypeFilterModel->mimeTypes(); 00309 } 00310 00311 void CollectionDialog::setAccessRightsFilter( Collection::Rights rights ) 00312 { 00313 d->mRightsFilterModel->setAccessRights( rights ); 00314 } 00315 00316 Akonadi::Collection::Rights CollectionDialog::accessRightsFilter() const 00317 { 00318 return d->mRightsFilterModel->accessRights(); 00319 } 00320 00321 void CollectionDialog::setDescription( const QString &text ) 00322 { 00323 d->setDescriptionText( text ); 00324 } 00325 00326 void CollectionDialog::setDefaultCollection( const Collection &collection ) 00327 { 00328 d->mSelectionHandler->waitForCollection( collection ); 00329 } 00330 00331 void CollectionDialog::setSelectionMode( QAbstractItemView::SelectionMode mode ) 00332 { 00333 d->mSelectionMode = mode; 00334 } 00335 00336 QAbstractItemView::SelectionMode CollectionDialog::selectionMode() const 00337 { 00338 return d->mSelectionMode; 00339 } 00340 00341 void CollectionDialog::changeCollectionDialogOptions( CollectionDialogOptions options ) 00342 { 00343 d->changeCollectionDialogOptions( options ); 00344 } 00345 00346 #include "collectiondialog.moc" 00347 #include "collectiondialog_mobile_p.moc"