/* This file is part of KOrganizer. Copyright (c) 2003,2004 Cornelius Schumacher Copyright (C) 2003-2004 Reinhold Kainhofer 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "resourceview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "koprefs.h" using namespace KCal; ResourceViewFactory::ResourceViewFactory( KCal::CalendarResources *calendar, CalendarView *view ) : mCalendar( calendar ), mView( view ), mResourceView( 0 ) { } CalendarViewExtension *ResourceViewFactory::create( QWidget *parent ) { mResourceView = new ResourceView( mCalendar, parent ); QObject::connect( mResourceView, SIGNAL( resourcesChanged() ), mView, SLOT( resourcesChanged() ) ); QObject::connect( mResourceView, SIGNAL( resourcesChanged() ), mView, SLOT( updateCategories() ) ); QObject::connect( mCalendar, SIGNAL( signalResourceAdded( ResourceCalendar * ) ), mResourceView, SLOT( addResourceItem( ResourceCalendar * ) ) ); QObject::connect( mCalendar, SIGNAL( signalResourceModified( ResourceCalendar * ) ), mResourceView, SLOT( updateResourceItem( ResourceCalendar * ) ) ); QObject::connect( mCalendar, SIGNAL( signalResourceAdded( ResourceCalendar * ) ), mView, SLOT( updateCategories() ) ); QObject::connect( mCalendar, SIGNAL( signalResourceModified( ResourceCalendar * ) ), mView, SLOT( updateCategories() ) ); return mResourceView; } ResourceView *ResourceViewFactory::resourceView() const { return mResourceView; } ResourceItem::ResourceItem( ResourceCalendar *resource, ResourceView *view, KListView *parent ) : QCheckListItem( parent, resource->resourceName(), CheckBox ), mResource( resource ), mView( view ), mBlockStateChange( false ), mIsSubresource( false ), mResourceIdentifier( QString::null ), mSubItemsCreated( false ), mIsStandardResource( false ) { mResourceColor = QColor(); setGuiState(); if ( mResource->isActive() ) { createSubresourceItems(); } } void ResourceItem::createSubresourceItems() { const QStringList subresources = mResource->subresources(); if ( !subresources.isEmpty() ) { setOpen( true ); setExpandable( true ); // This resource has subresources QStringList::ConstIterator it; for ( it=subresources.begin(); it!=subresources.end(); ++it ) { ResourceItem *item = new ResourceItem( mResource, *it, mResource->labelForSubresource( *it ), mView, this ); QColor resourceColor = *KOPrefs::instance()->resourceColor( *it ); item->setResourceColor( resourceColor ); item->update(); } } mSubItemsCreated = true; } ResourceItem::ResourceItem( KCal::ResourceCalendar *resource, const QString& sub, const QString& label, ResourceView *view, ResourceItem* parent ) : QCheckListItem( parent, label, CheckBox ), mResource( resource ), mView( view ), mBlockStateChange( false ), mIsSubresource( true ), mSubItemsCreated( false ), mIsStandardResource( false ) { mResourceColor = QColor(); mResourceIdentifier = sub; setGuiState(); } void ResourceItem::setGuiState() { mBlockStateChange = true; if ( mIsSubresource ) setOn( mResource->subresourceActive( mResourceIdentifier ) ); else setOn( mResource->isActive() ); mBlockStateChange = false; } void ResourceItem::stateChange( bool active ) { if ( mBlockStateChange ) return; if ( mIsSubresource ) { mResource->setSubresourceActive( mResourceIdentifier, active ); } else { if ( active ) { if ( mResource->load() ) { mResource->setActive( true ); if ( !mSubItemsCreated ) createSubresourceItems(); } } else { // mView->requestClose must be called before mResource->save() because // save causes closeResource do be called. mView->requestClose( mResource ); if ( mResource->save() ) mResource->setActive( false ); } setOpen( mResource->isActive() && childCount() > 0 ); setGuiState(); } mView->emitResourcesChanged(); } void ResourceItem::update() { setGuiState(); } void ResourceItem::setResourceColor(QColor& color) { if ( color.isValid() ) { if ( mResourceColor != color ) { QPixmap px(height()-4,height()-4); mResourceColor = color; px.fill(color); setPixmap(0,px); } } else { mResourceColor = color ; setPixmap(0,0); } } void ResourceItem::setStandardResource( bool std ) { if ( mIsStandardResource != std ) { mIsStandardResource = std; repaint(); } } void ResourceItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) { QFont oldFont = p->font(); QFont newFont = oldFont; newFont.setBold( mIsStandardResource && !mIsSubresource ); p->setFont( newFont ); QCheckListItem::paintCell( p, cg, column, width, alignment ); p->setFont( oldFont ); /* QColorGroup _cg = cg; if(!mResource) return; _cg.setColor(QColorGroup::Base, getTextColor(mResourceColor));*/ } ResourceView::ResourceView( KCal::CalendarResources *calendar, QWidget *parent, const char *name ) : CalendarViewExtension( parent, name ), mCalendar( calendar ) { QBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); QHBoxLayout *buttonBox = new QHBoxLayout(); buttonBox->setSpacing( KDialog::spacingHint() ); topLayout->addLayout( buttonBox ); QLabel *calLabel = new QLabel( i18n( "Calendar" ), this ); buttonBox->addWidget( calLabel ); buttonBox->addStretch( 1 ); mAddButton = new QPushButton( this, "add" ); mAddButton->setIconSet( SmallIconSet( "add" ) ); buttonBox->addWidget( mAddButton ); QToolTip::add( mAddButton, i18n( "Add calendar" ) ); QWhatsThis::add( mAddButton, i18n( "

Press this button to add a resource to " "KOrganizer.

" "

Events, journal entries and to-dos are retrieved " "and stored on resources. Available " "resources include groupware servers, local files, " "journal entries as blogs on a server, etc...

" "

If you have more than one active resource, " "when creating incidents you will either automatically " "use the default resource or be prompted " "to select the resource to use.

" ) ); mEditButton = new QPushButton( this, "edit" ); mEditButton->setIconSet( SmallIconSet( "edit" ) ); buttonBox->addWidget( mEditButton ); QToolTip::add( mEditButton, i18n( "Edit calendar settings" ) ); QWhatsThis::add( mEditButton, i18n( "Press this button to edit the resource currently " "selected on the KOrganizer resources list above." ) ); mDeleteButton = new QPushButton( this, "del" ); mDeleteButton->setIconSet( SmallIconSet( "remove" ) ); buttonBox->addWidget( mDeleteButton ); QToolTip::add( mDeleteButton, i18n( "Remove calendar" ) ); QWhatsThis::add( mDeleteButton, i18n( "Press this button to delete the resource currently " "selected on the KOrganizer resources list above." ) ); mDeleteButton->setDisabled( true ); mEditButton->setDisabled( true ); mListView = new KListView( this ); mListView->header()->hide(); QWhatsThis::add( mListView, i18n( "

Select on this list the active KOrganizer " "resources. Check the resource box to make it " "active. Press the \"Add...\" button below to add new " "resources to the list.

" "

Events, journal entries and to-dos are retrieved " "and stored on resources. Available " "resources include groupware servers, local files, " "journal entries as blogs on a server, etc...

" "

If you have more than one active resource, " "when creating incidents you will either automatically " "use the default resource or be prompted " "to select the resource to use.

" ) ); mListView->addColumn( i18n("Calendar") ); mListView->setResizeMode( QListView::LastColumn ); topLayout->addWidget( mListView ); connect( mListView, SIGNAL( clicked( QListViewItem * ) ), SLOT( currentChanged( QListViewItem * ) ) ); connect( mAddButton, SIGNAL( clicked() ), SLOT( addResource() ) ); connect( mDeleteButton, SIGNAL( clicked() ), SLOT( removeResource() ) ); connect( mEditButton, SIGNAL( clicked() ), SLOT( editResource() ) ); connect( mListView, SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int ) ), SLOT( editResource() ) ); connect( mListView, SIGNAL( contextMenuRequested ( QListViewItem *, const QPoint &, int ) ), SLOT( contextMenuRequested( QListViewItem *, const QPoint &, int ) ) ); updateView(); } ResourceView::~ResourceView() { } void ResourceView::updateView() { mListView->clear(); KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); KCal::CalendarResourceManager::Iterator it; for( it = manager->begin(); it != manager->end(); ++it ) { addResourceItem( *it ); } } void ResourceView::emitResourcesChanged() { mCalendar->resourceManager()->writeConfig(); emit resourcesChanged(); } void ResourceView::addResource() { bool ok = false; KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); ResourceItem *i = static_cast( mListView->selectedItem() ); if ( i && ( i->isSubresource() || i->resource()->canHaveSubresources() ) ) { const QString folderName = KInputDialog::getText( i18n( "Add Subresource" ), i18n( "Please enter a name for the new subresource" ), QString::null, &ok, this ); if ( !ok ) return; const QString parentId = i->isSubresource() ? i->resourceIdentifier() : QString:: null; if ( !i->resource()->addSubresource( folderName, parentId ) ) { KMessageBox::error( this, i18n("Unable to create subresource %1.") .arg( folderName ) ); } return; } QStringList types = manager->resourceTypeNames(); QStringList descs = manager->resourceTypeDescriptions(); QString desc = KInputDialog::getItem( i18n( "Resource Configuration" ), i18n( "Please select type of the new resource:" ), descs, 0, false, &ok, this ); if ( !ok ) return; QString type = types[ descs.findIndex( desc ) ]; // Create new resource ResourceCalendar *resource = manager->createResource( type ); if( !resource ) { KMessageBox::error( this, i18n("Unable to create resource of type %1.") .arg( type ) ); return; } resource->setResourceName( i18n("%1 resource").arg( type ) ); KRES::ConfigDialog *dlg = new KRES::ConfigDialog( this, QString("calendar"), resource, "KRES::ConfigDialog" ); bool success = true; if ( !dlg || !dlg->exec() ) success = false; if ( success ) { resource->setTimeZoneId( KOPrefs::instance()->mTimeZoneId ); if ( resource->isActive() && ( !resource->open() || !resource->load() ) ) { // ### There is a resourceLoadError() signal declared in ResourceCalendar // but no subclass seems to make use of it. We could do better. KMessageBox::error( this, i18n("Unable to create the resource.") .arg( type ) ); success = false; } } if ( success ) { manager->add( resource ); // we have to call resourceAdded manually, because for in-process changes // the dcop signals are not connected, so the resource's signals would not // be connected otherwise mCalendar->resourceAdded( resource ); } if ( !success ) delete resource; delete dlg; //### maybe only do this if ( success ) emitResourcesChanged(); } void ResourceView::addResourceItem( ResourceCalendar *resource ) { ResourceItem *item=new ResourceItem( resource, this, mListView ); // assign a color, but only if this is a resource that actually // hold items at top level if ( !resource->canHaveSubresources() || resource->subresources().isEmpty() ) { QColor resourceColor = *KOPrefs::instance()->resourceColor(resource->identifier()); item->setResourceColor(resourceColor); item->update(); } connect( resource, SIGNAL( signalSubresourceAdded( ResourceCalendar *, const QString &, const QString &, const QString & ) ), SLOT( slotSubresourceAdded( ResourceCalendar *, const QString &, const QString &, const QString & ) ) ); connect( resource, SIGNAL( signalSubresourceRemoved( ResourceCalendar *, const QString &, const QString & ) ), SLOT( slotSubresourceRemoved( ResourceCalendar *, const QString &, const QString & ) ) ); connect( resource, SIGNAL( resourceSaved( ResourceCalendar * ) ), SLOT( closeResource( ResourceCalendar * ) ) ); updateResourceList(); emit resourcesChanged(); } // Add a new entry void ResourceView::slotSubresourceAdded( ResourceCalendar *calendar, const QString& /*type*/, const QString& resource, const QString& label) { QListViewItem *i = mListView->findItem( calendar->resourceName(), 0 ); if ( !i ) // Not found return; if ( findItemByIdentifier( resource ) ) return; ResourceItem *item = static_cast( i ); ResourceItem *newItem = new ResourceItem( calendar, resource, label, this, item ); QColor resourceColor = *KOPrefs::instance()->resourceColor( resource ); newItem->setResourceColor( resourceColor ); } // Remove an entry void ResourceView::slotSubresourceRemoved( ResourceCalendar * /*calendar*/, const QString &/*type*/, const QString &resource ) { delete findItemByIdentifier( resource ); emit resourcesChanged(); } void ResourceView::closeResource( ResourceCalendar *r ) { if ( mResourcesToClose.find( r ) >= 0 ) { r->close(); mResourcesToClose.remove( r ); } } void ResourceView::updateResourceItem( ResourceCalendar *resource ) { ResourceItem *item = findItem( resource ); if ( item ) { item->update(); } } ResourceItem *ResourceView::currentItem() { QListViewItem *item = mListView->currentItem(); ResourceItem *rItem = static_cast( item ); return rItem; } void ResourceView::removeResource() { ResourceItem *item = currentItem(); if ( !item ) return; const QString warningMsg = item->isSubresource() ? i18n("Do you really want to remove the subresource %1? " "Note that its contents will be completely deleted. This " "operation cannot be undone. ").arg( item->text( 0 ) ) : i18n("Do you really want to remove the resource %1?").arg( item->text( 0 ) ); int km = KMessageBox::warningContinueCancel( this, warningMsg, "", KGuiItem( i18n("&Remove" ), "editdelete") ); if ( km == KMessageBox::Cancel ) return; // Don't be so restricitve #if 0 if ( item->resource() == mCalendar->resourceManager()->standardResource() ) { KMessageBox::sorry( this, i18n( "You cannot delete your standard resource." ) ); return; } #endif if ( item->isSubresource() ) { if ( !item->resource()->removeSubresource( item->resourceIdentifier() ) ) KMessageBox::sorry( this, i18n ("Failed to remove the subresource %1. The " "reason could be that it is a built-in one which cannot " "be removed, or that the removal of the underlying storage " "folder failed.").arg( item->resource()->name() ) ); return; } else { mCalendar->resourceManager()->remove( item->resource() ); } mListView->takeItem( item ); delete item; updateResourceList(); emit resourcesChanged(); } void ResourceView::editResource() { ResourceItem *item = currentItem(); if (!item) return; ResourceCalendar *resource = item->resource(); KRES::ConfigDialog dlg( this, QString("calendar"), resource, "KRES::ConfigDialog" ); if ( dlg.exec() ) { item->setText( 0, resource->resourceName() ); mCalendar->resourceManager()->change( resource ); } emitResourcesChanged(); } void ResourceView::currentChanged( QListViewItem *item ) { ResourceItem *i = currentItem(); if ( !item || i->isSubresource() ) { mDeleteButton->setEnabled( false ); mEditButton->setEnabled( false ); } else { mDeleteButton->setEnabled( true ); mEditButton->setEnabled( true ); } } ResourceItem *ResourceView::findItem( ResourceCalendar *r ) { QListViewItem *item; ResourceItem *i = 0; for( item = mListView->firstChild(); item; item = item->nextSibling() ) { i = static_cast( item ); if ( i->resource() == r ) break; } return i; } ResourceItem *ResourceView::findItemByIdentifier( const QString& id ) { QListViewItem *item; ResourceItem *i = 0; for( item = mListView->firstChild(); item; item = item->itemBelow() ) { i = static_cast( item ); if ( i->resourceIdentifier() == id ) return i; } return 0; } void ResourceView::contextMenuRequested ( QListViewItem *i, const QPoint &pos, int ) { KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); ResourceItem *item = static_cast( i ); QPopupMenu *menu = new QPopupMenu( this ); connect( menu, SIGNAL( aboutToHide() ), menu, SLOT( deleteLater() ) ); if ( item ) { int reloadId = menu->insertItem( i18n("Re&load"), this, SLOT( reloadResource() ) ); menu->setItemEnabled( reloadId, item->resource()->isActive() ); int saveId = menu->insertItem( i18n("&Save"), this, SLOT( saveResource() ) ); menu->setItemEnabled( saveId, item->resource()->isActive() ); menu->insertSeparator(); menu->insertItem( i18n("Show &Info"), this, SLOT( showInfo() ) ); //FIXME: This is better on the resource dialog if ( KOPrefs::instance()->agendaViewColors() != KOPrefs::CategoryOnly ) { QPopupMenu *assignMenu= new QPopupMenu( menu ); assignMenu->insertItem( i18n( "&Assign Color" ), this, SLOT( assignColor() ) ); if ( item->resourceColor().isValid() ) assignMenu->insertItem( i18n( "&Disable Color" ), this, SLOT( disableColor() ) ); menu->insertItem( i18n( "Resources Colors" ), assignMenu ); } menu->insertItem( i18n("&Edit..."), this, SLOT( editResource() ) ); menu->insertItem( i18n("&Remove"), this, SLOT( removeResource() ) ); if ( item->resource() != manager->standardResource() ) { menu->insertSeparator(); menu->insertItem( i18n("Use as &Default Calendar"), this, SLOT( setStandard() ) ); } menu->insertSeparator(); } menu->insertItem( i18n("&Add..."), this, SLOT( addResource() ) ); menu->popup( pos ); } void ResourceView::assignColor() { ResourceItem *item = currentItem(); if ( !item ) return; // A color without initialized is a color invalid QColor myColor; KCal::ResourceCalendar *cal = item->resource(); QString identifier = cal->identifier(); if ( item->isSubresource() ) identifier = item->resourceIdentifier(); QColor defaultColor =*KOPrefs::instance()->resourceColor( identifier ); int result = KColorDialog::getColor( myColor,defaultColor); if ( result == KColorDialog::Accepted ) { KOPrefs::instance()->setResourceColor( identifier, myColor ); item->setResourceColor( myColor ); item->update(); emitResourcesChanged(); } } void ResourceView::disableColor() { ResourceItem *item = currentItem(); if ( !item ) return; QColor colorInvalid; KCal::ResourceCalendar *cal = item->resource(); QString identifier = cal->identifier(); if ( item->isSubresource() ) identifier = item->resourceIdentifier(); KOPrefs::instance()->setResourceColor( identifier, colorInvalid ); item->setResourceColor( colorInvalid ); item->update(); emitResourcesChanged(); } void ResourceView::showInfo() { ResourceItem *item = currentItem(); if ( !item ) return; QString txt = "" + item->resource()->infoText() + ""; KMessageBox::information( this, txt ); } void ResourceView::reloadResource() { ResourceItem *item = currentItem(); if ( !item ) return; ResourceCalendar *r = item->resource(); r->load(); } void ResourceView::saveResource() { ResourceItem *item = currentItem(); if ( !item ) return; ResourceCalendar *r = item->resource(); r->save(); } void ResourceView::setStandard() { ResourceItem *item = currentItem(); if ( !item ) return; ResourceCalendar *r = item->resource(); KCal::CalendarResourceManager *manager = mCalendar->resourceManager(); manager->setStandardResource( r ); updateResourceList(); } void ResourceView::updateResourceList() { QListViewItemIterator it( mListView ); ResourceCalendar* stdRes = mCalendar->resourceManager()->standardResource(); while ( it.current() ) { ResourceItem *item = static_cast( it.current() ); item->setStandardResource( item->resource() == stdRes ); ++it; } } void ResourceView::showButtons( bool visible ) { if ( visible ) { mAddButton->show(); mDeleteButton->show(); mEditButton->show(); } else { mAddButton->hide(); mDeleteButton->hide(); mEditButton->hide(); } } void ResourceView::requestClose( ResourceCalendar *r ) { mResourcesToClose.append( r ); } #include "resourceview.moc"