35 #include <calendarsupport/kcalprefs.h>
36 #include <calendarsupport/utils.h>
38 #include <Akonadi/AgentFilterProxyModel>
39 #include <Akonadi/AgentInstanceCreateJob>
40 #include <Akonadi/AgentManager>
41 #include <Akonadi/AgentTypeDialog>
42 #include <Akonadi/CollectionDeleteJob>
43 #include <Akonadi/CollectionFilterProxyModel>
44 #include <Akonadi/EntityDisplayAttribute>
45 #include <Akonadi/EntityTreeView>
46 #include <Akonadi/EntityTreeModel>
47 #include <Akonadi/ETMViewStateSaver>
48 #include <Akonadi/Calendar/StandardCalendarActionManager>
51 #include <KActionCollection>
52 #include <KCheckableProxyModel>
53 #include <KColorDialog>
54 #include <KMessageBox>
55 #include <KRecursiveFilterProxyModel>
57 #include <QHeaderView>
59 #include <QStyledItemDelegate>
60 #include <QVBoxLayout>
63 : mView( view ), mAkonadiCollectionView( 0 )
69 static bool hasCompatibleMimeTypes(
const Akonadi::Collection &collection )
73 if ( goodMimeTypes.
isEmpty() ) {
75 << KCalCore::Event::eventMimeType()
76 << KCalCore::Todo::todoMimeType()
77 << KCalCore::Journal::journalMimeType();
80 for (
int i=0; i<goodMimeTypes.
count(); ++i ) {
81 if ( collection.contentMimeTypes().contains( goodMimeTypes.
at( i ) ) ) {
101 initStyleOption( &v4, index );
102 if ( v4.checkState == Qt::Checked ) {
103 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
105 if ( color.
isValid() && (collection.remoteId() !=
QLatin1String(
"akonadi_birthdays_resource")) ) {
107 const int h = r.
height() - 4;
127 explicit ColorProxyModel(
QObject *parent=0 )
138 if ( role == Qt::DecorationRole ) {
139 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
141 if ( hasCompatibleMimeTypes( collection ) ) {
142 if ( collection.hasAttribute<Akonadi::EntityDisplayAttribute>() &&
143 !collection.attribute<Akonadi::EntityDisplayAttribute>()->iconName().isEmpty() ) {
144 return collection.attribute<Akonadi::EntityDisplayAttribute>()->icon();
147 }
else if ( role == Qt::FontRole ) {
148 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
149 if ( !collection.contentMimeTypes().isEmpty() &&
151 collection.rights() & Akonadi::Collection::CanCreateItem ) {
154 if ( !mInitDefaultCalendar ) {
155 mInitDefaultCalendar =
true;
156 CalendarSupport::KCalPrefs::instance()->setDefaultCalendarId( collection.id() );
172 mutable bool mInitDefaultCalendar;
181 mView, SLOT(resourcesChanged()) );
183 mView, SLOT(resourcesChanged()) );
184 return mAkonadiCollectionView;
194 return mAkonadiCollectionView;
203 mSelectionProxyModel( 0 ),
204 mNotSendAddRemoveSignal( false ),
205 mWasDefaultCalendar( false ),
206 mHasContextMenu( hasContextMenu )
210 topLayout->
setSpacing( KDialog::spacingHint() );
218 ColorProxyModel *colorProxy =
new ColorProxyModel(
this );
219 colorProxy->setObjectName(
QLatin1String(
"Show calendar colors") );
220 colorProxy->setDynamicSortFilter(
true );
221 mBaseModel = colorProxy;
223 mCollectionView =
new Akonadi::EntityTreeView(
this );
225 mCollectionView->header()->hide();
226 mCollectionView->setRootIsDecorated(
true );
227 mCollectionView->setItemDelegate(
new ColorDelegate(
this ) );
235 mCollectionView->setModel( colorProxy );
236 connect( mCollectionView->selectionModel(),
238 SLOT(updateMenu()) );
252 mCollectionView->setXmlGuiClient( xmlclient );
255 new Akonadi::StandardCalendarActionManager( xmlclient->actionCollection(), mCollectionView );
258 standardActions << Akonadi::StandardActionManager::CreateCollection
259 << Akonadi::StandardActionManager::DeleteCollections
260 << Akonadi::StandardActionManager::SynchronizeCollections
261 << Akonadi::StandardActionManager::CollectionProperties
262 << Akonadi::StandardActionManager::CopyItems
263 << Akonadi::StandardActionManager::Paste
264 << Akonadi::StandardActionManager::DeleteItems
265 << Akonadi::StandardActionManager::CutItems
266 << Akonadi::StandardActionManager::CreateResource
267 << Akonadi::StandardActionManager::DeleteResources
268 << Akonadi::StandardActionManager::ResourceProperties
269 << Akonadi::StandardActionManager::SynchronizeResources
270 << Akonadi::StandardActionManager::SynchronizeCollectionsRecursive
271 << Akonadi::StandardActionManager::CopyCollectionToMenu
272 << Akonadi::StandardActionManager::MoveCollectionToMenu;
274 Q_FOREACH( Akonadi::StandardActionManager::Type standardAction, standardActions ) {
275 mActionManager->createAction( standardAction );
279 calendarActions << Akonadi::StandardCalendarActionManager::CreateEvent
280 << Akonadi::StandardCalendarActionManager::CreateTodo
281 << Akonadi::StandardCalendarActionManager::CreateSubTodo
282 << Akonadi::StandardCalendarActionManager::CreateJournal
283 << Akonadi::StandardCalendarActionManager::EditIncidence;
285 Q_FOREACH( Akonadi::StandardCalendarActionManager::Type calendarAction, calendarActions ) {
286 mActionManager->createAction( calendarAction );
289 mActionManager->setCollectionSelectionModel( mCollectionView->selectionModel() );
291 mActionManager->interceptAction( Akonadi::StandardActionManager::CreateResource );
292 mActionManager->interceptAction( Akonadi::StandardActionManager::DeleteResources );
293 mActionManager->interceptAction( Akonadi::StandardActionManager::DeleteCollections );
295 connect( mActionManager->action( Akonadi::StandardActionManager::CreateResource ),
296 SIGNAL(triggered(
bool)),
297 this, SLOT(newCalendar()) );
298 connect( mActionManager->action( Akonadi::StandardActionManager::DeleteResources ),
299 SIGNAL(triggered(
bool)),
300 this, SLOT(deleteCalendar()) );
301 connect( mActionManager->action( Akonadi::StandardActionManager::DeleteCollections ),
302 SIGNAL(triggered(
bool)),
303 this, SLOT(deleteCalendar()) );
305 mActionManager->setContextText( Akonadi::StandardActionManager::CollectionProperties,
306 Akonadi::StandardActionManager::DialogTitle,
307 ki18nc(
"@title:window",
"Properties of Calendar Folder %1" ) );
314 mActionManager->setCollectionPropertiesPageNames( pages );
316 mDisableColor =
new KAction( mCollectionView );
317 mDisableColor->setText( i18n(
"&Disable Color" ) );
318 mDisableColor->setEnabled(
false );
321 connect( mDisableColor, SIGNAL(triggered(
bool)),
this, SLOT(disableColor()) );
323 mAssignColor =
new KAction( mCollectionView );
324 mAssignColor->setText( i18n(
"&Assign Color..." ) );
325 mAssignColor->setEnabled(
false );
326 xmlclient->actionCollection()->addAction(
QString::fromLatin1(
"assign_color" ), mAssignColor );
327 connect( mAssignColor, SIGNAL(triggered(
bool)),
this, SLOT(assignColor()) );
329 mDefaultCalendar =
new KAction( mCollectionView );
330 mDefaultCalendar->setText( i18n(
"Use as &Default Calendar" ) );
331 mDefaultCalendar->setEnabled(
false );
334 connect( mDefaultCalendar, SIGNAL(triggered(
bool)),
this, SLOT(setDefaultCalendar()) );
340 Akonadi::ETMViewStateSaver treeStateSaver;
341 KConfigGroup group(
KOGlobals::self()->config(),
"CollectionTreeView" );
342 treeStateSaver.setView( mCollectionView );
343 treeStateSaver.setSelectionModel( 0 );
344 treeStateSaver.saveState( group );
347 void AkonadiCollectionView::restoreTreeState()
350 if ( treeStateRestorer ) {
351 delete treeStateRestorer;
353 treeStateRestorer =
new Akonadi::ETMViewStateSaver();
354 KConfigGroup group(
KOGlobals::self()->config(),
"CollectionTreeView" );
355 treeStateRestorer->setView( mCollectionView );
356 treeStateRestorer->setSelectionModel( 0 );
357 treeStateRestorer->restoreState( group );
360 void AkonadiCollectionView::setDefaultCalendar()
362 QModelIndex index = mCollectionView->selectionModel()->currentIndex();
364 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
365 CalendarSupport::KCalPrefs::instance()->setDefaultCalendarId( collection.id() );
366 CalendarSupport::KCalPrefs::instance()->usrWriteConfig();
373 void AkonadiCollectionView::assignColor()
375 QModelIndex index = mCollectionView->selectionModel()->currentIndex();
377 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
378 Q_ASSERT( collection.isValid() );
383 const int result = KColorDialog::getColor( myColor, defaultColor );
384 if ( result == KColorDialog::Accepted && myColor != defaultColor ) {
392 void AkonadiCollectionView::disableColor()
394 QModelIndex index = mCollectionView->selectionModel()->currentIndex();
396 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
397 Q_ASSERT( collection.isValid() );
407 if ( mSelectionProxyModel == m ) {
411 mSelectionProxyModel = m;
412 if ( !mSelectionProxyModel ) {
421 return mSelectionProxyModel;
426 return mCollectionView;
429 void AkonadiCollectionView::updateView()
432 mSelectionProxyModel->selectionModel()->hasSelection() :
436 void AkonadiCollectionView::updateMenu()
438 if ( !mHasContextMenu ) {
441 bool enableAction = mCollectionView->selectionModel()->hasSelection();
442 enableAction = enableAction &&
444 mAssignColor->setEnabled( enableAction );
445 QModelIndex index = mCollectionView->selectionModel()->currentIndex();
447 bool disableStuff =
false;
450 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
451 Q_ASSERT( collection.isValid() );
452 if ( !collection.contentMimeTypes().isEmpty() ) {
455 enableAction = enableAction && defaultColor.
isValid();
456 if (collection.remoteId() ==
QLatin1String(
"akonadi_birthdays_resource")) {
457 enableAction =
false;
458 mAssignColor->setEnabled( enableAction );
460 mDisableColor->setEnabled( enableAction );
462 collection.rights() & Akonadi::Collection::CanCreateItem );
471 if ( disableStuff ) {
472 mDisableColor->setEnabled(
false );
473 mDefaultCalendar->setEnabled(
false );
474 mAssignColor->setEnabled(
false );
478 void AkonadiCollectionView::newCalendar()
480 Akonadi::AgentTypeDialog dlg(
this );
481 dlg.setWindowTitle( i18n(
"Add Calendar" ) );
483 dlg.agentFilterProxyModel()->addCapabilityFilter(
QLatin1String(
"Resource") );
485 mNotSendAddRemoveSignal =
true;
486 const Akonadi::AgentType agentType = dlg.agentType();
487 if ( agentType.isValid() ) {
488 Akonadi::AgentInstanceCreateJob *job =
new Akonadi::AgentInstanceCreateJob( agentType,
this );
489 job->configure(
this );
490 connect( job, SIGNAL(result(
KJob*)),
this, SLOT(newCalendarDone(
KJob*)) );
496 void AkonadiCollectionView::newCalendarDone(
KJob *job )
498 Akonadi::AgentInstanceCreateJob *createjob =
static_cast<Akonadi::AgentInstanceCreateJob*
>( job );
499 if ( createjob->error() ) {
503 kWarning() <<
"Create calendar failed:" << createjob->errorString();
504 mNotSendAddRemoveSignal =
false;
507 mNotSendAddRemoveSignal =
false;
511 void AkonadiCollectionView::deleteCalendar()
513 QModelIndex index = mCollectionView->selectionModel()->currentIndex();
515 const Akonadi::Collection collection = CalendarSupport::collectionFromIndex( index );
516 Q_ASSERT( collection.isValid() );
519 Q_ASSERT( !displayname.isEmpty() );
521 if ( KMessageBox::warningContinueCancel(
523 i18n(
"Do you really want to delete calendar %1?", displayname ),
524 i18n(
"Delete Calendar" ),
525 KStandardGuiItem::del(),
526 KStandardGuiItem::cancel(),
528 KMessageBox::Dangerous ) == KMessageBox::Continue ) {
530 bool isTopLevel = collection.parentCollection() == Akonadi::Collection::root();
532 mNotSendAddRemoveSignal =
true;
537 Akonadi::CollectionDeleteJob *job =
new Akonadi::CollectionDeleteJob( collection,
this );
538 connect( job, SIGNAL(result(
KJob*)),
this, SLOT(deleteCalendarDone(
KJob*)) );
541 const Akonadi::AgentInstance instance =
542 Akonadi::AgentManager::self()->instance( collection.resource() );
543 if ( instance.isValid() ) {
544 Akonadi::AgentManager::self()->removeInstance( instance );
550 void AkonadiCollectionView::deleteCalendarDone(
KJob *job )
552 Akonadi::CollectionDeleteJob *deletejob =
static_cast<Akonadi::CollectionDeleteJob*
>( job );
553 if ( deletejob->error() ) {
554 kWarning() <<
"Delete calendar failed:" << deletejob->errorString();
555 mNotSendAddRemoveSignal =
false;
558 if ( mWasDefaultCalendar ) {
559 CalendarSupport::KCalPrefs::instance()->setDefaultCalendarId( Akonadi::Collection().
id() );
561 mNotSendAddRemoveSignal =
false;
565 void AkonadiCollectionView::rowsInserted(
const QModelIndex &,
int,
int )
567 if ( !mNotSendAddRemoveSignal ) {
575 Akonadi::Collection collection;
577 if ( !selectionModel ) {
581 if ( !indexes.isEmpty() ) {
582 collection = indexes.first().data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>();
589 Akonadi::Collection::List collections;
590 if ( !mSelectionProxyModel ) {
594 if ( !selectionModel ) {
600 Akonadi::Collection collection = index.
data( Akonadi::EntityTreeModel::CollectionRole ).
value<Akonadi::Collection>();
601 if ( collection.isValid() )
602 collections << collection;
610 if (!mSelectionProxyModel)
618 Akonadi::Collection c = index.
data(Akonadi::EntityTreeModel::CollectionRole).
value<Akonadi::Collection>();
619 if (c.id() == collection.id()) {
627 Akonadi::EntityTreeModel *AkonadiCollectionView::entityTreeModel()
const
631 Akonadi::EntityTreeModel *etm = qobject_cast<Akonadi::EntityTreeModel*>( proxy->
sourceModel() );
638 kWarning() <<
"Couldn't find EntityTreeModel";
642 void AkonadiCollectionView::checkNewCalendar(
const QModelIndex &parent,
int begin,
int end )
650 Akonadi::EntityTreeModel *etm = entityTreeModel();
651 if ( etm && etm->isCollectionTreeFetched() ) {
653 for (
int row = begin; row <= end; ++row ) {
656 model->
setData( index, Qt::Checked, Qt::CheckStateRole );
657 checkNewCalendar( index, 0, model->
rowCount(index) - 1 );
661 mCollectionView->setExpanded( parent,
true );
virtual int rowCount(const QModelIndex &parent) const =0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
KCheckableProxyModel * collectionSelectionProxyModel() const
void setResourceColor(const QString &, const QColor &)
AkonadiCollectionView(CalendarView *view, bool hasContextMenu=true, QWidget *parent=0)
virtual Qt::ItemFlags flags(const QModelIndex &index) const
void setRenderHint(RenderHint hint, bool on)
void strokePath(const QPainterPath &path, const QPen &pen)
KXMLGUIClient * xmlguiClient(QWidget *) const
const T & at(int i) const
Akonadi::EntityTreeView * view() const
void addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
CalendarViewExtension * create(QWidget *)
AkonadiCollectionView * collectionView() const
void setBold(bool enable)
QString number(int n, int base)
int count(const T &value) const
This is the main calendar widget.
void fillPath(const QPainterPath &path, const QBrush &brush)
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
QModelIndexList selectedIndexes() const
CalendarView * view() const
virtual void setSourceModel(QAbstractItemModel *sourceModel)
virtual QVariant data(const QModelIndex &index, int role) const =0
void setColor(const QColor &color)
void setMargin(int margin)
Akonadi::Collection::List checkedCollections() const
AkonadiCollectionViewFactory(CalendarView *view)
Akonadi::Collection selectedCollection() const
static KOGlobals * self()
QAbstractItemModel * sourceModel() const
const QAbstractItemModel * model() const
This class provides a view of calendar resources.
QVariant data(int role) const
void resourcesChanged(bool enabled)
void resourcesAddedRemoved()
KORGANIZERPRIVATE_EXPORT QColor resourceColor(const Akonadi::Item &incidence)
This method returns the proper resource / subresource color for the view.
void adjust(int dx1, int dy1, int dx2, int dy2)
static KOPrefs * instance()
Get instance of KOPrefs.
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
bool isChecked(const Akonadi::Collection &) const
QString fromLatin1(const char *str, int size)
void setCollectionSelectionProxyModel(KCheckableProxyModel *)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KORGANIZERPRIVATE_EXPORT bool isStandardCalendar(const Akonadi::Entity::Id &id)
Return true if it's the standard calendar.
QColor resourceColor(const QString &)
void setSpacing(int spacing)
virtual QVariant data(const QModelIndex &index, int role) const
void defaultResourceChanged(const Akonadi::Collection &)