00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "apptsummarywidget.h"
00027 #include "korganizerplugin.h"
00028 #include "korganizerinterface.h"
00029
00030 #include <korganizer/stdcalendar.h>
00031 #include <kontactinterfaces/core.h>
00032
00033 #include <kcal/incidenceformatter.h>
00034 #include <kcal/resourcecalendar.h>
00035
00036 #include <kconfiggroup.h>
00037 #include <kiconloader.h>
00038 #include <klocale.h>
00039 #include <kmenu.h>
00040 #include <kurllabel.h>
00041
00042 #include <QDateTime>
00043 #include <QGridLayout>
00044 #include <QLabel>
00045 #include <QVBoxLayout>
00046 #include <QTextDocument>
00047
00048 ApptSummaryWidget::ApptSummaryWidget( KOrganizerPlugin *plugin, QWidget *parent )
00049 : Kontact::Summary( parent ), mPlugin( plugin ), mCalendar( 0 )
00050 {
00051 QVBoxLayout *mainLayout = new QVBoxLayout( this );
00052 mainLayout->setSpacing( 3 );
00053 mainLayout->setMargin( 3 );
00054
00055 QWidget *header = createHeader(
00056 this, "view-calendar-upcoming-events", i18n( "Upcoming Events" ) );
00057 mainLayout->addWidget( header );
00058
00059 mLayout = new QGridLayout();
00060 mainLayout->addItem( mLayout );
00061 mLayout->setSpacing( 3 );
00062 mLayout->setRowStretch( 6, 1 );
00063
00064 mCalendar = KOrg::StdCalendar::self();
00065 mCalendar->load();
00066
00067 connect( mCalendar, SIGNAL(calendarChanged()), this, SLOT(updateView()) );
00068 connect( mPlugin->core(), SIGNAL(dayChanged(const QDate&)), this, SLOT(updateView()) );
00069
00070
00071 configUpdated();
00072 }
00073
00074 ApptSummaryWidget::~ApptSummaryWidget()
00075 {
00076 }
00077
00078 void ApptSummaryWidget::configUpdated()
00079 {
00080 KConfig config( "kcmapptsummaryrc" );
00081
00082 KConfigGroup group = config.group( "Days" );
00083 mDaysAhead = group.readEntry( "DaysToShow", 7 );
00084
00085 group = config.group( "Show" );
00086 mShowBirthdaysFromCal = group.readEntry( "BirthdaysFromCalendar", true );
00087 mShowAnniversariesFromCal = group.readEntry( "AnniversariesFromCalendar", true );
00088
00089 updateView();
00090 }
00091
00092 void ApptSummaryWidget::updateView()
00093 {
00094 qDeleteAll( mLabels );
00095 mLabels.clear();
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 QLabel *label = 0;
00107 int counter = 0;
00108
00109 KIconLoader loader( "korganizer" );
00110 QPixmap pm = loader.loadIcon( "view-calendar-day", KIconLoader::Small );
00111
00112 QString str;
00113 QDate dt;
00114 QDate currentDate = QDate::currentDate();
00115 for ( dt = currentDate;
00116 dt <= currentDate.addDays( mDaysAhead - 1 );
00117 dt = dt.addDays( 1 ) ) {
00118
00119 KCal::Event *ev;
00120
00121 KCal::Event::List events_orig = mCalendar->events( dt, mCalendar->timeSpec() );
00122 KCal::Event::List::ConstIterator it = events_orig.begin();
00123
00124 KCal::Event::List events;
00125 events.setAutoDelete( true );
00126 KDateTime qdt;
00127
00128
00129
00130 for ( ; it != events_orig.end(); ++it ) {
00131 ev = (*it)->clone();
00132 if ( ev->recursOn( dt, mCalendar->timeSpec() ) ) {
00133 qdt = ev->dtStart();
00134 qdt.setDate( dt );
00135 ev->setDtStart( qdt );
00136 }
00137 if ( !skip( ev ) ) {
00138 events.append( ev );
00139 }
00140 }
00141
00142
00143 events = KCal::Calendar::sortEvents( &events,
00144 KCal::EventSortSummary,
00145 KCal::SortDirectionAscending );
00146
00147 events = KCal::Calendar::sortEvents( &events,
00148 KCal::EventSortStartDate,
00149 KCal::SortDirectionAscending );
00150
00151 for ( it=events.begin(); it != events.end(); ++it ) {
00152 ev = *it;
00153 bool makeBold = false;
00154 int daysTo = -1;
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 int span = 1;
00165 int dayof = 1;
00166 if ( ev->isMultiDay() ) {
00167 QDate d = ev->dtStart().date();
00168 if ( d < currentDate ) {
00169 dayof += d.daysTo( currentDate );
00170 span += d.daysTo( currentDate );
00171 d = currentDate;
00172 }
00173 while ( d < ev->dtEnd().date() ) {
00174 if ( d < dt ) {
00175 dayof++;
00176 }
00177 span++;
00178 d = d.addDays( 1 );
00179 }
00180 }
00181
00182 QDate startOfMultiday = ev->dtStart().date();
00183 if ( startOfMultiday < currentDate )
00184 startOfMultiday = currentDate;
00185 bool firstDayOfMultiday = ( dt == startOfMultiday );
00186
00187
00188
00189 if ( ev->isMultiDay() && ev->allDay() && !firstDayOfMultiday ) {
00190 continue;
00191 }
00192
00193
00194 label = new QLabel( this );
00195 label->setPixmap( pm );
00196 label->setMaximumWidth( label->minimumSizeHint().width() );
00197 mLayout->addWidget( label, counter, 0 );
00198 mLabels.append( label );
00199
00200
00201 str = "";
00202 QDate sD = QDate( dt.year(), dt.month(), dt.day() );
00203 if ( ( sD.month() == currentDate.month() ) &&
00204 ( sD.day() == currentDate.day() ) ) {
00205 str = i18nc( "@label the appointment is today", "Today" );
00206 makeBold = true;
00207 } else if ( ( sD.month() == currentDate.addDays( 1 ).month() ) &&
00208 ( sD.day() == currentDate.addDays( 1 ).day() ) ) {
00209 str = i18nc( "@label the appointment is tomorrow", "Tomorrow" );
00210 } else {
00211 str = KGlobal::locale()->formatDate( sD, KLocale::FancyLongDate );
00212 }
00213
00214
00215
00216 if ( ev->isMultiDay() && ev->allDay() && firstDayOfMultiday && span > 1 ) {
00217 str = KGlobal::locale()->formatDate( ev->dtStart().date(), KLocale::FancyLongDate );
00218 str += " -\n " +
00219 KGlobal::locale()->formatDate( sD.addDays( span-1 ), KLocale::FancyLongDate );
00220 }
00221
00222 label = new QLabel( str, this );
00223 label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
00224 mLayout->addWidget( label, counter, 1 );
00225 mLabels.append( label );
00226 if ( makeBold ) {
00227 QFont font = label->font();
00228 font.setBold( true );
00229 label->setFont( font );
00230 }
00231
00232
00233 str = "";
00234 dateDiff( startOfMultiday, daysTo );
00235 if ( ev->isMultiDay() && !ev->allDay() && daysTo == 0 )
00236 dateDiff( dt, daysTo );
00237 if ( daysTo > 0 ) {
00238 str = i18np( "in 1 day", "in %1 days", daysTo );
00239 } else {
00240 str = i18n( "now" );
00241 }
00242 label = new QLabel( str, this );
00243 label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
00244 mLayout->addWidget( label, counter, 2 );
00245 mLabels.append( label );
00246
00247
00248 str = ev->richSummary();
00249 if ( ev->isMultiDay() && !ev->allDay() ) {
00250 str.append( QString( " (%1/%2)" ).arg( dayof ).arg( span ) );
00251 }
00252
00253 KUrlLabel *urlLabel = new KUrlLabel( this );
00254 urlLabel->setText( str );
00255 urlLabel->setUrl( ev->uid() );
00256 urlLabel->installEventFilter( this );
00257 urlLabel->setTextFormat( Qt::RichText );
00258 mLayout->addWidget( urlLabel, counter, 3 );
00259 mLabels.append( urlLabel );
00260
00261 connect( urlLabel, SIGNAL(leftClickedUrl(const QString&)),
00262 this, SLOT(viewEvent(const QString&)) );
00263 connect( urlLabel, SIGNAL(rightClickedUrl(const QString&)),
00264 this, SLOT(popupMenu(const QString&)) );
00265
00266 QString tipText( KCal::IncidenceFormatter::toolTipString( ev, true ) );
00267 if ( !tipText.isEmpty() ) {
00268 urlLabel->setToolTip( tipText );
00269 }
00270
00271
00272 str = "";
00273 if ( !ev->allDay() ) {
00274 QTime sST = ev->dtStart().time();
00275 QTime sET = ev->dtEnd().time();
00276 if ( ev->isMultiDay() ) {
00277 if ( ev->dtStart().date() < dt ) {
00278 sST = QTime( 0, 0 );
00279 }
00280 if ( ev->dtEnd().date() > dt ) {
00281 sET = QTime( 23, 59 );
00282 }
00283 }
00284 str = i18nc( "Time from - to", "%1 - %2",
00285 KGlobal::locale()->formatTime( sST ),
00286 KGlobal::locale()->formatTime( sET ) );
00287 label = new QLabel( str, this );
00288 label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
00289 mLayout->addWidget( label, counter, 4 );
00290 mLabels.append( label );
00291 }
00292
00293 counter++;
00294 }
00295 }
00296
00297 if ( !counter ) {
00298 QLabel *noEvents = new QLabel(
00299 i18np( "No upcoming events starting within the next day",
00300 "No upcoming events starting within the next %1 days",
00301 mDaysAhead ), this );
00302 noEvents->setObjectName( "nothing to see" );
00303 noEvents->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
00304 mLayout->addWidget( noEvents, 0, 2 );
00305 mLabels.append( noEvents );
00306 }
00307
00308 Q_FOREACH( label, mLabels ) {
00309 label->show();
00310 }
00311 }
00312
00313 void ApptSummaryWidget::viewEvent( const QString &uid )
00314 {
00315 mPlugin->core()->selectPlugin( "kontact_korganizerplugin" );
00316 OrgKdeKorganizerKorganizerInterface korganizer(
00317 "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
00318 korganizer.editIncidence( uid );
00319 }
00320
00321 void ApptSummaryWidget::removeEvent( const QString &uid )
00322 {
00323 mPlugin->core()->selectPlugin( "kontact_korganizerplugin" );
00324 OrgKdeKorganizerKorganizerInterface korganizer(
00325 "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );
00326 korganizer.deleteIncidence( uid, false );
00327 }
00328
00329 void ApptSummaryWidget::popupMenu( const QString &uid )
00330 {
00331 KMenu popup( this );
00332 QAction *editIt = popup.addAction( i18n( "&Edit Appointment..." ) );
00333 QAction *delIt = popup.addAction( i18n( "&Delete Appointment" ) );
00334 delIt->setIcon( KIconLoader::global()->
00335 loadIcon( "edit-delete", KIconLoader::Small ) );
00336
00337 const QAction *selectedAction = popup.exec( QCursor::pos() );
00338 if ( selectedAction == editIt ) {
00339 viewEvent( uid );
00340 } else if ( selectedAction == delIt ) {
00341 removeEvent( uid );
00342 }
00343 }
00344
00345 bool ApptSummaryWidget::eventFilter( QObject *obj, QEvent *e )
00346 {
00347 if ( obj->inherits( "KUrlLabel" ) ) {
00348 KUrlLabel *label = static_cast<KUrlLabel*>( obj );
00349 if ( e->type() == QEvent::Enter ) {
00350 emit message( i18n( "Edit Event: \"%1\"", label->text() ) );
00351 }
00352 if ( e->type() == QEvent::Leave ) {
00353 emit message( QString::null );
00354 }
00355 }
00356
00357 return Kontact::Summary::eventFilter( obj, e );
00358 }
00359
00360 void ApptSummaryWidget::dateDiff( const QDate &date, int &days )
00361 {
00362 QDate currentDate;
00363 QDate eventDate;
00364
00365 if ( QDate::isLeapYear( date.year() ) && date.month() == 2 && date.day() == 29 ) {
00366 currentDate = QDate( date.year(), QDate::currentDate().month(), QDate::currentDate().day() );
00367 if ( !QDate::isLeapYear( QDate::currentDate().year() ) ) {
00368 eventDate = QDate( date.year(), date.month(), 28 );
00369 } else {
00370 eventDate = QDate( date.year(), date.month(), date.day() );
00371 }
00372 } else {
00373 currentDate = QDate( QDate::currentDate().year(),
00374 QDate::currentDate().month(),
00375 QDate::currentDate().day() );
00376 eventDate = QDate( QDate::currentDate().year(), date.month(), date.day() );
00377 }
00378
00379 int offset = currentDate.daysTo( eventDate );
00380 if ( offset < 0 ) {
00381 days = 365 + offset;
00382 } else {
00383 days = offset;
00384 }
00385 }
00386
00387 bool ApptSummaryWidget::skip( KCal::Event *event )
00388 {
00389
00390
00391 QStringList c = event->categories();
00392 if ( !mShowBirthdaysFromCal &&
00393 c.contains( i18n( "BIRTHDAY" ), Qt::CaseInsensitive ) ) {
00394 return true;
00395 }
00396 if ( !mShowAnniversariesFromCal &&
00397 c.contains( i18n( "ANNIVERSARY" ), Qt::CaseInsensitive ) ) {
00398 return true;
00399 }
00400
00401 return false;
00402 }
00403
00404 QStringList ApptSummaryWidget::configModules() const
00405 {
00406 return QStringList( "kcmapptsummary.desktop" );
00407 }
00408
00409 #include "apptsummarywidget.moc"