• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kontact

apptsummarywidget.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of Kontact.
00003 
00004   Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
00005   Copyright (c) 2005-2006,2008 Allen Winter <winter@kde.org>
00006 
00007   This program is free software; you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation; either version 2 of the License, or
00010   (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015   GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License along
00018   with this program; if not, write to the Free Software Foundation, Inc.,
00019   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021   As a special exception, permission is given to link this program
00022   with any edition of Qt, and distribute the resulting executable,
00023   without including the source code for Qt in the source distribution.
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   // Update Configuration
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   // The event print consists of the following fields:
00098   //  icon:start date:days-to-go:summary:time range
00099   // where,
00100   //   the icon is the typical event icon
00101   //   the start date is the event start date
00102   //   the days-to-go is the #days until the event starts
00103   //   the summary is the event summary
00104   //   the time range is the start-end time (only for non-floating events)
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     // prevent implicitely sharing while finding recurring events
00129     // replacing the QDate with the currentDate
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     // sort the events for this date by summary
00143     events = KCal::Calendar::sortEvents( &events,
00144                                          KCal::EventSortSummary,
00145                                          KCal::SortDirectionAscending );
00146     // sort the events for this date by start date
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       // ### If you change anything in the multiday logic below, make sure
00157       //     you test it with:
00158       //     - a multiday, all-day event currently in progress
00159       //     - a multiday, all-day event in the future
00160       //     - a multiday event with associated time which is in progress
00161       //     - a multiday event with associated time which is in the future
00162 
00163       // Count number of days remaining in multiday event
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       // If this date is part of a floating, multiday event, then we
00188       // only make a print for the first day of the event.
00189       if ( ev->isMultiDay() && ev->allDay() && !firstDayOfMultiday ) {
00190         continue;
00191       }
00192 
00193       // Icon label
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       // Start date label
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       // Print the date span for multiday, floating events, for the
00215       // first day of the event only.
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       // Days to go label
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       // Summary label
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       // Time range label (only for non-floating events)
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" ); //ensure loaded
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" ); //ensure loaded
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 ); //krazy:exclude=nullstrassign for old broken gcc
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 ); // celebrate one day earlier ;)
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   //simply check categories because the birthdays resource always adds
00390   //the appropriate category to the event.
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"

kontact

Skip menu "kontact"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal