/* * resourceselector.cpp - calendar resource selection widget * Program: kalarm * Copyright © 2006-2013 by David Jarvie * Based on KOrganizer's ResourceView class and KAddressBook's ResourceSelection class, * Copyright (C) 2003,2004 Cornelius Schumacher * Copyright (C) 2003-2004 Reinhold Kainhofer * Copyright (c) 2004 Tobias Koenig * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "resourceselector.h" #include "kalarm.h" #include "alarmcalendar.h" #include "autoqpointer.h" #ifdef USE_AKONADI #include "akonadiresourcecreator.h" #include "calendarmigrator.h" #include "kalarmapp.h" #else #include "alarmresources.h" #include "eventlistmodel.h" #include "resourcemodelview.h" #endif #include "messagebox.h" #include "packedlayout.h" #include "preferences.h" #include "resourceconfigdialog.h" #ifdef USE_AKONADI #include #include #include #include #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_AKONADI using namespace KCalCore; #else using namespace KCal; #endif #ifdef USE_AKONADI using namespace Akonadi; #endif #ifdef USE_AKONADI ResourceSelector::ResourceSelector(QWidget* parent) #else ResourceSelector::ResourceSelector(AlarmResources* calendar, QWidget* parent) #endif : QFrame(parent), #ifndef USE_AKONADI mCalendar(calendar), #endif mContextMenu(0), mActionReload(0), mActionShowDetails(0), mActionSetColour(0), mActionClearColour(0), mActionEdit(0), #ifdef USE_AKONADI mActionUpdate(0), #else mActionSave(0), #endif mActionRemove(0), mActionImport(0), mActionExport(0), mActionSetDefault(0) { QBoxLayout* topLayout = new QVBoxLayout(this); topLayout->setMargin(KDialog::spacingHint()); // use spacingHint for the margin QLabel* label = new QLabel(i18nc("@title:group", "Calendars"), this); topLayout->addWidget(label, 0, Qt::AlignHCenter); mAlarmType = new KComboBox(this); mAlarmType->addItem(i18nc("@item:inlistbox", "Active Alarms")); mAlarmType->addItem(i18nc("@item:inlistbox", "Archived Alarms")); mAlarmType->addItem(i18nc("@item:inlistbox", "Alarm Templates")); mAlarmType->setFixedHeight(mAlarmType->sizeHint().height()); mAlarmType->setWhatsThis(i18nc("@info:whatsthis", "Choose which type of data to show alarm calendars for")); topLayout->addWidget(mAlarmType); // No spacing between combo box and listview. #ifdef USE_AKONADI CollectionFilterCheckListModel* model = new CollectionFilterCheckListModel(this); mListView = new CollectionView(model, this); #else ResourceModel* model = ResourceModel::instance(); ResourceFilterModel* filterModel = new ResourceFilterModel(model, this); mListView = new ResourceView(this); mListView->setModel(filterModel); #endif connect(mListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged())); mListView->setContextMenuPolicy(Qt::CustomContextMenu); connect(mListView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(contextMenuRequested(QPoint))); mListView->setWhatsThis(i18nc("@info:whatsthis", "List of available calendars of the selected type. The checked state shows whether a calendar " "is enabled (checked) or disabled (unchecked). The default calendar is shown in bold.")); topLayout->addWidget(mListView, 1); topLayout->addSpacing(KDialog::spacingHint()); PackedLayout* blayout = new PackedLayout(Qt::AlignHCenter); blayout->setMargin(0); blayout->setSpacing(KDialog::spacingHint()); topLayout->addLayout(blayout); mAddButton = new QPushButton(i18nc("@action:button", "Add..."), this); mEditButton = new QPushButton(i18nc("@action:button", "Edit..."), this); mDeleteButton = new QPushButton(i18nc("@action:button", "Remove"), this); blayout->addWidget(mAddButton); blayout->addWidget(mEditButton); blayout->addWidget(mDeleteButton); mEditButton->setWhatsThis(i18nc("@info:whatsthis", "Edit the highlighted calendar")); mDeleteButton->setWhatsThis(i18nc("@info:whatsthis", "Remove the highlighted calendar from the list." "The calendar itself is left intact, and may subsequently be reinstated in the list if desired.")); mEditButton->setDisabled(true); mDeleteButton->setDisabled(true); connect(mAddButton, SIGNAL(clicked()), SLOT(addResource())); connect(mEditButton, SIGNAL(clicked()), SLOT(editResource())); connect(mDeleteButton, SIGNAL(clicked()), SLOT(removeResource())); #ifdef USE_AKONADI connect(AkonadiModel::instance(), SIGNAL(collectionAdded(Akonadi::Collection)), SLOT(slotCollectionAdded(Akonadi::Collection))); #else connect(mCalendar, SIGNAL(resourceStatusChanged(AlarmResource*,AlarmResources::Change)), SLOT(slotStatusChanged(AlarmResource*,AlarmResources::Change))); #endif connect(mAlarmType, SIGNAL(activated(int)), SLOT(alarmTypeSelected())); QTimer::singleShot(0, this, SLOT(alarmTypeSelected())); Preferences::connect(SIGNAL(archivedKeepDaysChanged(int)), this, SLOT(archiveDaysChanged(int))); } /****************************************************************************** * Called when an alarm type has been selected. * Filter the resource list to show resources of the selected alarm type, and * add appropriate whatsThis texts to the list and to the Add button. */ void ResourceSelector::alarmTypeSelected() { QString addTip; switch (mAlarmType->currentIndex()) { case 0: mCurrentAlarmType = CalEvent::ACTIVE; addTip = i18nc("@info:tooltip", "Add a new active alarm calendar"); break; case 1: mCurrentAlarmType = CalEvent::ARCHIVED; addTip = i18nc("@info:tooltip", "Add a new archived alarm calendar"); break; case 2: mCurrentAlarmType = CalEvent::TEMPLATE; addTip = i18nc("@info:tooltip", "Add a new alarm template calendar"); break; } // WORKAROUND: Switch scroll bars off to avoid crash (see explanation // in reinstateAlarmTypeScrollBars() description). mListView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); mListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); #ifdef USE_AKONADI mListView->collectionModel()->setEventTypeFilter(mCurrentAlarmType); #else static_cast(mListView->model())->setFilter(mCurrentAlarmType); #endif mAddButton->setWhatsThis(addTip); mAddButton->setToolTip(addTip); // WORKAROUND: Switch scroll bars back on after allowing geometry to update ... QTimer::singleShot(0, this, SLOT(reinstateAlarmTypeScrollBars())); #ifdef USE_AKONADI selectionChanged(); // enable/disable buttons #endif } /****************************************************************************** * WORKAROUND for crash due to presumed Qt bug. * Switch scroll bars off. This is to avoid a crash which can very occasionally * happen when changing from a list of calendars which requires vertical scroll * bars, to a list whose text is very slightly wider but which doesn't require * scroll bars at all. (The suspicion is that the width is such that it would * require horizontal scroll bars if the vertical scroll bars were still * present.) Presumably due to a Qt bug, this can result in a recursive call to * ResourceView::viewportEvent() with a Resize event. * * The crash only occurs if the ResourceSelector happens to have exactly (within * one pixel) the "right" width to create the crash. */ void ResourceSelector::reinstateAlarmTypeScrollBars() { mListView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); mListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); } /****************************************************************************** * Prompt the user for a new resource to add to the list. */ void ResourceSelector::addResource() { #ifdef USE_AKONADI AkonadiResourceCreator* creator = new AkonadiResourceCreator(mCurrentAlarmType, this); connect(creator, SIGNAL(finished(AkonadiResourceCreator*,bool)), SLOT(resourceAdded(AkonadiResourceCreator*,bool))); creator->createResource(); #else AlarmResourceManager* manager = mCalendar->resourceManager(); QStringList descs = manager->resourceTypeDescriptions(); bool ok = false; QString desc = KInputDialog::getItem(i18nc("@title:window", "Calendar Configuration"), i18nc("@info", "Select storage type of new calendar:"), descs, 0, false, &ok, this); if (!ok || descs.isEmpty()) return; QString type = manager->resourceTypeNames()[descs.indexOf(desc)]; AlarmResource* resource = dynamic_cast(manager->createResource(type)); if (!resource) { KAMessageBox::error(this, i18nc("@info", "Unable to create calendar of type %1.", type)); return; } resource->setResourceName(i18nc("@info/plain", "%1 calendar", type)); resource->setAlarmType(mCurrentAlarmType); resource->setActive(false); // prevent setReadOnly() declaring it as unwritable before we've tried to load it // Use AutoQPointer to guard against crash on application exit while // the dialogue is still open. It prevents double deletion (both on // deletion of ResourceSelector, and on return from this function). AutoQPointer dlg = new ResourceConfigDialog(this, resource); if (dlg->exec() == QDialog::Accepted) { resource->setEnabled(true); resource->setTimeSpec(Preferences::timeZone()); manager->add(resource); manager->writeConfig(); mCalendar->resourceAdded(resource); // load the resource and connect in-process change signals } else { delete resource; resource = 0; } #endif } #ifdef USE_AKONADI /****************************************************************************** * Called when the job started by AkonadiModel::addCollection() has completed. */ void ResourceSelector::resourceAdded(AkonadiResourceCreator* creator, bool success) { if (success) { AgentInstance agent = creator->agentInstance(); if (agent.isValid()) { // Note that we're expecting the agent's Collection to be added mAddAgents += agent; } } delete creator; } /****************************************************************************** * Called when a collection is added to the AkonadiModel. */ void ResourceSelector::slotCollectionAdded(const Collection& collection) { if (collection.isValid()) { AgentInstance agent = AgentManager::self()->instance(collection.resource()); if (agent.isValid()) { int i = mAddAgents.indexOf(agent); if (i >= 0) { // The collection belongs to an agent created by addResource() CalEvent::Types types = CalEvent::types(collection.contentMimeTypes()); CollectionControlModel::setEnabled(collection, types, true); if (!(types & mCurrentAlarmType)) { // The user has selected alarm types for the resource // which don't include the currently displayed type. // Show a collection list which includes a selected type. int index = -1; if (types & CalEvent::ACTIVE) index = 0; else if (types & CalEvent::ARCHIVED) index = 1; else if (types & CalEvent::TEMPLATE) index = 2; if (index >= 0) { mAlarmType->setCurrentIndex(index); alarmTypeSelected(); } } mAddAgents.removeAt(i); } } } } #endif /****************************************************************************** * Edit the currently selected resource. */ void ResourceSelector::editResource() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) { AgentInstance instance = AgentManager::self()->instance(collection.resource()); if (instance.isValid()) instance.configure(this); } #else AlarmResource* resource = currentResource(); if (!resource) return; bool readOnly = resource->readOnly(); // Use AutoQPointer to guard against crash on application exit while // the dialogue is still open. It prevents double deletion (both on // deletion of ResourceSelector, and on return from this function). AutoQPointer dlg = new ResourceConfigDialog(this, resource); if (dlg->exec() == QDialog::Accepted) { // Act on any changed settings. // Read-only is handled automatically by AlarmResource::setReadOnly(). if (!readOnly && resource->readOnly() && resource->standardResource()) { // A standard resource is being made read-only. if (resource->alarmType() == CalEvent::ACTIVE) { KAMessageBox::sorry(this, i18nc("@info", "You cannot make your default active alarm calendar read-only.")); resource->setReadOnly(false); } else if (resource->alarmType() == CalEvent::ARCHIVED && Preferences::archivedKeepDays()) { // Only allow the archived alarms standard resource to be made read-only // if we're not saving archived alarms. KAMessageBox::sorry(this, i18nc("@info", "You cannot make your default archived alarm calendar " "read-only while expired alarms are configured to be kept.")); resource->setReadOnly(false); } else if (KAMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to make your default calendar read-only?")) == KMessageBox::Cancel) { resource->setReadOnly(false); } } } #endif } #ifdef USE_AKONADI /****************************************************************************** * Update the backend storage format for the currently selected resource in the * displayed list. */ void ResourceSelector::updateResource() { Collection collection = currentResource(); if (!collection.isValid()) return; AkonadiModel::instance()->refresh(collection); // update with latest data CalendarMigrator::updateToCurrentFormat(collection, true, this); } #endif /****************************************************************************** * Remove the currently selected resource from the displayed list. */ void ResourceSelector::removeResource() { #ifdef USE_AKONADI Collection collection = currentResource(); if (!collection.isValid()) return; QString name = collection.name(); // Check if it's the standard or only resource for at least one type. CalEvent::Types allTypes = AkonadiModel::types(collection); CalEvent::Types standardTypes = CollectionControlModel::standardTypes(collection, true); CalEvent::Type currentType = currentResourceType(); CalEvent::Type stdType = (standardTypes & CalEvent::ACTIVE) ? CalEvent::ACTIVE : (standardTypes & CalEvent::ARCHIVED) ? CalEvent::ARCHIVED : CalEvent::EMPTY; #else AlarmResource* resource = currentResource(); if (!resource) return; QString name = resource->resourceName(); bool std = resource->standardResource(); // Check if it's the standard resource for its type. CalEvent::Type stdType = std ? resource->alarmType() : CalEvent::EMPTY; #endif if (stdType == CalEvent::ACTIVE) { KAMessageBox::sorry(this, i18nc("@info", "You cannot remove your default active alarm calendar.")); return; } if (stdType == CalEvent::ARCHIVED && Preferences::archivedKeepDays()) { // Only allow the archived alarms standard resource to be removed if // we're not saving archived alarms. KAMessageBox::sorry(this, i18nc("@info", "You cannot remove your default archived alarm calendar " "while expired alarms are configured to be kept.")); return; } #ifdef USE_AKONADI QString text; if (standardTypes) { // It's a standard resource for at least one alarm type if (allTypes != currentType) { // It also contains alarm types other than the currently displayed type QString stdTypes = CollectionControlModel::typeListForDisplay(standardTypes); QString otherTypes; CalEvent::Types nonStandardTypes(allTypes & ~standardTypes); if (nonStandardTypes != currentType) otherTypes = i18nc("@info", "It also contains:%1", CollectionControlModel::typeListForDisplay(nonStandardTypes)); text = i18nc("@info", "%1 is the default calendar for:%2%3" "Do you really want to remove it from all calendar lists?", name, stdTypes, otherTypes); } else text = i18nc("@info", "Do you really want to remove your default calendar (%1) from the list?", name); } else if (allTypes != currentType) text = i18nc("@info", "%1 contains:%2Do you really want to remove it from all calendar lists?", name, CollectionControlModel::typeListForDisplay(allTypes)); else text = i18nc("@info", "Do you really want to remove the calendar %1 from the list?", name); #else QString text = std ? i18nc("@info", "Do you really want to remove your default calendar (%1) from the list?", name) : i18nc("@info", "Do you really want to remove the calendar %1 from the list?", name); #endif if (KAMessageBox::warningContinueCancel(this, text, QString(), KStandardGuiItem::remove()) == KMessageBox::Cancel) return; #ifdef USE_AKONADI AkonadiModel::instance()->removeCollection(collection); #else // Remove resource from alarm and resource lists before deleting it, to avoid // crashes when display updates occur immediately after it is deleted. if (resource->alarmType() == CalEvent::TEMPLATE) EventListModel::templates()->removeResource(resource); else EventListModel::alarms()->removeResource(resource); ResourceModel::instance()->removeResource(resource); AlarmResourceManager* manager = mCalendar->resourceManager(); manager->remove(resource); manager->writeConfig(); #endif } /****************************************************************************** * Called when the current selection changes, to enable/disable the * Delete and Edit buttons accordingly. */ void ResourceSelector::selectionChanged() { bool state = mListView->selectionModel()->selectedRows().count(); mDeleteButton->setEnabled(state); mEditButton->setEnabled(state); } /****************************************************************************** * Initialise the button and context menu actions. */ void ResourceSelector::initActions(KActionCollection* actions) { mActionReload = new KAction(KIcon(QLatin1String("view-refresh")), i18nc("@action Reload calendar", "Re&load"), this); actions->addAction(QLatin1String("resReload"), mActionReload); connect(mActionReload, SIGNAL(triggered(bool)), SLOT(reloadResource())); #ifndef USE_AKONADI mActionSave = new KAction(KIcon(QLatin1String("document-save")), i18nc("@action", "&Save"), this); actions->addAction(QLatin1String("resSave"), mActionSave); connect(mActionSave, SIGNAL(triggered(bool)), SLOT(saveResource())); #endif mActionShowDetails = new KAction(KIcon(QLatin1String("help-about")), i18nc("@action", "Show &Details"), this); actions->addAction(QLatin1String("resDetails"), mActionShowDetails); connect(mActionShowDetails, SIGNAL(triggered(bool)), SLOT(showInfo())); mActionSetColour = new KAction(KIcon(QLatin1String("color-picker")), i18nc("@action", "Set &Color..."), this); actions->addAction(QLatin1String("resSetColour"), mActionSetColour); connect(mActionSetColour, SIGNAL(triggered(bool)), SLOT(setColour())); mActionClearColour = new KAction(i18nc("@action", "Clear C&olor"), this); actions->addAction(QLatin1String("resClearColour"), mActionClearColour); connect(mActionClearColour, SIGNAL(triggered(bool)), SLOT(clearColour())); mActionEdit = new KAction(KIcon(QLatin1String("document-properties")), i18nc("@action", "&Edit..."), this); actions->addAction(QLatin1String("resEdit"), mActionEdit); connect(mActionEdit, SIGNAL(triggered(bool)), SLOT(editResource())); #ifdef USE_AKONADI mActionUpdate = new KAction(i18nc("@action", "&Update Calendar Format"), this); actions->addAction(QLatin1String("resUpdate"), mActionUpdate); connect(mActionUpdate, SIGNAL(triggered(bool)), SLOT(updateResource())); #endif mActionRemove = new KAction(KIcon(QLatin1String("edit-delete")), i18nc("@action", "&Remove"), this); actions->addAction(QLatin1String("resRemove"), mActionRemove); connect(mActionRemove, SIGNAL(triggered(bool)), SLOT(removeResource())); mActionSetDefault = new KToggleAction(this); actions->addAction(QLatin1String("resDefault"), mActionSetDefault); connect(mActionSetDefault, SIGNAL(triggered(bool)), SLOT(setStandard())); QAction* action = new KAction(KIcon(QLatin1String("document-new")), i18nc("@action", "&Add..."), this); actions->addAction(QLatin1String("resAdd"), action); connect(action, SIGNAL(triggered(bool)), SLOT(addResource())); mActionImport = new KAction(i18nc("@action", "Im&port..."), this); actions->addAction(QLatin1String("resImport"), mActionImport); connect(mActionImport, SIGNAL(triggered(bool)), SLOT(importCalendar())); mActionExport = new KAction(i18nc("@action", "E&xport..."), this); actions->addAction(QLatin1String("resExport"), mActionExport); connect(mActionExport, SIGNAL(triggered(bool)), SLOT(exportCalendar())); } void ResourceSelector::setContextMenu(KMenu* menu) { mContextMenu = menu; } /****************************************************************************** * Display the context menu for the selected calendar. */ void ResourceSelector::contextMenuRequested(const QPoint& viewportPos) { if (!mContextMenu) return; bool active = false; bool writable = false; #ifdef USE_AKONADI bool updatable = false; Collection collection; #else AlarmResource* resource = 0; #endif if (mListView->selectionModel()->hasSelection()) { QModelIndex index = mListView->indexAt(viewportPos); if (index.isValid()) #ifdef USE_AKONADI collection = mListView->collectionModel()->collection(index); #else resource = static_cast(mListView->model())->resource(index); #endif else mListView->clearSelection(); } CalEvent::Type type = currentResourceType(); #ifdef USE_AKONADI bool haveCalendar = collection.isValid(); #else bool haveCalendar = resource; #endif if (haveCalendar) { #ifdef USE_AKONADI // Note: the CollectionControlModel functions call AkonadiModel::refresh(collection) active = CollectionControlModel::isEnabled(collection, type); KACalendar::Compat compatibility; int rw = CollectionControlModel::isWritableEnabled(collection, type, compatibility); writable = (rw > 0); if (!rw && (compatibility & ~KACalendar::Converted) && !(compatibility & ~(KACalendar::Convertible | KACalendar::Converted))) updatable = true; // the calendar format is convertible to the current KAlarm format if (!(AkonadiModel::instance()->types(collection) & type)) type = CalEvent::EMPTY; #else active = resource->isEnabled(); type = resource->alarmType(); writable = resource->writable(); #endif } mActionReload->setEnabled(active); mActionShowDetails->setEnabled(haveCalendar); mActionSetColour->setEnabled(haveCalendar); mActionClearColour->setEnabled(haveCalendar); #ifdef USE_AKONADI mActionClearColour->setVisible(AkonadiModel::instance()->backgroundColor(collection).isValid()); #else mActionClearColour->setVisible(resource && resource->colour().isValid()); mActionSave->setEnabled(active && writable); #endif mActionEdit->setEnabled(haveCalendar); #ifdef USE_AKONADI mActionUpdate->setEnabled(updatable); #endif mActionRemove->setEnabled(haveCalendar); mActionImport->setEnabled(active && writable); mActionExport->setEnabled(active); QString text; switch (type) { case CalEvent::ACTIVE: text = i18nc("@action", "Use as &Default for Active Alarms"); break; case CalEvent::ARCHIVED: text = i18nc("@action", "Use as &Default for Archived Alarms"); break; case CalEvent::TEMPLATE: text = i18nc("@action", "Use as &Default for Alarm Templates"); break; default: break; } mActionSetDefault->setText(text); #ifdef USE_AKONADI bool standard = CollectionControlModel::isStandard(collection, type); #else bool standard = (resource && resource == mCalendar->getStandardResource(static_cast(type)) && resource->standardResource()); #endif mActionSetDefault->setChecked(active && writable && standard); mActionSetDefault->setEnabled(active && writable); mContextMenu->popup(mListView->viewport()->mapToGlobal(viewportPos)); } /****************************************************************************** * Called from the context menu to reload the selected resource. */ void ResourceSelector::reloadResource() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) AkonadiModel::instance()->reloadCollection(collection); #else AlarmResource* resource = currentResource(); if (resource) AlarmCalendar::resources()->loadResource(resource, this); #endif } /****************************************************************************** * Called from the context menu to save the selected resource. */ void ResourceSelector::saveResource() { #ifdef USE_AKONADI // Save resource is not applicable to Akonadi #else AlarmResource* resource = currentResource(); if (resource) resource->save(); #endif } /****************************************************************************** * Called when the length of time archived alarms are to be stored changes. * If expired alarms are now to be stored, set any single archived alarm * resource to be the default. */ void ResourceSelector::archiveDaysChanged(int days) { if (days) { #ifdef USE_AKONADI if (!CollectionControlModel::getStandard(CalEvent::ARCHIVED).isValid()) { Collection::List cols = CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, true); if (cols.count() == 1) { CollectionControlModel::setStandard(cols[0], CalEvent::ARCHIVED); theApp()->purgeNewArchivedDefault(cols[0]); } } #else AlarmResources* resources = AlarmResources::instance(); AlarmResource* std = resources->getStandardResource(CalEvent::ARCHIVED); if (std && !std->standardResource()) resources->setStandardResource(std); #endif } } /****************************************************************************** * Called from the context menu to set the selected resource as the default * for its alarm type. The resource is automatically made active. */ void ResourceSelector::setStandard() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) { CalEvent::Type alarmType = currentResourceType(); bool standard = mActionSetDefault->isChecked(); if (standard) CollectionControlModel::setEnabled(collection, alarmType, true); CollectionControlModel::setStandard(collection, alarmType, standard); if (alarmType == CalEvent::ARCHIVED) theApp()->purgeNewArchivedDefault(collection); } #else AlarmResource* resource = currentResource(); if (resource) { if (mActionSetDefault->isChecked()) { resource->setEnabled(true); mCalendar->setStandardResource(resource); } else resource->setStandardResource(false); } #endif } #ifndef USE_AKONADI /****************************************************************************** * Called when a calendar status has changed. */ void ResourceSelector::slotStatusChanged(AlarmResource* resource, AlarmResources::Change change) { if (change == AlarmResources::WrongType && resource->isWrongAlarmType()) { QString text; switch (resource->alarmType()) { case CalEvent::ACTIVE: text = i18nc("@info/plain", "It is not an active alarm calendar."); break; case CalEvent::ARCHIVED: text = i18nc("@info/plain", "It is not an archived alarm calendar."); break; case CalEvent::TEMPLATE: text = i18nc("@info/plain", "It is not an alarm template calendar."); break; default: return; } KAMessageBox::sorry(this, i18nc("@info", "Calendar %1 has been disabled:%2", resource->resourceName(), text)); } } #endif /****************************************************************************** * Called from the context menu to merge alarms from an external calendar into * the selected resource (if any). */ void ResourceSelector::importCalendar() { #ifdef USE_AKONADI Collection collection = currentResource(); AlarmCalendar::importAlarms(this, (collection.isValid() ? &collection : 0)); #else AlarmCalendar::importAlarms(this, currentResource()); #endif } /****************************************************************************** * Called from the context menu to copy the selected resource's alarms to an * external calendar. */ void ResourceSelector::exportCalendar() { #ifdef USE_AKONADI Collection calendar = currentResource(); if (calendar.isValid()) #else AlarmResource* calendar = currentResource(); if (calendar) #endif AlarmCalendar::exportAlarms(AlarmCalendar::resources()->events(calendar), this); } /****************************************************************************** * Called from the context menu to set a colour for the selected resource. */ void ResourceSelector::setColour() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) { QColor colour = AkonadiModel::instance()->backgroundColor(collection); if (!colour.isValid()) colour = QApplication::palette().color(QPalette::Base); if (KColorDialog::getColor(colour, QColor(), this) == KColorDialog::Accepted) AkonadiModel::instance()->setBackgroundColor(collection, colour); } #else AlarmResource* resource = currentResource(); if (resource) { QColor colour = resource->colour(); if (!colour.isValid()) colour = QApplication::palette().color(QPalette::Base); if (KColorDialog::getColor(colour, QColor(), this) == KColorDialog::Accepted) resource->setColour(colour); } #endif } /****************************************************************************** * Called from the context menu to clear the display colour for the selected * resource. */ void ResourceSelector::clearColour() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) AkonadiModel::instance()->setBackgroundColor(collection, QColor()); #else AlarmResource* resource = currentResource(); if (resource) resource->setColour(QColor()); #endif } /****************************************************************************** * Called from the context menu to display information for the selected resource. */ void ResourceSelector::showInfo() { #ifdef USE_AKONADI Collection collection = currentResource(); if (collection.isValid()) { const QString name = collection.displayName(); QString id = collection.resource(); // resource name CalEvent::Type alarmType = currentResourceType(); QString calType = AgentManager::self()->instance(id).type().name(); QString storage = AkonadiModel::instance()->storageType(collection); QString location = collection.remoteId(); KUrl url(location); if (url.isLocalFile()) location = url.path(); CalEvent::Types altypes = AkonadiModel::instance()->types(collection); QStringList alarmTypes; if (altypes & CalEvent::ACTIVE) alarmTypes << i18nc("@info/plain", "Active alarms"); if (altypes & CalEvent::ARCHIVED) alarmTypes << i18nc("@info/plain", "Archived alarms"); if (altypes & CalEvent::TEMPLATE) alarmTypes << i18nc("@info/plain", "Alarm templates"); QString alarmTypeString = alarmTypes.join(i18nc("@info/plain List separator", ", ")); KACalendar::Compat compat; QString perms = AkonadiModel::readOnlyTooltip(collection); if (perms.isEmpty()) perms = i18nc("@info/plain", "Read-write"); QString enabled = CollectionControlModel::isEnabled(collection, alarmType) ? i18nc("@info/plain", "Enabled") : i18nc("@info/plain", "Disabled"); QString std = CollectionControlModel::isStandard(collection, alarmType) ? i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "Yes") : i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "No"); QString text = i18nc("@info", "%1" "ID: %2" "Calendar type: %3" "Contents: %4" "%5: %6" "Permissions: %7" "Status: %8" "Default calendar: %9", name, id, calType, alarmTypeString, storage, location, perms, enabled, std); // Display the collection information. Because the user requested // the information, don't raise a KNotify event. KAMessageBox::information(this, text, QString(), QString(), 0); } #else AlarmResource* resource = currentResource(); if (resource) { // Display the collection information. Because the user requested // the information, don't raise a KNotify event. KAMessageBox::information(this, resource->infoText(), QString(), QString(), 0); } #endif } /****************************************************************************** * Return the currently selected resource in the list. */ #ifdef USE_AKONADI Collection ResourceSelector::currentResource() const { return mListView->collection(mListView->selectionModel()->currentIndex()); } #else AlarmResource* ResourceSelector::currentResource() const { return mListView->resource(mListView->selectionModel()->currentIndex()); } #endif /****************************************************************************** * Return the currently selected resource type. */ CalEvent::Type ResourceSelector::currentResourceType() const { switch (mAlarmType->currentIndex()) { case 0: return CalEvent::ACTIVE; case 1: return CalEvent::ARCHIVED; case 2: return CalEvent::TEMPLATE; default: return CalEvent::EMPTY; } } void ResourceSelector::resizeEvent(QResizeEvent* re) { emit resized(re->oldSize(), re->size()); } // vim: et sw=4: