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