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   QDate currentDate = QDate::currentDate();
00272   for ( dt=currentDate;
00273         dt<=currentDate.addDays( mDaysAhead - 1 );
00274         dt=dt.addDays(1) ) {
00275     KCal::Event::List events = mCalendar->events( dt,
00276                                                   KCal::EventSortStartDate,
00277                                                   KCal::SortDirectionAscending );
00278     KCal::Event *ev;
00279     KCal::Event::List::ConstIterator it;
00280     for ( it=events.begin(); it!=events.end(); ++it ) {
00281       ev = *it;
00282       if ( !ev->categoriesStr().isEmpty() ) {
00283         QStringList::ConstIterator it2;
00284         QStringList c = ev->categories();
00285         for ( it2=c.begin(); it2!=c.end(); ++it2 ) {
00286 
00287           // Append Birthday Event?
00288           if ( mShowBirthdaysFromCal &&
00289                ( ( *it2 ).upper() == i18n( "BIRTHDAY" ) ) ) {
00290             SDEntry entry;
00291             entry.type = IncidenceTypeEvent;
00292             entry.category = CategoryBirthday;
00293             entry.date = dt;
00294             entry.summary = ev->summary();
00295             entry.desc = ev->description();
00296             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00297             entry.span = 1;
00298             dates.append( entry );
00299             break;
00300           }
00301 
00302           // Append Anniversary Event?
00303           if ( mShowAnniversariesFromCal &&
00304                ( ( *it2 ).upper() == i18n( "ANNIVERSARY" ) ) ) {
00305             SDEntry entry;
00306             entry.type = IncidenceTypeEvent;
00307             entry.category = CategoryAnniversary;
00308             entry.date = dt;
00309             entry.summary = ev->summary();
00310             entry.desc = ev->description();
00311             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00312             entry.span = 1;
00313             dates.append( entry );
00314             break;
00315           }
00316 
00317           // Append Holiday Event?
00318           if ( mShowHolidays &&
00319                ( ( *it2 ).upper() == i18n( "HOLIDAY" ) ) ) {
00320             SDEntry entry;
00321             entry.type = IncidenceTypeEvent;
00322             entry.category = CategoryHoliday;
00323             entry.date = dt;
00324             entry.summary = ev->summary();
00325             entry.desc = ev->description();
00326             dateDiff( dt, entry.daysTo, entry.yearsOld );
00327             entry.yearsOld = -1; //ignore age of holidays
00328             entry.span = span( ev );
00329             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00330               break;
00331             dates.append( entry );
00332             break;
00333           }
00334 
00335           // Append Special Occasion Event?
00336           if ( mShowSpecialsFromCal &&
00337                ( ( *it2 ).upper() == i18n( "SPECIAL OCCASION" ) ) ) {
00338             SDEntry entry;
00339             entry.type = IncidenceTypeEvent;
00340             entry.category = CategoryOther;
00341             entry.date = dt;
00342             entry.summary = ev->summary();
00343             entry.desc = ev->description();
00344             dateDiff( dt, entry.daysTo, entry.yearsOld );
00345             entry.yearsOld = -1; //ignore age of special occasions
00346             entry.span = span( ev );
00347             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00348               break;
00349             dates.append( entry );
00350             break;
00351           }
00352         }
00353       }
00354     }
00355   }
00356 
00357   // Seach for Holidays
00358   if ( mShowHolidays ) {
00359     if ( initHolidays() ) {
00360       for ( dt=currentDate;
00361             dt<=currentDate.addDays( mDaysAhead - 1 );
00362             dt=dt.addDays(1) ) {
00363         QValueList<KHoliday> holidays = mHolidays->getHolidays( dt );
00364         QValueList<KHoliday>::ConstIterator it = holidays.begin();
00365         for ( ; it != holidays.end(); ++it ) {
00366           SDEntry entry;
00367           entry.type = IncidenceTypeEvent;
00368           entry.category = ((*it).Category==KHolidays::HOLIDAY)?CategoryHoliday:CategoryOther;
00369           entry.date = dt;
00370           entry.summary = (*it).text;
00371           dateDiff( dt, entry.daysTo, entry.yearsOld );
00372           entry.yearsOld = -1; //ignore age of holidays
00373           entry.span = 1;
00374           dates.append( entry );
00375         }
00376       }
00377     }
00378   }
00379 
00380   // Sort, then Print the Special Dates
00381   qHeapSort( dates );
00382 
00383   if ( !dates.isEmpty() ) {
00384     int counter = 0;
00385     QValueList<SDEntry>::Iterator addrIt;
00386     QString lines;
00387     for ( addrIt = dates.begin(); addrIt != dates.end(); ++addrIt ) {
00388       bool makeBold = (*addrIt).daysTo == 0; // i.e., today
00389 
00390       // Pixmap
00391       QImage icon_img;
00392       QString icon_name;
00393       KABC::Picture pic;
00394       switch( (*addrIt).category ) {  // TODO: better icons
00395       case CategoryBirthday:
00396         icon_name = "cookie";
00397         pic = (*addrIt).addressee.photo();
00398         if ( pic.isIntern() && !pic.data().isNull() ) {
00399           QImage img = pic.data();
00400           if ( img.width() > img.height() ) {
00401             icon_img = img.scaleWidth( 32 );
00402           } else {
00403             icon_img = img.scaleHeight( 32 );
00404           }
00405         }
00406         break;
00407       case CategoryAnniversary:
00408         icon_name = "kdmconfig";
00409         pic = (*addrIt).addressee.photo();
00410         if ( pic.isIntern() && !pic.data().isNull() ) {
00411           QImage img = pic.data();
00412           if ( img.width() > img.height() ) {
00413             icon_img = img.scaleWidth( 32 );
00414           } else {
00415             icon_img = img.scaleHeight( 32 );
00416           }
00417         }
00418         break;
00419       case CategoryHoliday:
00420         icon_name = "kdmconfig"; break;
00421       case CategoryOther:
00422         icon_name = "cookie"; break;
00423       }
00424       label = new QLabel( this );
00425       if ( icon_img.isNull() ) {
00426         label->setPixmap( KGlobal::iconLoader()->loadIcon( icon_name,
00427                                                            KIcon::Small ) );
00428       } else {
00429         label->setPixmap( icon_img );
00430       }
00431       label->setMaximumWidth( label->minimumSizeHint().width() );
00432       label->setAlignment( AlignVCenter );
00433       mLayout->addWidget( label, counter, 0 );
00434       mLabels.append( label );
00435 
00436       // Event date
00437       QString datestr;
00438 
00439       //Muck with the year -- change to the year 'daysTo' days away
00440       int year = currentDate.addDays( (*addrIt).daysTo ).year();
00441       QDate sD = QDate::QDate( year,
00442                            (*addrIt).date.month(), (*addrIt).date.day() );
00443 
00444       if ( (*addrIt).daysTo == 0 ) {
00445         datestr = i18n( "Today" );
00446       } else if ( (*addrIt).daysTo == 1 ) {
00447         datestr = i18n( "Tomorrow" );
00448       } else {
00449         datestr = KGlobal::locale()->formatDate( sD );
00450       }
00451       // Print the date span for multiday, floating events, for the
00452       // first day of the event only.
00453       if ( (*addrIt).span > 1 ) {
00454         QString endstr =
00455           KGlobal::locale()->formatDate( sD.addDays( (*addrIt).span - 1 ) );
00456         datestr += " -\n " + endstr;
00457       }
00458 
00459       label = new QLabel( datestr, this );
00460       label->setAlignment( AlignLeft | AlignVCenter );
00461       mLayout->addWidget( label, counter, 1 );
00462       mLabels.append( label );
00463       if ( makeBold ) {
00464         QFont font = label->font();
00465         font.setBold( true );
00466         label->setFont( font );
00467       }
00468 
00469       // Countdown
00470       label = new QLabel( this );
00471       if ( (*addrIt).daysTo == 0 ) {
00472         label->setText( i18n( "now" ) );
00473       } else {
00474         label->setText( i18n( "in 1 day", "in %n days", (*addrIt).daysTo ) );
00475       }
00476 
00477       label->setAlignment( AlignLeft | AlignVCenter );
00478       mLayout->addWidget( label, counter, 2 );
00479       mLabels.append( label );
00480 
00481       // What
00482       QString what;
00483       switch( (*addrIt).category ) {
00484       case CategoryBirthday:
00485         what = i18n( "Birthday" ); break;
00486       case CategoryAnniversary:
00487         what = i18n( "Anniversary" ); break;
00488       case CategoryHoliday:
00489         what = i18n( "Holiday" ); break;
00490       case CategoryOther:
00491         what = i18n( "Special Occasion" ); break;
00492       }
00493       label = new QLabel( this );
00494       label->setText( what );
00495       label->setAlignment( AlignLeft | AlignVCenter );
00496       mLayout->addWidget( label, counter, 3 );
00497       mLabels.append( label );
00498 
00499       // Description
00500       if ( (*addrIt).type == IncidenceTypeContact ) {
00501         KURLLabel *urlLabel = new KURLLabel( this );
00502         urlLabel->installEventFilter( this );
00503         urlLabel->setURL( (*addrIt).addressee.uid() );
00504         urlLabel->setText( (*addrIt).addressee.realName() );
00505         urlLabel->setTextFormat( Qt::RichText );
00506         mLayout->addWidget( urlLabel, counter, 4 );
00507         mLabels.append( urlLabel );
00508 
00509         connect( urlLabel, SIGNAL( leftClickedURL( const QString& ) ),
00510                  this, SLOT( mailContact( const QString& ) ) );
00511         connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ),
00512                  this, SLOT( popupMenu( const QString& ) ) );
00513       } else {
00514         label = new QLabel( this );
00515         label->setText( (*addrIt).summary );
00516         label->setTextFormat( Qt::RichText );
00517         mLayout->addWidget( label, counter, 4 );
00518         mLabels.append( label );
00519         if ( !(*addrIt).desc.isEmpty() ) {
00520           QToolTip::add( label, (*addrIt).desc );
00521         }
00522       }
00523 
00524      // Age
00525       if ( (*addrIt).category == CategoryBirthday ||
00526            (*addrIt).category == CategoryAnniversary ) {
00527         label = new QLabel( this );
00528         if ( (*addrIt).yearsOld <= 0 ) {
00529           label->setText( "" );
00530         } else {
00531           label->setText( i18n( "one year", "%n years", (*addrIt).yearsOld  ) );
00532         }
00533         label->setAlignment( AlignLeft | AlignVCenter );
00534         mLayout->addWidget( label, counter, 5 );
00535         mLabels.append( label );
00536       }
00537 
00538       counter++;
00539     }
00540   } else {
00541     label = new QLabel(
00542         i18n( "No special dates within the next 1 day",
00543               "No special dates pending within the next %n days",
00544               mDaysAhead ), this, "nothing to see" );
00545     label->setAlignment( AlignHCenter | AlignVCenter );
00546     mLayout->addMultiCellWidget( label, 0, 0, 0, 4 );
00547     mLabels.append( label );
00548   }
00549 
00550   for ( label = mLabels.first(); label; label = mLabels.next() )
00551     label->show();
00552 
00553   KGlobal::locale()->setDateFormat( savefmt );
00554 }
00555 
00556 void SDSummaryWidget::mailContact( const QString &uid )
00557 {
00558   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00559   QString email = ab->findByUid( uid ).fullEmail();
00560 
00561   kapp->invokeMailer( email, QString::null );
00562 }
00563 
00564 void SDSummaryWidget::viewContact( const QString &uid )
00565 {
00566   if ( !mPlugin->isRunningStandalone() )
00567     mPlugin->core()->selectPlugin( "kontact_kaddressbookplugin" );
00568   else
00569     mPlugin->bringToForeground();
00570 
00571   DCOPRef dcopCall( "kaddressbook", "KAddressBookIface" );
00572   dcopCall.send( "showContactEditor(QString)", uid );
00573 }
00574 
00575 void SDSummaryWidget::popupMenu( const QString &uid )
00576 {
00577   KPopupMenu popup( this );
00578   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kmail", KIcon::Small ),
00579                     i18n( "Send &Mail" ), 0 );
00580   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Small ),
00581                     i18n( "View &Contact" ), 1 );
00582 
00583   switch ( popup.exec( QCursor::pos() ) ) {
00584     case 0:
00585       mailContact( uid );
00586       break;
00587     case 1:
00588       viewContact( uid );
00589       break;
00590   }
00591 }
00592 
00593 bool SDSummaryWidget::eventFilter( QObject *obj, QEvent* e )
00594 {
00595   if ( obj->inherits( "KURLLabel" ) ) {
00596     KURLLabel* label = static_cast<KURLLabel*>( obj );
00597     if ( e->type() == QEvent::Enter )
00598       emit message( i18n( "Mail to:\"%1\"" ).arg( label->text() ) );
00599     if ( e->type() == QEvent::Leave )
00600       emit message( QString::null );
00601   }
00602 
00603   return Kontact::Summary::eventFilter( obj, e );
00604 }
00605 
00606 void SDSummaryWidget::dateDiff( const QDate &date, int &days, int &years )
00607 {
00608   QDate currentDate;
00609   QDate eventDate;
00610 
00611   if ( QDate::leapYear( date.year() ) && date.month() == 2 && date.day() == 29 ) {
00612     currentDate = QDate( date.year(), QDate::currentDate().month(), QDate::currentDate().day() );
00613     if ( !QDate::leapYear( QDate::currentDate().year() ) )
00614       eventDate = QDate( date.year(), date.month(), 28 ); // celebrate one day earlier ;)
00615     else
00616       eventDate = QDate( date.year(), date.month(), date.day() );
00617   } else {
00618     currentDate = QDate( 0, QDate::currentDate().month(), QDate::currentDate().day() );
00619     eventDate = QDate( 0, date.month(), date.day() );
00620   }
00621 
00622   int offset = currentDate.daysTo( eventDate );
00623   if ( offset < 0 ) {
00624     days = 365 + offset;
00625     years = QDate::currentDate().year() + 1 - date.year();
00626   } else {
00627     days = offset;
00628     years = QDate::currentDate().year() - date.year();
00629   }
00630 }
00631 
00632 QStringList SDSummaryWidget::configModules() const
00633 {
00634   return QStringList( "kcmsdsummary.desktop" );
00635 }
00636 
00637 #include "sdsummarywidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys