korganizer

koeditorgeneral.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00004     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
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 
00026 #include <qwidget.h>
00027 #include <qtooltip.h>
00028 #include <qlayout.h>
00029 #include <qvbox.h>
00030 #include <qhbox.h>
00031 #include <qbuttongroup.h>
00032 #include <qvgroupbox.h>
00033 #include <qwidgetstack.h>
00034 #include <qdatetime.h>
00035 #include <qlineedit.h>
00036 #include <qlabel.h>
00037 #include <qcheckbox.h>
00038 #include <qpushbutton.h>
00039 #include <qcombobox.h>
00040 #include <qspinbox.h>
00041 #include <qwhatsthis.h>
00042 
00043 #include <kglobal.h>
00044 #include <kdialog.h>
00045 #include <kdebug.h>
00046 #include <klocale.h>
00047 #include <kiconloader.h>
00048 #include <kmessagebox.h>
00049 #include <kfiledialog.h>
00050 #include <ksqueezedtextlabel.h>
00051 #include <kstandarddirs.h>
00052 #include <ktextedit.h>
00053 #include <krestrictedline.h>
00054 
00055 #include <libkcal/todo.h>
00056 #include <libkcal/event.h>
00057 #include <libkcal/incidenceformatter.h>
00058 
00059 #include <libkdepim/kdateedit.h>
00060 #include <libkdepim/categoryselectdialog.h>
00061 
00062 #include "koprefs.h"
00063 #include "koglobals.h"
00064 
00065 #include "koeditorgeneral.h"
00066 #include "koeditoralarms.h"
00067 #include "koeditorattachments.h"
00068 #include "koeditorgeneral.moc"
00069 #include "kohelper.h"
00070 
00071 KOEditorGeneral::KOEditorGeneral(QObject* parent, const char* name) :
00072   QObject( parent, name ), mAttachments(0)
00073 {
00074   mType = "Event";
00075   mAlarmList.setAutoDelete( true );
00076 }
00077 
00078 KOEditorGeneral::~KOEditorGeneral()
00079 {
00080 }
00081 
00082 
00083 FocusLineEdit::FocusLineEdit( QWidget *parent )
00084   : QLineEdit( parent ), mSkipFirst( true )
00085 {
00086 }
00087 
00088 void FocusLineEdit::focusInEvent ( QFocusEvent *e )
00089 {
00090   if ( !mSkipFirst ) {
00091     emit focusReceivedSignal();
00092   } else {
00093     mSkipFirst = false;
00094   }
00095   QLineEdit::focusInEvent( e );
00096 }
00097 
00098 
00099 void KOEditorGeneral::initHeader( QWidget *parent,QBoxLayout *topLayout)
00100 {
00101   QGridLayout *headerLayout = new QGridLayout();
00102   headerLayout->setSpacing( topLayout->spacing() );
00103   topLayout->addLayout( headerLayout );
00104 
00105 #if 0
00106   mOwnerLabel = new QLabel(i18n("Owner:"),parent);
00107   headerLayout->addMultiCellWidget(mOwnerLabel,0,0,0,1);
00108 #endif
00109 
00110   QString whatsThis = i18n("Sets the Title of this event or to-do.");
00111   QLabel *summaryLabel = new QLabel( i18n("T&itle:"), parent );
00112   QWhatsThis::add( summaryLabel, whatsThis );
00113   QFont f = summaryLabel->font();
00114   f.setBold( true );
00115   summaryLabel->setFont(f);
00116   headerLayout->addWidget(summaryLabel,1,0);
00117 
00118   mSummaryEdit = new FocusLineEdit( parent );
00119   QWhatsThis::add( mSummaryEdit, whatsThis );
00120   connect( mSummaryEdit, SIGNAL( focusReceivedSignal() ),
00121            SIGNAL( focusReceivedSignal() ) );
00122   headerLayout->addWidget(mSummaryEdit,1,1);
00123   summaryLabel->setBuddy( mSummaryEdit );
00124 
00125   mAttendeeSummaryLabel = new QLabel( parent );
00126   updateAttendeeSummary( 0 );
00127   headerLayout->addWidget( mAttendeeSummaryLabel, 1, 2 );
00128 
00129   whatsThis = i18n("Sets where the event or to-do will take place.");
00130   QLabel *locationLabel = new QLabel( i18n("&Location:"), parent );
00131   QWhatsThis::add( locationLabel, whatsThis );
00132   headerLayout->addWidget(locationLabel,2,0);
00133 
00134   mLocationEdit = new QLineEdit( parent );
00135   QWhatsThis::add( mLocationEdit, whatsThis );
00136   headerLayout->addMultiCellWidget( mLocationEdit, 2, 2, 1, 2 );
00137   locationLabel->setBuddy( mLocationEdit );
00138 
00139   QBoxLayout *thirdLineLayout = new QHBoxLayout();
00140   headerLayout->addMultiCellLayout( thirdLineLayout, 3, 3, 0, 2 );
00141 
00142   mResourceLabel = new QLabel( parent );
00143   mResourceLabel->hide();
00144   thirdLineLayout->addWidget( mResourceLabel );
00145 
00146   whatsThis = i18n("Allows you to select the categories that this event or to-do belongs to.");
00147   QLabel *categoriesLabel = new QLabel( i18n("Categories:"), parent );
00148   QWhatsThis::add( categoriesLabel, whatsThis );
00149   thirdLineLayout->addWidget( categoriesLabel );
00150   mCategoriesLabel = new KSqueezedTextLabel( parent );
00151   QWhatsThis::add( mCategoriesLabel, whatsThis );
00152   mCategoriesLabel->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00153   thirdLineLayout->addWidget( mCategoriesLabel );
00154 
00155   mCategoriesButton = new QPushButton( parent );
00156   mCategoriesButton->setText(i18n("&Select..."));
00157   QWhatsThis::add( mCategoriesButton, whatsThis );
00158   connect(mCategoriesButton,SIGNAL(clicked()),SLOT(selectCategories()));
00159   thirdLineLayout->addWidget( mCategoriesButton );
00160 }
00161 
00162 void KOEditorGeneral::initSecrecy(QWidget *parent, QBoxLayout *topLayout)
00163 {
00164   QBoxLayout *secrecyLayout = new QHBoxLayout( topLayout );
00165 
00166   QLabel *secrecyLabel = new QLabel(i18n("Acc&ess:"),parent);
00167   QString whatsThis = i18n("Sets whether the access to this event or to-do "
00168                "is restricted. Please note that KOrganizer "
00169                "currently does not use this setting, so the "
00170                "implementation of the restrictions will depend "
00171                "on the groupware server. This means that events "
00172                "or to-dos marked as private or confidential may "
00173                "be visible to others.");
00174   QWhatsThis::add( secrecyLabel, whatsThis );
00175   secrecyLayout->addWidget(secrecyLabel);
00176 
00177   mSecrecyCombo = new QComboBox(parent);
00178   QWhatsThis::add( mSecrecyCombo, whatsThis );
00179   mSecrecyCombo->insertStringList(Incidence::secrecyList());
00180   secrecyLayout->addWidget(mSecrecyCombo);
00181   secrecyLabel->setBuddy( mSecrecyCombo );
00182 }
00183 
00184 void KOEditorGeneral::initDescription(QWidget *parent,QBoxLayout *topLayout)
00185 {
00186   mDescriptionEdit = new KTextEdit(parent);
00187   QWhatsThis::add( mDescriptionEdit,
00188            i18n("Sets the description for this event or to-do. This "
00189             "will be displayed in a reminder if one is set, "
00190             "as well as in a tooltip when you hover over the "
00191             "event.") );
00192   mDescriptionEdit->append("");
00193   mDescriptionEdit->setReadOnly(false);
00194   mDescriptionEdit->setOverwriteMode(false);
00195   mDescriptionEdit->setWordWrap( KTextEdit::WidgetWidth );
00196   mDescriptionEdit->setTabChangesFocus( true );;
00197   topLayout->addWidget(mDescriptionEdit, 4);
00198 }
00199 
00200 void KOEditorGeneral::initAlarm(QWidget *parent,QBoxLayout *topLayout)
00201 {
00202   QBoxLayout *alarmLayout = new QHBoxLayout(topLayout);
00203 
00204   mAlarmBell = new QLabel(parent);
00205   mAlarmBell->setPixmap(KOGlobals::self()->smallIcon("bell"));
00206   alarmLayout->addWidget( mAlarmBell );
00207 
00208 
00209   mAlarmStack = new QWidgetStack( parent );
00210   alarmLayout->addWidget( mAlarmStack );
00211 
00212   mAlarmInfoLabel = new QLabel( i18n("No reminders configured"), mAlarmStack );
00213   mAlarmStack->addWidget( mAlarmInfoLabel, AdvancedAlarmLabel );
00214 
00215   QHBox *simpleAlarmBox = new QHBox( mAlarmStack );
00216   mAlarmStack->addWidget( simpleAlarmBox, SimpleAlarmPage );
00217 
00218   mAlarmButton = new QCheckBox(i18n("&Reminder:"), simpleAlarmBox );
00219   QWhatsThis::add( mAlarmButton,
00220        i18n("Activates a reminder for this event or to-do.") );
00221 
00222   QString whatsThis = i18n("Sets how long before the event occurs "
00223                            "the reminder will be triggered.");
00224   mAlarmTimeEdit = new QSpinBox( 0, 99999, 1, simpleAlarmBox, "alarmTimeEdit" );
00225   mAlarmTimeEdit->setValue( 0 );
00226   QWhatsThis::add( mAlarmTimeEdit, whatsThis );
00227 
00228   mAlarmIncrCombo = new QComboBox( false, simpleAlarmBox );
00229   QWhatsThis::add( mAlarmIncrCombo, whatsThis );
00230   mAlarmIncrCombo->insertItem( i18n("minute(s)") );
00231   mAlarmIncrCombo->insertItem( i18n("hour(s)") );
00232   mAlarmIncrCombo->insertItem( i18n("day(s)") );
00233 //  mAlarmIncrCombo->setMinimumHeight(20);
00234   connect(mAlarmButton, SIGNAL(toggled(bool)), mAlarmTimeEdit, SLOT(setEnabled(bool)));
00235   connect(mAlarmButton, SIGNAL(toggled(bool)), mAlarmIncrCombo, SLOT(setEnabled(bool)));
00236   mAlarmTimeEdit->setEnabled( false );
00237   mAlarmIncrCombo->setEnabled( false );
00238 
00239   mAlarmEditButton = new QPushButton( i18n("Advanced..."), parent );
00240   mAlarmEditButton->setEnabled( false );
00241   alarmLayout->addWidget( mAlarmEditButton );
00242   connect( mAlarmButton, SIGNAL(toggled(bool)), mAlarmEditButton, SLOT(setEnabled( bool)));
00243   connect( mAlarmEditButton, SIGNAL( clicked() ),
00244       SLOT( editAlarms() ) );
00245 
00246 }
00247 
00248 void KOEditorGeneral::initAttachments(QWidget *parent,QBoxLayout *topLayout)
00249 {
00250   mAttachments = new KOEditorAttachments( KDialog::spacingHint(), parent );
00251   connect( mAttachments, SIGNAL( openURL( const KURL & ) ) ,
00252            this, SIGNAL( openURL( const KURL & ) ) );
00253   topLayout->addWidget( mAttachments, 1 );
00254 }
00255 
00256 void KOEditorGeneral::setType( const QCString &type )
00257 {
00258   // must be "Event", "Todo", "Journal", etc.
00259   mType = type;
00260 }
00261 
00262 void KOEditorGeneral::addAttachments( const QStringList &attachments,
00263                                       const QStringList &mimeTypes,
00264                                       bool inlineAttachments )
00265 {
00266   QStringList::ConstIterator it;
00267   uint i = 0;
00268   for ( it = attachments.begin(); it != attachments.end(); ++it, ++i ) {
00269     QString mimeType;
00270     if ( mimeTypes.count() > i )
00271       mimeType = mimeTypes[ i ];
00272     mAttachments->addUriAttachment( *it, mimeType, QString(), inlineAttachments );
00273   }
00274 }
00275 
00276 void KOEditorGeneral::selectCategories()
00277 {
00278   KPIM::CategorySelectDialog *categoryDialog = new KPIM::CategorySelectDialog( KOPrefs::instance(), mCategoriesButton    );
00279   KOGlobals::fitDialogToScreen( categoryDialog );
00280   categoryDialog->setSelected( mCategories );
00281 
00282   connect(categoryDialog, SIGNAL(editCategories()), this, SIGNAL(openCategoryDialog()));
00283   connect(this, SIGNAL(updateCategoryConfig()), categoryDialog, SLOT(updateCategoryConfig()));
00284 
00285   if ( categoryDialog->exec() ) {
00286     setCategories( categoryDialog->selectedCategories() );
00287   }
00288   delete categoryDialog;
00289 }
00290 
00291 
00292 void KOEditorGeneral::editAlarms()
00293 {
00294   if ( mAlarmStack->id( mAlarmStack->visibleWidget() ) == SimpleAlarmPage ) {
00295     mAlarmList.clear();
00296     Alarm *al = alarmFromSimplePage();
00297     if ( al ) {
00298       mAlarmList.append( al );
00299     }
00300   }
00301 
00302   KOEditorAlarms *dlg = new KOEditorAlarms( mType, &mAlarmList, mAlarmEditButton );
00303   if ( dlg->exec() != KDialogBase::Cancel ) {
00304     updateAlarmWidgets();
00305   }
00306 }
00307 
00308 
00309 void KOEditorGeneral::enableAlarm( bool enable )
00310 {
00311   mAlarmStack->setEnabled( enable );
00312   mAlarmEditButton->setEnabled( enable );
00313 }
00314 
00315 
00316 void KOEditorGeneral::toggleAlarm( bool on )
00317 {
00318   mAlarmButton->setChecked( on );
00319 }
00320 
00321 void KOEditorGeneral::setCategories( const QStringList &categories )
00322 {
00323   mCategoriesLabel->setText( categories.join(",") );
00324   mCategories = categories;
00325 }
00326 
00327 void KOEditorGeneral::setDefaults(bool /*allDay*/)
00328 {
00329 #if 0
00330   mOwnerLabel->setText(i18n("Owner: ") + KOPrefs::instance()->fullName());
00331 #endif
00332 
00333   mAlarmList.clear();
00334   updateDefaultAlarmTime();
00335   updateAlarmWidgets();
00336 
00337   mSecrecyCombo->setCurrentItem(Incidence::SecrecyPublic);
00338   mAttachments->setDefaults();
00339 }
00340 
00341 void KOEditorGeneral::updateDefaultAlarmTime()
00342 {
00343   int reminderTime = KOPrefs::instance()->mReminderTime;
00344   int index = KOPrefs::instance()->mReminderTimeUnits;
00345   if ( index < 0 || index > 2 ) {
00346     index = 0;
00347   }
00348   mAlarmTimeEdit->setValue( reminderTime );
00349   mAlarmIncrCombo->setCurrentItem( index );
00350 }
00351 
00352 bool KOEditorGeneral::isSimpleAlarm( Alarm *alarm )
00353 {
00354   // Check if its the trivial type of alarm, which can be
00355   // configured with a simply spin box...
00356 
00357   bool simple = false;
00358   if ( alarm->type() == Alarm::Display && alarm->text().isEmpty() &&
00359        alarm->repeatCount() == 0 && !alarm->hasTime() &&
00360        ( ( mType == "Event" &&
00361            alarm->hasStartOffset() && alarm->startOffset().asSeconds() < 0 ) ||
00362          ( mType == "Todo" &&
00363            alarm->hasEndOffset() && alarm->endOffset().asSeconds() < 0 ) ) ) {
00364     simple = true;
00365   }
00366   return simple;
00367 }
00368 
00369 void KOEditorGeneral::updateAlarmWidgets()
00370 {
00371   if ( mAlarmList.isEmpty() ) {
00372     mAlarmStack->raiseWidget( SimpleAlarmPage );
00373     bool on;
00374     if ( mType == "Event" ) {
00375       on = KOPrefs::instance()->defaultEventReminders();
00376     } else if ( mType == "Todo" ) {
00377       on = KOPrefs::instance()->defaultTodoReminders();
00378     } else {
00379       on = false;
00380     }
00381     mAlarmButton->setChecked( on );
00382     mAlarmEditButton->setEnabled( on );
00383   } else if ( mAlarmList.count() > 1 ) {
00384     mAlarmStack->raiseWidget( AdvancedAlarmLabel );
00385     mAlarmInfoLabel->setText( i18n("1 advanced reminder configured",
00386                                    "%n advanced reminders configured",
00387                                    mAlarmList.count() ) );
00388     mAlarmEditButton->setEnabled( true );
00389   } else {
00390     Alarm *alarm = mAlarmList.first();
00391     if ( isSimpleAlarm( alarm ) ) {
00392       mAlarmStack->raiseWidget( SimpleAlarmPage );
00393       mAlarmButton->setChecked( true );
00394       int offset;
00395       if ( mType == "Event" ) {
00396         offset = alarm->startOffset().asSeconds();
00397       } else {
00398         offset = alarm->endOffset().asSeconds();
00399       }
00400 
00401       offset = offset / -60; // make minutes
00402       int useoffset = offset;
00403       if (offset % (24*60) == 0) { // divides evenly into days?
00404         useoffset = offset / (24*60);
00405         mAlarmIncrCombo->setCurrentItem(2);
00406       } else if (offset % 60 == 0) { // divides evenly into hours?
00407         useoffset = offset / 60;
00408         mAlarmIncrCombo->setCurrentItem(1);
00409       }
00410       mAlarmTimeEdit->setValue( useoffset );
00411     } else {
00412       mAlarmStack->raiseWidget( AdvancedAlarmLabel );
00413       mAlarmInfoLabel->setText( i18n("1 advanced reminder configured") );
00414       mAlarmEditButton->setEnabled( true );
00415     }
00416   }
00417 }
00418 
00419 void KOEditorGeneral::readIncidence(Incidence *event, Calendar *calendar)
00420 {
00421   mSummaryEdit->setText(event->summary());
00422   mLocationEdit->setText(event->location());
00423 
00424   mDescriptionEdit->setText(event->description());
00425 
00426 #if 0
00427   // organizer information
00428   mOwnerLabel->setText(i18n("Owner: ") + event->organizer().fullName() );
00429 #endif
00430 
00431   mSecrecyCombo->setCurrentItem(event->secrecy());
00432 
00433   // set up alarm stuff
00434   mAlarmList.clear();
00435   Alarm::List::ConstIterator it;
00436   Alarm::List alarms = event->alarms();
00437   for( it = alarms.begin(); it != alarms.end(); ++it ) {
00438     Alarm *al = new Alarm( *(*it) );
00439     al->setParent( 0 );
00440     mAlarmList.append( al );
00441   }
00442   updateDefaultAlarmTime();
00443   updateAlarmWidgets();
00444 
00445   setCategories(event->categories());
00446 
00447   mAttachments->readIncidence( event );
00448 
00449   QString resLabel = IncidenceFormatter::resourceString( calendar, event );
00450   if ( !resLabel.isEmpty() ) {
00451     mResourceLabel->setText( i18n( "Calendar: %1" ).arg( resLabel ) );
00452     mResourceLabel->show();
00453   }
00454 }
00455 
00456 Alarm *KOEditorGeneral::alarmFromSimplePage() const
00457 {
00458   if ( mAlarmButton->isChecked() ) {
00459     Alarm *alarm = new Alarm( 0 );
00460     alarm->setDisplayAlarm("");
00461     alarm->setEnabled(true);
00462     QString tmpStr = mAlarmTimeEdit->text();
00463     int j = mAlarmTimeEdit->value() * -60;
00464     if (mAlarmIncrCombo->currentItem() == 1)
00465       j = j * 60;
00466     else if (mAlarmIncrCombo->currentItem() == 2)
00467       j = j * (60 * 24);
00468     if ( mType == "Event" ) {
00469       alarm->setStartOffset( j );
00470     } else {
00471       alarm->setEndOffset( j );
00472     }
00473     return alarm;
00474   } else {
00475     return 0;
00476   }
00477 }
00478 void KOEditorGeneral::writeIncidence(Incidence *event)
00479 {
00480 //  kdDebug(5850) << "KOEditorGeneral::writeEvent()" << endl;
00481 
00482   event->setSummary(mSummaryEdit->text());
00483   event->setLocation(mLocationEdit->text());
00484   event->setDescription(mDescriptionEdit->text());
00485   event->setCategories(mCategories);
00486   event->setSecrecy(mSecrecyCombo->currentItem());
00487 
00488   // alarm stuff
00489   event->clearAlarms();
00490   if ( mAlarmStack->id( mAlarmStack->visibleWidget() ) == SimpleAlarmPage ) {
00491     Alarm *al = alarmFromSimplePage();
00492     if ( al ) {
00493       al->setParent( event );
00494       event->addAlarm( al );
00495     }
00496   } else {
00497     // simply assign the list of alarms
00498     Alarm::List::ConstIterator it;
00499     for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00500       Alarm *al = new Alarm( *(*it) );
00501       al->setParent( event );
00502       al->setEnabled( true );
00503       event->addAlarm( al );
00504     }
00505   }
00506   mAttachments->writeIncidence( event );
00507 }
00508 
00509 void KOEditorGeneral::setSummary( const QString &text )
00510 {
00511   mSummaryEdit->setText( text );
00512 }
00513 
00514 void KOEditorGeneral::setDescription( const QString &text )
00515 {
00516   mDescriptionEdit->setText( text );
00517 }
00518 
00519 QObject *KOEditorGeneral::typeAheadReceiver() const
00520 {
00521   return mSummaryEdit;
00522 }
00523 
00524 void KOEditorGeneral::updateAttendeeSummary(int count)
00525 {
00526   if ( count <= 0 )
00527     mAttendeeSummaryLabel->setText( i18n("No attendees") );
00528   else
00529     mAttendeeSummaryLabel->setText( i18n( "One attendee", "%n attendees", count ) );
00530 }
KDE Home | KDE Accessibility Home | Description of Access Keys