kontact

sdsummarywidget.cpp

00001 /*
00002     This file is part of Kontact.
00003     Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
00004     Copyright (c) 2004 Allen Winter <winter@kde.org>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include <qcursor.h>
00026 #include <qlabel.h>
00027 #include <qlayout.h>
00028 #include <qimage.h>
00029 #include <qtooltip.h>
00030 
00031 #include <dcopclient.h>
00032 #include <dcopref.h>
00033 #include <kabc/stdaddressbook.h>
00034 #include <korganizer/stdcalendar.h>
00035 #include <kapplication.h>
00036 #include <kdialog.h>
00037 #include <kglobal.h>
00038 #include <kiconloader.h>
00039 #include <klocale.h>
00040 #include <kparts/part.h>
00041 #include <kpopupmenu.h>
00042 #include <kstandarddirs.h>
00043 #include <kurllabel.h>
00044 #include <libkcal/event.h>
00045 #include <libkcal/resourcecalendar.h>
00046 #include <libkcal/resourcelocal.h>
00047 #include <libkdepim/kpimprefs.h>
00048 
00049 #include "core.h"
00050 #include "plugin.h"
00051 
00052 #include "sdsummarywidget.h"
00053 
00054 enum SDIncidenceType {
00055   IncidenceTypeContact, IncidenceTypeEvent
00056 };
00057 enum SDCategory {
00058   CategoryBirthday, CategoryAnniversary, CategoryHoliday, CategoryOther
00059 };
00060 
00061 class SDEntry
00062 {
00063   public:
00064     SDIncidenceType type;
00065     SDCategory category;
00066     int yearsOld;
00067     int daysTo;
00068     QDate date;
00069     QString summary;
00070     QString desc;
00071     int span; // #days in the special occassion.
00072     KABC::Addressee addressee;
00073 
00074     bool operator<( const SDEntry &entry ) const
00075     {
00076       return daysTo < entry.daysTo;
00077     }
00078 };
00079 
00080 SDSummaryWidget::SDSummaryWidget( Kontact::Plugin *plugin, QWidget *parent,
00081                                     const char *name )
00082   : Kontact::Summary( parent, name ), mPlugin( plugin ), mCalendar( 0 ), mHolidays( 0 )
00083 {
00084   // Create the Summary Layout
00085   QVBoxLayout *mainLayout = new QVBoxLayout( this, 3, 3 );
00086 
00087   QPixmap icon = KGlobal::iconLoader()->loadIcon( "cookie",
00088                     KIcon::Desktop, KIcon::SizeMedium );
00089 
00090   QWidget *header = createHeader( this, icon, i18n( "Special Dates" ) );
00091   mainLayout->addWidget(header);
00092 
00093   mLayout = new QGridLayout( mainLayout, 7, 6, 3 );
00094   mLayout->setRowStretch( 6, 1 );
00095 
00096   // Setup the Addressbook
00097   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00098   connect( ab, SIGNAL( addressBookChanged( AddressBook* ) ),
00099            this, SLOT( updateView() ) );
00100   connect( mPlugin->core(), SIGNAL( dayChanged( const QDate& ) ),
00101            this, SLOT( updateView() ) );
00102 
00103   // Setup the Calendar
00104   mCalendar = new KCal::CalendarResources( KPimPrefs::timezone() );
00105   mCalendar->readConfig();
00106 
00107   KCal::CalendarResourceManager *manager = mCalendar->resourceManager();
00108   if ( manager->isEmpty() ) {
00109     KConfig config( "korganizerrc" );
00110     config.setGroup( "General" );
00111     QString fileName = config.readPathEntry( "Active Calendar" );
00112 
00113     QString resourceName;
00114     if ( fileName.isEmpty() ) {
00115       fileName = locateLocal( "data", "korganizer/std.ics" );
00116       resourceName = i18n( "Default KOrganizer resource" );
00117     } else {
00118       resourceName = i18n( "Active Calendar" );
00119     }
00120 
00121     KCal::ResourceCalendar *defaultResource =
00122       new KCal::ResourceLocal( fileName );
00123 
00124     defaultResource->setResourceName( resourceName );
00125 
00126     manager->add( defaultResource );
00127     manager->setStandardResource( defaultResource );
00128   }
00129   mCalendar = KOrg::StdCalendar::self();
00130   mCalendar->load();
00131 
00132   connect( mCalendar, SIGNAL( calendarChanged() ),
00133            this, SLOT( updateView() ) );
00134   connect( mPlugin->core(), SIGNAL( dayChanged( const QDate& ) ),
00135            this, SLOT( updateView() ) );
00136 
00137   // Update Configuration
00138   configUpdated();
00139 }
00140 
00141 void SDSummaryWidget::configUpdated()
00142 {
00143   KConfig config( "kcmsdsummaryrc" );
00144 
00145   config.setGroup( "Days" );
00146   mDaysAhead = config.readNumEntry( "DaysToShow", 7 );
00147 
00148   config.setGroup( "EventTypes" );
00149   mShowBirthdaysFromKAB =
00150     config.readBoolEntry( "ShowBirthdaysFromContacts", true );
00151   mShowBirthdaysFromCal =
00152     config.readBoolEntry( "ShowBirthdaysFromCalendar", true );
00153 
00154   mShowAnniversariesFromKAB =
00155     config.readBoolEntry( "ShowAnniversariesFromContacts", true );
00156   mShowAnniversariesFromCal =
00157     config.readBoolEntry( "ShowAnniversariesFromCalendar", true );
00158 
00159   mShowHolidays =
00160     config.readBoolEntry( "ShowHolidays", true );
00161 
00162   mShowSpecialsFromCal =
00163     config.readBoolEntry( "ShowSpecialsFromCalendar", true );
00164 
00165   updateView();
00166 }
00167 
00168 bool SDSummaryWidget::initHolidays()
00169 {
00170   KConfig hconfig( "korganizerrc" );
00171   hconfig.setGroup( "Time & Date" );
00172   QString location = hconfig.readEntry( "Holidays" );
00173   if ( !location.isEmpty() ) {
00174     if ( mHolidays ) delete mHolidays;
00175     mHolidays = new KHolidays( location );
00176     return true;
00177   }
00178   return false;
00179 }
00180 
00181 // number of days remaining in an Event
00182 int SDSummaryWidget::span( KCal::Event *event )
00183 {
00184   int span=1;
00185   if ( event->isMultiDay() && event->doesFloat() ) {
00186     QDate d = event->dtStart().date();
00187     if ( d < QDate::currentDate() ) {
00188       d = QDate::currentDate();
00189     }
00190     while ( d < event->dtEnd().date() ) {
00191       span++;
00192       d=d.addDays( 1 );
00193     }
00194   }
00195   return span;
00196 }
00197 
00198 // day of a multiday Event
00199 int SDSummaryWidget::dayof( KCal::Event *event, const QDate& date )
00200 {
00201   int dayof=1;
00202   QDate d = event->dtStart().date();
00203   if ( d < QDate::currentDate() ) {
00204     d = QDate::currentDate();
00205   }
00206   while ( d < event->dtEnd().date() ) {
00207     if ( d < date ) {
00208       dayof++;
00209     }
00210     d = d.addDays( 1 );
00211   }
00212   return dayof;
00213 }
00214 
00215 
00216 
00217 void SDSummaryWidget::updateView()
00218 {
00219   mLabels.setAutoDelete( true );
00220   mLabels.clear();
00221   mLabels.setAutoDelete( false );
00222 
00223   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00224   QValueList<SDEntry> dates;
00225   QLabel *label = 0;
00226 
00227   // No reason to show the date year
00228   QString savefmt = KGlobal::locale()->dateFormat();
00229   KGlobal::locale()->setDateFormat( KGlobal::locale()->
00230                                     dateFormat().replace( 'Y', ' ' ) );
00231 
00232   // Search for Birthdays and Anniversaries in the Addressbook
00233   KABC::AddressBook::Iterator it;
00234   for ( it = ab->begin(); it != ab->end(); ++it ) {
00235     QDate birthday = (*it).birthday().date();
00236     if ( birthday.isValid() && mShowBirthdaysFromKAB ) {
00237       SDEntry entry;
00238       entry.type = IncidenceTypeContact;
00239       entry.category = CategoryBirthday;
00240       dateDiff( birthday, entry.daysTo, entry.yearsOld );
00241 
00242       entry.date = birthday;
00243       entry.addressee = *it;
00244       entry.span = 1;
00245       if ( entry.daysTo <= mDaysAhead )
00246         dates.append( entry );
00247     }
00248 
00249     QString anniversaryAsString =
00250       (*it).custom( "KADDRESSBOOK" , "X-Anniversary" );
00251     if ( !anniversaryAsString.isEmpty() ) {
00252       QDate anniversary = QDate::fromString( anniversaryAsString, Qt::ISODate );
00253       if ( anniversary.isValid() && mShowAnniversariesFromKAB ) {
00254         SDEntry entry;
00255         entry.type = IncidenceTypeContact;
00256         entry.category = CategoryAnniversary;
00257         dateDiff( anniversary, entry.daysTo, entry.yearsOld );
00258 
00259         entry.date = anniversary;
00260         entry.addressee = *it;
00261         entry.span = 1;
00262         if ( entry.daysTo <= mDaysAhead )
00263           dates.append( entry );
00264       }
00265     }
00266   }
00267 
00268   // Search for Birthdays, Anniversaries, Holidays, and Special Occasions
00269   // in the Calendar
00270   QDate dt;
00271   for ( dt=QDate::currentDate();
00272         dt<=QDate::currentDate().addDays( mDaysAhead - 1 );
00273         dt=dt.addDays(1) ) {
00274     KCal::Event::List events = mCalendar->events( dt,
00275                                                   KCal::EventSortStartDate,
00276                                                   KCal::SortDirectionAscending );
00277     KCal::Event *ev;
00278     KCal::Event::List::ConstIterator it;
00279     for ( it=events.begin(); it!=events.end(); ++it ) {
00280       ev = *it;
00281       if ( !ev->categoriesStr().isEmpty() ) {
00282         QStringList::ConstIterator it2;
00283         QStringList c = ev->categories();
00284         for ( it2=c.begin(); it2!=c.end(); ++it2 ) {
00285 
00286           // Append Birthday Event?
00287           if ( mShowBirthdaysFromCal &&
00288                ( ( *it2 ).upper() == i18n( "BIRTHDAY" ) ) ) {
00289             SDEntry entry;
00290             entry.type = IncidenceTypeEvent;
00291             entry.category = CategoryBirthday;
00292             entry.date = dt;
00293             entry.summary = ev->summary();
00294             entry.desc = ev->description();
00295             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00296             entry.span = 1;
00297             dates.append( entry );
00298             break;
00299           }
00300 
00301           // Append Anniversary Event?
00302           if ( mShowAnniversariesFromCal &&
00303                ( ( *it2 ).upper() == i18n( "ANNIVERSARY" ) ) ) {
00304             SDEntry entry;
00305             entry.type = IncidenceTypeEvent;
00306             entry.category = CategoryAnniversary;
00307             entry.date = dt;
00308             entry.summary = ev->summary();
00309             entry.desc = ev->description();
00310             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00311             entry.span = 1;
00312             dates.append( entry );
00313             break;
00314           }
00315 
00316           // Append Holiday Event?
00317           if ( mShowHolidays &&
00318                ( ( *it2 ).upper() == i18n( "HOLIDAY" ) ) ) {
00319             SDEntry entry;
00320             entry.type = IncidenceTypeEvent;
00321             entry.category = CategoryHoliday;
00322             entry.date = dt;
00323             entry.summary = ev->summary();
00324             entry.desc = ev->description();
00325             dateDiff( dt, entry.daysTo, entry.yearsOld );
00326             entry.yearsOld = -1; //ignore age of holidays
00327             entry.span = span( ev );
00328             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00329               break;
00330             dates.append( entry );
00331             break;
00332           }
00333 
00334           // Append Special Occasion Event?
00335           if ( mShowSpecialsFromCal &&
00336                ( ( *it2 ).upper() == i18n( "SPECIAL OCCASION" ) ) ) {
00337             SDEntry entry;
00338             entry.type = IncidenceTypeEvent;
00339             entry.category = CategoryOther;
00340             entry.date = dt;
00341             entry.summary = ev->summary();
00342             entry.desc = ev->description();
00343             dateDiff( dt, entry.daysTo, entry.yearsOld );
00344             entry.yearsOld = -1; //ignore age of special occasions
00345             entry.span = span( ev );
00346             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00347               break;
00348             dates.append( entry );
00349             break;
00350           }
00351         }
00352       }
00353     }
00354   }
00355 
00356   // Seach for Holidays
00357   if ( mShowHolidays ) {
00358     if ( initHolidays() ) {
00359       for ( dt=QDate::currentDate();
00360             dt<=QDate::currentDate().addDays( mDaysAhead - 1 );
00361             dt=dt.addDays(1) ) {
00362         QString holstring = mHolidays->shortText( dt );
00363         if ( !holstring.isNull() && !holstring.isEmpty() ) {
00364           SDEntry entry;
00365           entry.type = IncidenceTypeEvent;
00366           entry.category = CategoryHoliday;
00367           entry.date = dt;
00368           entry.summary = holstring;
00369           dateDiff( dt, entry.daysTo, entry.yearsOld );
00370           entry.yearsOld = -1; //ignore age of holidays
00371           entry.span = 1;
00372           dates.append( entry );
00373         }
00374       }
00375     }
00376   }
00377 
00378   // Sort, then Print the Special Dates
00379   qHeapSort( dates );
00380 
00381   if ( !dates.isEmpty() ) {
00382     int counter = 0;
00383     QValueList<SDEntry>::Iterator addrIt;
00384     QString lines;
00385     for ( addrIt = dates.begin(); addrIt != dates.end(); ++addrIt ) {
00386       bool makeBold = (*addrIt).daysTo == 0; // i.e., today
00387 
00388       // Pixmap
00389       QImage icon_img;
00390       QString icon_name;
00391       KABC::Picture pic;
00392       switch( (*addrIt).category ) {  // TODO: better icons
00393       case CategoryBirthday:
00394         icon_name = "cookie";
00395         pic = (*addrIt).addressee.photo();
00396         if ( pic.isIntern() && !pic.data().isNull() ) {
00397           QImage img = pic.data();
00398           if ( img.width() > img.height() ) {
00399             icon_img = img.scaleWidth( 32 );
00400           } else {
00401             icon_img = img.scaleHeight( 32 );
00402           }
00403         }
00404         break;
00405       case CategoryAnniversary:
00406         icon_name = "kdmconfig";
00407         pic = (*addrIt).addressee.photo();
00408         if ( pic.isIntern() && !pic.data().isNull() ) {
00409           QImage img = pic.data();
00410           if ( img.width() > img.height() ) {
00411             icon_img = img.scaleWidth( 32 );
00412           } else {
00413             icon_img = img.scaleHeight( 32 );
00414           }
00415         }
00416         break;
00417       case CategoryHoliday:
00418         icon_name = "kdmconfig"; break;
00419       case CategoryOther:
00420         icon_name = "cookie"; break;
00421       }
00422       label = new QLabel( this );
00423       if ( icon_img.isNull() ) {
00424         label->setPixmap( KGlobal::iconLoader()->loadIcon( icon_name,
00425                                                            KIcon::Small ) );
00426       } else {
00427         label->setPixmap( icon_img );
00428       }
00429       label->setMaximumWidth( label->minimumSizeHint().width() );
00430       label->setAlignment( AlignVCenter );
00431       mLayout->addWidget( label, counter, 0 );
00432       mLabels.append( label );
00433 
00434       // Event date
00435       QString datestr;
00436 
00437       //Muck with the year -- change to the year 'daysTo' days away
00438       int year = QDate::currentDate().addDays( (*addrIt).daysTo ).year();
00439       QDate sD = QDate::QDate( year,
00440                            (*addrIt).date.month(), (*addrIt).date.day() );
00441 
00442       if ( (*addrIt).daysTo == 0 ) {
00443         datestr = i18n( "Today" );
00444       } else if ( (*addrIt).daysTo == 1 ) {
00445         datestr = i18n( "Tomorrow" );
00446       } else {
00447         datestr = KGlobal::locale()->formatDate( sD );
00448       }
00449       // Print the date span for multiday, floating events, for the
00450       // first day of the event only.
00451       if ( (*addrIt).span > 1 ) {
00452         QString endstr =
00453           KGlobal::locale()->formatDate( sD.addDays( (*addrIt).span - 1 ) );
00454         datestr += " -\n " + endstr;
00455       }
00456 
00457       label = new QLabel( datestr, this );
00458       label->setAlignment( AlignLeft | AlignVCenter );
00459       mLayout->addWidget( label, counter, 1 );
00460       mLabels.append( label );
00461       if ( makeBold ) {
00462         QFont font = label->font();
00463         font.setBold( true );
00464         label->setFont( font );
00465       }
00466 
00467       // Countdown
00468       label = new QLabel( this );
00469       if ( (*addrIt).daysTo == 0 ) {
00470         label->setText( i18n( "now" ) );
00471       } else {
00472         label->setText( i18n( "in 1 day", "in %n days", (*addrIt).daysTo ) );
00473       }
00474 
00475       label->setAlignment( AlignLeft | AlignVCenter );
00476       mLayout->addWidget( label, counter, 2 );
00477       mLabels.append( label );
00478 
00479       // What
00480       QString what;
00481       switch( (*addrIt).category ) {
00482       case CategoryBirthday:
00483         what = i18n( "Birthday" ); break;
00484       case CategoryAnniversary:
00485         what = i18n( "Anniversary" ); break;
00486       case CategoryHoliday:
00487         what = i18n( "Holiday" ); break;
00488       case CategoryOther:
00489         what = i18n( "Special Occasion" ); break;
00490       }
00491       label = new QLabel( this );
00492       label->setText( what );
00493       label->setAlignment( AlignLeft | AlignVCenter );
00494       mLayout->addWidget( label, counter, 3 );
00495       mLabels.append( label );
00496 
00497       // Description
00498       if ( (*addrIt).type == IncidenceTypeContact ) {
00499         KURLLabel *urlLabel = new KURLLabel( this );
00500         urlLabel->installEventFilter( this );
00501         urlLabel->setURL( (*addrIt).addressee.uid() );
00502         urlLabel->setText( (*addrIt).addressee.realName() );
00503         urlLabel->setTextFormat( Qt::RichText );
00504         mLayout->addWidget( urlLabel, counter, 4 );
00505         mLabels.append( urlLabel );
00506 
00507         connect( urlLabel, SIGNAL( leftClickedURL( const QString& ) ),
00508                  this, SLOT( mailContact( const QString& ) ) );
00509         connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ),
00510                  this, SLOT( popupMenu( const QString& ) ) );
00511       } else {
00512         label = new QLabel( this );
00513         label->setText( (*addrIt).summary );
00514         label->setTextFormat( Qt::RichText );
00515         mLayout->addWidget( label, counter, 4 );
00516         mLabels.append( label );
00517         if ( !(*addrIt).desc.isEmpty() ) {
00518           QToolTip::add( label, (*addrIt).desc );
00519         }
00520       }
00521 
00522      // Age
00523       if ( (*addrIt).category == CategoryBirthday ||
00524            (*addrIt).category == CategoryAnniversary ) {
00525         label = new QLabel( this );
00526         if ( (*addrIt).yearsOld <= 0 ) {
00527           label->setText( "" );
00528         } else {
00529           label->setText( i18n( "one year", "%n years", (*addrIt).yearsOld  ) );
00530         }
00531         label->setAlignment( AlignLeft | AlignVCenter );
00532         mLayout->addWidget( label, counter, 5 );
00533         mLabels.append( label );
00534       }
00535 
00536       counter++;
00537     }
00538   } else {
00539     label = new QLabel(
00540         i18n( "No special dates within the next 1 day",
00541               "No special dates pending within the next %n days",
00542               mDaysAhead ), this, "nothing to see" );
00543     label->setAlignment( AlignHCenter | AlignVCenter );
00544     mLayout->addMultiCellWidget( label, 0, 0, 0, 4 );
00545     mLabels.append( label );
00546   }
00547 
00548   for ( label = mLabels.first(); label; label = mLabels.next() )
00549     label->show();
00550 
00551   KGlobal::locale()->setDateFormat( savefmt );
00552 }
00553 
00554 void SDSummaryWidget::mailContact( const QString &uid )
00555 {
00556   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00557   QString email = ab->findByUid( uid ).fullEmail();
00558 
00559   kapp->invokeMailer( email, QString::null );
00560 }
00561 
00562 void SDSummaryWidget::viewContact( const QString &uid )
00563 {
00564   if ( !mPlugin->isRunningStandalone() )
00565     mPlugin->core()->selectPlugin( "kontact_kaddressbookplugin" );
00566   else
00567     mPlugin->bringToForeground();
00568 
00569   DCOPRef dcopCall( "kaddressbook", "KAddressBookIface" );
00570   dcopCall.send( "showContactEditor(QString)", uid );
00571 }
00572 
00573 void SDSummaryWidget::popupMenu( const QString &uid )
00574 {
00575   KPopupMenu popup( this );
00576   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kmail", KIcon::Small ),
00577                     i18n( "Send &Mail" ), 0 );
00578   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Small ),
00579                     i18n( "View &Contact" ), 1 );
00580 
00581   switch ( popup.exec( QCursor::pos() ) ) {
00582     case 0:
00583       mailContact( uid );
00584       break;
00585     case 1:
00586       viewContact( uid );
00587       break;
00588   }
00589 }
00590 
00591 bool SDSummaryWidget::eventFilter( QObject *obj, QEvent* e )
00592 {
00593   if ( obj->inherits( "KURLLabel" ) ) {
00594     KURLLabel* label = static_cast<KURLLabel*>( obj );
00595     if ( e->type() == QEvent::Enter )
00596       emit message( i18n( "Mail to:\"%1\"" ).arg( label->text() ) );
00597     if ( e->type() == QEvent::Leave )
00598       emit message( QString::null );
00599   }
00600 
00601   return Kontact::Summary::eventFilter( obj, e );
00602 }
00603 
00604 void SDSummaryWidget::dateDiff( const QDate &date, int &days, int &years )
00605 {
00606   QDate currentDate;
00607   QDate eventDate;
00608 
00609   if ( QDate::leapYear( date.year() ) && date.month() == 2 && date.day() == 29 ) {
00610     currentDate = QDate( date.year(), QDate::currentDate().month(), QDate::currentDate().day() );
00611     if ( !QDate::leapYear( QDate::currentDate().year() ) )
00612       eventDate = QDate( date.year(), date.month(), 28 ); // celebrate one day earlier ;)
00613     else
00614       eventDate = QDate( date.year(), date.month(), date.day() );
00615   } else {
00616     currentDate = QDate( 0, QDate::currentDate().month(), QDate::currentDate().day() );
00617     eventDate = QDate( 0, date.month(), date.day() );
00618   }
00619 
00620   int offset = currentDate.daysTo( eventDate );
00621   if ( offset < 0 ) {
00622     days = 365 + offset;
00623     years = QDate::currentDate().year() + 1 - date.year();
00624   } else {
00625     days = offset;
00626     years = QDate::currentDate().year() - date.year();
00627   }
00628 }
00629 
00630 QStringList SDSummaryWidget::configModules() const
00631 {
00632   return QStringList( "kcmsdsummary.desktop" );
00633 }
00634 
00635 #include "sdsummarywidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys