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