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 
00131   connect( mCalendar, SIGNAL( calendarChanged() ),
00132            this, SLOT( updateView() ) );
00133   connect( mPlugin->core(), SIGNAL( dayChanged( const QDate& ) ),
00134            this, SLOT( updateView() ) );
00135 
00136   // Update Configuration
00137   configUpdated();
00138 }
00139 
00140 void SDSummaryWidget::configUpdated()
00141 {
00142   KConfig config( "kcmsdsummaryrc" );
00143 
00144   config.setGroup( "Days" );
00145   mDaysAhead = config.readNumEntry( "DaysToShow", 7 );
00146 
00147   config.setGroup( "EventTypes" );
00148   mShowBirthdaysFromKAB =
00149     config.readBoolEntry( "ShowBirthdaysFromContacts", true );
00150   mShowBirthdaysFromCal =
00151     config.readBoolEntry( "ShowBirthdaysFromCalendar", true );
00152 
00153   mShowAnniversariesFromKAB =
00154     config.readBoolEntry( "ShowAnniversariesFromContacts", true );
00155   mShowAnniversariesFromCal =
00156     config.readBoolEntry( "ShowAnniversariesFromCalendar", true );
00157 
00158   mShowHolidays =
00159     config.readBoolEntry( "ShowHolidays", true );
00160 
00161   mShowSpecialsFromCal =
00162     config.readBoolEntry( "ShowSpecialsFromCalendar", true );
00163 
00164   updateView();
00165 }
00166 
00167 bool SDSummaryWidget::initHolidays()
00168 {
00169   KConfig hconfig( "korganizerrc" );
00170   hconfig.setGroup( "Time & Date" );
00171   QString location = hconfig.readEntry( "Holidays" );
00172   if ( !location.isEmpty() ) {
00173     if ( mHolidays ) delete mHolidays;
00174     mHolidays = new KHolidays( location );
00175     return true;
00176   }
00177   return false;
00178 }
00179 
00180 // number of days remaining in an Event
00181 int SDSummaryWidget::span( KCal::Event *event )
00182 {
00183   int span=1;
00184   if ( event->isMultiDay() && event->doesFloat() ) {
00185     QDate d = event->dtStart().date();
00186     if ( d < QDate::currentDate() ) {
00187       d = QDate::currentDate();
00188     }
00189     while ( d < event->dtEnd().date() ) {
00190       span++;
00191       d=d.addDays( 1 );
00192     }
00193   }
00194   return span;
00195 }
00196 
00197 // day of a multiday Event
00198 int SDSummaryWidget::dayof( KCal::Event *event, const QDate& date )
00199 {
00200   int dayof=1;
00201   QDate d = event->dtStart().date();
00202   if ( d < QDate::currentDate() ) {
00203     d = QDate::currentDate();
00204   }
00205   while ( d < event->dtEnd().date() ) {
00206     if ( d < date ) {
00207       dayof++;
00208     }
00209     d = d.addDays( 1 );
00210   }
00211   return dayof;
00212 }
00213 
00214 
00215 
00216 void SDSummaryWidget::updateView()
00217 {
00218   mLabels.setAutoDelete( true );
00219   mLabels.clear();
00220   mLabels.setAutoDelete( false );
00221 
00222   KIconLoader loader( "kdepim" );
00223 
00224   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00225   QValueList<SDEntry> dates;
00226   QLabel *label = 0;
00227 
00228   // No reason to show the date year
00229   QString savefmt = KGlobal::locale()->dateFormat();
00230   KGlobal::locale()->setDateFormat( KGlobal::locale()->
00231                                     dateFormat().replace( 'Y', ' ' ) );
00232 
00233   // Search for Birthdays and Anniversaries in the Addressbook
00234   KABC::AddressBook::Iterator it;
00235   for ( it = ab->begin(); it != ab->end(); ++it ) {
00236     QDate birthday = (*it).birthday().date();
00237     if ( birthday.isValid() && mShowBirthdaysFromKAB ) {
00238       SDEntry entry;
00239       entry.type = IncidenceTypeContact;
00240       entry.category = CategoryBirthday;
00241       dateDiff( birthday, entry.daysTo, entry.yearsOld );
00242 
00243       entry.date = birthday;
00244       entry.addressee = *it;
00245       entry.span = 1;
00246       if ( entry.daysTo <= mDaysAhead )
00247         dates.append( entry );
00248     }
00249 
00250     QString anniversaryAsString =
00251       (*it).custom( "KADDRESSBOOK" , "X-Anniversary" );
00252     if ( !anniversaryAsString.isEmpty() ) {
00253       QDate anniversary = QDate::fromString( anniversaryAsString, Qt::ISODate );
00254       if ( anniversary.isValid() && mShowAnniversariesFromKAB ) {
00255         SDEntry entry;
00256         entry.type = IncidenceTypeContact;
00257         entry.category = CategoryAnniversary;
00258         dateDiff( anniversary, entry.daysTo, entry.yearsOld );
00259 
00260         entry.date = anniversary;
00261         entry.addressee = *it;
00262         entry.span = 1;
00263         if ( entry.daysTo <= mDaysAhead )
00264           dates.append( entry );
00265       }
00266     }
00267   }
00268 
00269   // Search for Birthdays, Anniversaries, Holidays, and Special Occasions
00270   // in the Calendar
00271   QDate dt;
00272   QDate currentDate = QDate::currentDate();
00273   for ( dt=currentDate;
00274         dt<=currentDate.addDays( mDaysAhead - 1 );
00275         dt=dt.addDays(1) ) {
00276     KCal::Event::List events = mCalendar->events( dt,
00277                                                   KCal::EventSortStartDate,
00278                                                   KCal::SortDirectionAscending );
00279     KCal::Event *ev;
00280     KCal::Event::List::ConstIterator it;
00281     for ( it=events.begin(); it!=events.end(); ++it ) {
00282       ev = *it;
00283       if ( !ev->categoriesStr().isEmpty() ) {
00284         QStringList::ConstIterator it2;
00285         QStringList c = ev->categories();
00286         for ( it2=c.begin(); it2!=c.end(); ++it2 ) {
00287 
00288           // Append Birthday Event?
00289           if ( mShowBirthdaysFromCal &&
00290                ( ( *it2 ).upper() == i18n( "BIRTHDAY" ) ) ) {
00291             SDEntry entry;
00292             entry.type = IncidenceTypeEvent;
00293             entry.category = CategoryBirthday;
00294             entry.date = dt;
00295             entry.summary = ev->summary();
00296             entry.desc = ev->description();
00297             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00298             entry.span = 1;
00299             dates.append( entry );
00300             break;
00301           }
00302 
00303           // Append Anniversary Event?
00304           if ( mShowAnniversariesFromCal &&
00305                ( ( *it2 ).upper() == i18n( "ANNIVERSARY" ) ) ) {
00306             SDEntry entry;
00307             entry.type = IncidenceTypeEvent;
00308             entry.category = CategoryAnniversary;
00309             entry.date = dt;
00310             entry.summary = ev->summary();
00311             entry.desc = ev->description();
00312             dateDiff( ev->dtStart().date(), entry.daysTo, entry.yearsOld );
00313             entry.span = 1;
00314             dates.append( entry );
00315             break;
00316           }
00317 
00318           // Append Holiday Event?
00319           if ( mShowHolidays &&
00320                ( ( *it2 ).upper() == i18n( "HOLIDAY" ) ) ) {
00321             SDEntry entry;
00322             entry.type = IncidenceTypeEvent;
00323             entry.category = CategoryHoliday;
00324             entry.date = dt;
00325             entry.summary = ev->summary();
00326             entry.desc = ev->description();
00327             dateDiff( dt, entry.daysTo, entry.yearsOld );
00328             entry.yearsOld = -1; //ignore age of holidays
00329             entry.span = span( ev );
00330             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00331               break;
00332             dates.append( entry );
00333             break;
00334           }
00335 
00336           // Append Special Occasion Event?
00337           if ( mShowSpecialsFromCal &&
00338                ( ( *it2 ).upper() == i18n( "SPECIAL OCCASION" ) ) ) {
00339             SDEntry entry;
00340             entry.type = IncidenceTypeEvent;
00341             entry.category = CategoryOther;
00342             entry.date = dt;
00343             entry.summary = ev->summary();
00344             entry.desc = ev->description();
00345             dateDiff( dt, entry.daysTo, entry.yearsOld );
00346             entry.yearsOld = -1; //ignore age of special occasions
00347             entry.span = span( ev );
00348             if ( entry.span > 1 && dayof( ev, dt ) > 1 ) // skip days 2,3,...
00349               break;
00350             dates.append( entry );
00351             break;
00352           }
00353         }
00354       }
00355     }
00356   }
00357 
00358   // Seach for Holidays
00359   if ( mShowHolidays ) {
00360     if ( initHolidays() ) {
00361       for ( dt=currentDate;
00362             dt<=currentDate.addDays( mDaysAhead - 1 );
00363             dt=dt.addDays(1) ) {
00364         QValueList<KHoliday> holidays = mHolidays->getHolidays( dt );
00365         QValueList<KHoliday>::ConstIterator it = holidays.begin();
00366         for ( ; it != holidays.end(); ++it ) {
00367           SDEntry entry;
00368           entry.type = IncidenceTypeEvent;
00369           entry.category = ((*it).Category==KHolidays::HOLIDAY)?CategoryHoliday:CategoryOther;
00370           entry.date = dt;
00371           entry.summary = (*it).text;
00372           dateDiff( dt, entry.daysTo, entry.yearsOld );
00373           entry.yearsOld = -1; //ignore age of holidays
00374           entry.span = 1;
00375           dates.append( entry );
00376         }
00377       }
00378     }
00379   }
00380 
00381   // Sort, then Print the Special Dates
00382   qHeapSort( dates );
00383 
00384   if ( !dates.isEmpty() ) {
00385     int counter = 0;
00386     QValueList<SDEntry>::Iterator addrIt;
00387     QString lines;
00388     for ( addrIt = dates.begin(); addrIt != dates.end(); ++addrIt ) {
00389       bool makeBold = (*addrIt).daysTo == 0; // i.e., today
00390 
00391       // Pixmap
00392       QImage icon_img;
00393       QString icon_name;
00394       KABC::Picture pic;
00395       switch( (*addrIt).category ) {
00396       case CategoryBirthday:
00397         icon_name = "calendarbirthday";
00398         pic = (*addrIt).addressee.photo();
00399         if ( pic.isIntern() && !pic.data().isNull() ) {
00400           QImage img = pic.data();
00401           if ( img.width() > img.height() ) {
00402             icon_img = img.scaleWidth( 32 );
00403           } else {
00404             icon_img = img.scaleHeight( 32 );
00405           }
00406         }
00407         break;
00408       case CategoryAnniversary:
00409         icon_name = "calendaranniversary";
00410         pic = (*addrIt).addressee.photo();
00411         if ( pic.isIntern() && !pic.data().isNull() ) {
00412           QImage img = pic.data();
00413           if ( img.width() > img.height() ) {
00414             icon_img = img.scaleWidth( 32 );
00415           } else {
00416             icon_img = img.scaleHeight( 32 );
00417           }
00418         }
00419         break;
00420       case CategoryHoliday:
00421         icon_name = "calendarholiday"; break;
00422       case CategoryOther:
00423         icon_name = "cookie"; break;
00424       }
00425       label = new QLabel( this );
00426       if ( icon_img.isNull() ) {
00427         label->setPixmap( KGlobal::iconLoader()->loadIcon( icon_name,
00428                                                            KIcon::Small ) );
00429       } else {
00430         label->setPixmap( icon_img );
00431       }
00432       label->setMaximumWidth( label->minimumSizeHint().width() );
00433       label->setAlignment( AlignVCenter );
00434       mLayout->addWidget( label, counter, 0 );
00435       mLabels.append( label );
00436 
00437       // Event date
00438       QString datestr;
00439 
00440       //Muck with the year -- change to the year 'daysTo' days away
00441       int year = currentDate.addDays( (*addrIt).daysTo ).year();
00442       QDate sD = QDate::QDate( year,
00443                            (*addrIt).date.month(), (*addrIt).date.day() );
00444 
00445       if ( (*addrIt).daysTo == 0 ) {
00446         datestr = i18n( "Today" );
00447       } else if ( (*addrIt).daysTo == 1 ) {
00448         datestr = i18n( "Tomorrow" );
00449       } else {
00450         datestr = KGlobal::locale()->formatDate( sD );
00451       }
00452       // Print the date span for multiday, floating events, for the
00453       // first day of the event only.
00454       if ( (*addrIt).span > 1 ) {
00455         QString endstr =
00456           KGlobal::locale()->formatDate( sD.addDays( (*addrIt).span - 1 ) );
00457         datestr += " -\n " + endstr;
00458       }
00459 
00460       label = new QLabel( datestr, this );
00461       label->setAlignment( AlignLeft | AlignVCenter );
00462       mLayout->addWidget( label, counter, 1 );
00463       mLabels.append( label );
00464       if ( makeBold ) {
00465         QFont font = label->font();
00466         font.setBold( true );
00467         label->setFont( font );
00468       }
00469 
00470       // Countdown
00471       label = new QLabel( this );
00472       if ( (*addrIt).daysTo == 0 ) {
00473         label->setText( i18n( "now" ) );
00474       } else {
00475         label->setText( i18n( "in 1 day", "in %n days", (*addrIt).daysTo ) );
00476       }
00477 
00478       label->setAlignment( AlignLeft | AlignVCenter );
00479       mLayout->addWidget( label, counter, 2 );
00480       mLabels.append( label );
00481 
00482       // What
00483       QString what;
00484       switch( (*addrIt).category ) {
00485       case CategoryBirthday:
00486         what = i18n( "Birthday" ); break;
00487       case CategoryAnniversary:
00488         what = i18n( "Anniversary" ); break;
00489       case CategoryHoliday:
00490         what = i18n( "Holiday" ); break;
00491       case CategoryOther:
00492         what = i18n( "Special Occasion" ); break;
00493       }
00494       label = new QLabel( this );
00495       label->setText( what );
00496       label->setAlignment( AlignLeft | AlignVCenter );
00497       mLayout->addWidget( label, counter, 3 );
00498       mLabels.append( label );
00499 
00500       // Description
00501       if ( (*addrIt).type == IncidenceTypeContact ) {
00502         KURLLabel *urlLabel = new KURLLabel( this );
00503         urlLabel->installEventFilter( this );
00504         urlLabel->setURL( (*addrIt).addressee.uid() );
00505         urlLabel->setText( (*addrIt).addressee.realName() );
00506         urlLabel->setTextFormat( Qt::RichText );
00507         mLayout->addWidget( urlLabel, counter, 4 );
00508         mLabels.append( urlLabel );
00509 
00510         connect( urlLabel, SIGNAL( leftClickedURL( const QString& ) ),
00511                  this, SLOT( mailContact( const QString& ) ) );
00512         connect( urlLabel, SIGNAL( rightClickedURL( const QString& ) ),
00513                  this, SLOT( popupMenu( const QString& ) ) );
00514       } else {
00515         label = new QLabel( this );
00516         label->setText( (*addrIt).summary );
00517         label->setTextFormat( Qt::RichText );
00518         mLayout->addWidget( label, counter, 4 );
00519         mLabels.append( label );
00520         if ( !(*addrIt).desc.isEmpty() ) {
00521           QToolTip::add( label, (*addrIt).desc );
00522         }
00523       }
00524 
00525      // Age
00526       if ( (*addrIt).category == CategoryBirthday ||
00527            (*addrIt).category == CategoryAnniversary ) {
00528         label = new QLabel( this );
00529         if ( (*addrIt).yearsOld <= 0 ) {
00530           label->setText( "" );
00531         } else {
00532           label->setText( i18n( "one year", "%n years", (*addrIt).yearsOld  ) );
00533         }
00534         label->setAlignment( AlignLeft | AlignVCenter );
00535         mLayout->addWidget( label, counter, 5 );
00536         mLabels.append( label );
00537       }
00538 
00539       counter++;
00540     }
00541   } else {
00542     label = new QLabel(
00543         i18n( "No special dates within the next 1 day",
00544               "No special dates pending within the next %n days",
00545               mDaysAhead ), this, "nothing to see" );
00546     label->setAlignment( AlignHCenter | AlignVCenter );
00547     mLayout->addMultiCellWidget( label, 0, 0, 0, 4 );
00548     mLabels.append( label );
00549   }
00550 
00551   for ( label = mLabels.first(); label; label = mLabels.next() )
00552     label->show();
00553 
00554   KGlobal::locale()->setDateFormat( savefmt );
00555 }
00556 
00557 void SDSummaryWidget::mailContact( const QString &uid )
00558 {
00559   KABC::StdAddressBook *ab = KABC::StdAddressBook::self( true );
00560   QString email = ab->findByUid( uid ).fullEmail();
00561 
00562   kapp->invokeMailer( email, QString::null );
00563 }
00564 
00565 void SDSummaryWidget::viewContact( const QString &uid )
00566 {
00567   if ( !mPlugin->isRunningStandalone() )
00568     mPlugin->core()->selectPlugin( "kontact_kaddressbookplugin" );
00569   else
00570     mPlugin->bringToForeground();
00571 
00572   DCOPRef dcopCall( "kaddressbook", "KAddressBookIface" );
00573   dcopCall.send( "showContactEditor(QString)", uid );
00574 }
00575 
00576 void SDSummaryWidget::popupMenu( const QString &uid )
00577 {
00578   KPopupMenu popup( this );
00579   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kmail", KIcon::Small ),
00580                     i18n( "Send &Mail" ), 0 );
00581   popup.insertItem( KGlobal::iconLoader()->loadIcon( "kaddressbook", KIcon::Small ),
00582                     i18n( "View &Contact" ), 1 );
00583 
00584   switch ( popup.exec( QCursor::pos() ) ) {
00585     case 0:
00586       mailContact( uid );
00587       break;
00588     case 1:
00589       viewContact( uid );
00590       break;
00591   }
00592 }
00593 
00594 bool SDSummaryWidget::eventFilter( QObject *obj, QEvent* e )
00595 {
00596   if ( obj->inherits( "KURLLabel" ) ) {
00597     KURLLabel* label = static_cast<KURLLabel*>( obj );
00598     if ( e->type() == QEvent::Enter )
00599       emit message( i18n( "Mail to:\"%1\"" ).arg( label->text() ) );
00600     if ( e->type() == QEvent::Leave )
00601       emit message( QString::null );
00602   }
00603 
00604   return Kontact::Summary::eventFilter( obj, e );
00605 }
00606 
00607 void SDSummaryWidget::dateDiff( const QDate &date, int &days, int &years )
00608 {
00609   QDate currentDate;
00610   QDate eventDate;
00611 
00612   if ( QDate::leapYear( date.year() ) && date.month() == 2 && date.day() == 29 ) {
00613     currentDate = QDate( date.year(), QDate::currentDate().month(), QDate::currentDate().day() );
00614     if ( !QDate::leapYear( QDate::currentDate().year() ) )
00615       eventDate = QDate( date.year(), date.month(), 28 ); // celebrate one day earlier ;)
00616     else
00617       eventDate = QDate( date.year(), date.month(), date.day() );
00618   } else {
00619     currentDate = QDate( 0, QDate::currentDate().month(), QDate::currentDate().day() );
00620     eventDate = QDate( 0, date.month(), date.day() );
00621   }
00622 
00623   int offset = currentDate.daysTo( eventDate );
00624   if ( offset < 0 ) {
00625     days = 365 + offset;
00626     years = QDate::currentDate().year() + 1 - date.year();
00627   } else {
00628     days = offset;
00629     years = QDate::currentDate().year() - date.year();
00630   }
00631 }
00632 
00633 QStringList SDSummaryWidget::configModules() const
00634 {
00635   return QStringList( "kcmsdsummary.desktop" );
00636 }
00637 
00638 #include "sdsummarywidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys