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 <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 <qdatetime.h>
00034 #include <qlineedit.h>
00035 #include <qlabel.h>
00036 #include <qcheckbox.h>
00037 #include <qpushbutton.h>
00038 #include <qcombobox.h>
00039 #include <qspinbox.h>
00040 #include <qwhatsthis.h>
00041
00042 #include <kglobal.h>
00043 #include <kdialog.h>
00044 #include <kdebug.h>
00045 #include <klocale.h>
00046 #include <kiconloader.h>
00047 #include <kmessagebox.h>
00048 #include <kfiledialog.h>
00049 #include <ksqueezedtextlabel.h>
00050 #include <kstandarddirs.h>
00051 #include <ktextedit.h>
00052 #include <krestrictedline.h>
00053
00054 #include <libkcal/todo.h>
00055 #include <libkcal/event.h>
00056 #include <libkcal/incidenceformatter.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 QString whatsThis = i18n("Sets the Title of this event or to-do.");
00105 QLabel *summaryLabel = new QLabel( i18n("T&itle:"), parent );
00106 QWhatsThis::add( summaryLabel, whatsThis );
00107 QFont f = summaryLabel->font();
00108 f.setBold( true );
00109 summaryLabel->setFont(f);
00110 headerLayout->addWidget(summaryLabel,1,0);
00111
00112 mSummaryEdit = new FocusLineEdit( parent );
00113 QWhatsThis::add( mSummaryEdit, whatsThis );
00114 connect( mSummaryEdit, SIGNAL( focusReceivedSignal() ),
00115 SIGNAL( focusReceivedSignal() ) );
00116 headerLayout->addWidget(mSummaryEdit,1,1);
00117 summaryLabel->setBuddy( mSummaryEdit );
00118
00119 mAttendeeSummaryLabel = new QLabel( parent );
00120 updateAttendeeSummary( 0 );
00121 headerLayout->addWidget( mAttendeeSummaryLabel, 1, 2 );
00122
00123 whatsThis = i18n("Sets where the event or to-do will take place.");
00124 QLabel *locationLabel = new QLabel( i18n("&Location:"), parent );
00125 QWhatsThis::add( locationLabel, whatsThis );
00126 headerLayout->addWidget(locationLabel,2,0);
00127
00128 mLocationEdit = new QLineEdit( parent );
00129 QWhatsThis::add( mLocationEdit, whatsThis );
00130 headerLayout->addMultiCellWidget( mLocationEdit, 2, 2, 1, 2 );
00131 locationLabel->setBuddy( mLocationEdit );
00132
00133 QBoxLayout *thirdLineLayout = new QHBoxLayout();
00134 headerLayout->addMultiCellLayout( thirdLineLayout, 3, 3, 0, 2 );
00135
00136 mResourceLabel = new QLabel( parent );
00137 mResourceLabel->hide();
00138 thirdLineLayout->addWidget( mResourceLabel );
00139
00140 whatsThis = i18n("Allows you to select the categories that this event or to-do belongs to.");
00141 QLabel *categoriesLabel = new QLabel( i18n("Categories:"), parent );
00142 QWhatsThis::add( categoriesLabel, whatsThis );
00143 thirdLineLayout->addWidget( categoriesLabel );
00144 mCategoriesLabel = new KSqueezedTextLabel( parent );
00145 QWhatsThis::add( mCategoriesLabel, whatsThis );
00146 mCategoriesLabel->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00147 thirdLineLayout->addWidget( mCategoriesLabel );
00148
00149 mCategoriesButton = new QPushButton( parent );
00150 mCategoriesButton->setText(i18n("&Select..."));
00151 QWhatsThis::add( mCategoriesButton, whatsThis );
00152 connect(mCategoriesButton,SIGNAL(clicked()),SLOT(selectCategories()));
00153 thirdLineLayout->addWidget( mCategoriesButton );
00154 }
00155
00156 void KOEditorGeneral::initSecrecy(QWidget *parent, QBoxLayout *topLayout)
00157 {
00158 QBoxLayout *secrecyLayout = new QHBoxLayout( topLayout );
00159
00160 QLabel *secrecyLabel = new QLabel(i18n("Acc&ess:"),parent);
00161 QString whatsThis = i18n("Sets whether the access to this event or to-do "
00162 "is restricted. Please note that KOrganizer "
00163 "currently does not use this setting, so the "
00164 "implementation of the restrictions will depend "
00165 "on the groupware server. This means that events "
00166 "or to-dos marked as private or confidential may "
00167 "be visible to others.");
00168 QWhatsThis::add( secrecyLabel, whatsThis );
00169 secrecyLayout->addWidget(secrecyLabel);
00170
00171 mSecrecyCombo = new QComboBox(parent);
00172 QWhatsThis::add( mSecrecyCombo, whatsThis );
00173 mSecrecyCombo->insertStringList(Incidence::secrecyList());
00174 secrecyLayout->addWidget(mSecrecyCombo);
00175 secrecyLabel->setBuddy( mSecrecyCombo );
00176 }
00177
00178 void KOEditorGeneral::initDescription(QWidget *parent,QBoxLayout *topLayout)
00179 {
00180 mDescriptionEdit = new KTextEdit(parent);
00181 QWhatsThis::add( mDescriptionEdit,
00182 i18n("Sets the description for this event or to-do. This "
00183 "will be displayed in a reminder if one is set, "
00184 "as well as in a tooltip when you hover over the "
00185 "event.") );
00186 mDescriptionEdit->append("");
00187 mDescriptionEdit->setReadOnly(false);
00188 mDescriptionEdit->setOverwriteMode(false);
00189 mDescriptionEdit->setWordWrap( KTextEdit::WidgetWidth );
00190 mDescriptionEdit->setTabChangesFocus( true );;
00191 topLayout->addWidget(mDescriptionEdit, 4);
00192 }
00193
00194 void KOEditorGeneral::initAlarm( QWidget *parent, QBoxLayout *topLayout )
00195 {
00196 QBoxLayout *alarmLayout = new QHBoxLayout( topLayout );
00197
00198 mAlarmButton = new QCheckBox( parent );
00199 QWhatsThis::add( mAlarmButton, i18n( "Enable reminders for this event or to-do." ) );
00200 QToolTip::add( mAlarmButton, i18n( "Enable reminders" ) );
00201 alarmLayout->addWidget( mAlarmButton );
00202
00203 mAlarmAdvancedButton = new QPushButton( parent );
00204 mAlarmAdvancedButton->setIconSet( KOGlobals::self()->smallIconSet( "bell", 16 ) );
00205 QWhatsThis::add( mAlarmAdvancedButton,
00206 i18n( "Push this button to create an advanced set of reminders "
00207 "for this event or to-do." ) );
00208 QToolTip::add( mAlarmAdvancedButton, i18n( "Set an advanced reminder" ) );
00209 connect( mAlarmAdvancedButton, SIGNAL(clicked()), SLOT(editAlarms()) );
00210 alarmLayout->addWidget( mAlarmAdvancedButton );
00211
00212 mSimpleAlarmBox = new QHBox( parent );
00213 alarmLayout->addWidget( mSimpleAlarmBox );
00214
00215 QString whatsThis, toolTip;
00216 if ( mType == "Event" ) {
00217 whatsThis = i18n( "Set the time before the event starts when the reminder will be triggered." );
00218 toolTip = i18n( "Set the start time trigger offset" );
00219 } else {
00220 whatsThis = i18n( "Set the time before the to-do is due when the reminder will be triggered." );
00221 toolTip = i18n( "Set the due time trigger offset" );
00222 }
00223 mAlarmTimeEdit = new QSpinBox( 0, 99999, 1, mSimpleAlarmBox, "alarmTimeEdit" );
00224 mAlarmTimeEdit->setValue( 0 );
00225 QWhatsThis::add( mAlarmTimeEdit, whatsThis );
00226 QToolTip::add( mAlarmTimeEdit, toolTip );
00227
00228 mAlarmIncrCombo = new QComboBox( false, mSimpleAlarmBox );
00229 mAlarmIncrCombo->insertItem( i18n("minute(s)") );
00230 mAlarmIncrCombo->insertItem( i18n("hour(s)") );
00231 mAlarmIncrCombo->insertItem( i18n("day(s)") );
00232 QWhatsThis::add( mAlarmIncrCombo, whatsThis );
00233 QToolTip::add( mAlarmIncrCombo, toolTip );
00234
00235 mAlarmInfoLabel = new QLabel( parent );
00236 if ( mType == "Event" ) {
00237 mAlarmInfoLabel->setText( i18n( "before the start" ) );
00238 } else {
00239 mAlarmInfoLabel->setText( i18n( "before the due time" ) );
00240 }
00241 alarmLayout->addWidget( mAlarmInfoLabel );
00242
00243 mAlarmAdvancedButton->setEnabled( false );
00244 mAlarmTimeEdit->setEnabled( false );
00245 mAlarmIncrCombo->setEnabled( false );
00246 mAlarmInfoLabel->setEnabled( false );
00247 connect( mAlarmButton, SIGNAL(toggled(bool)), mAlarmAdvancedButton, SLOT(setEnabled(bool)) );
00248 connect( mAlarmButton, SIGNAL(toggled(bool)), mAlarmTimeEdit, SLOT(setEnabled(bool)) );
00249 connect( mAlarmButton, SIGNAL(toggled(bool)), mAlarmIncrCombo, SLOT(setEnabled(bool)) );
00250 connect( mAlarmButton, SIGNAL(toggled(bool)), mAlarmInfoLabel, SLOT(setEnabled(bool)) );
00251 }
00252
00253 void KOEditorGeneral::initAttachments(QWidget *parent,QBoxLayout *topLayout)
00254 {
00255 mAttachments = new KOEditorAttachments( KDialog::spacingHint(), parent );
00256 connect( mAttachments, SIGNAL( openURL( const KURL & ) ) ,
00257 this, SIGNAL( openURL( const KURL & ) ) );
00258 topLayout->addWidget( mAttachments, 1 );
00259 }
00260
00261 void KOEditorGeneral::setType( const QCString &type )
00262 {
00263
00264 mType = type;
00265 }
00266
00267 void KOEditorGeneral::addAttachments( const QStringList &attachments,
00268 const QStringList &mimeTypes,
00269 bool inlineAttachments )
00270 {
00271 QStringList::ConstIterator it;
00272 uint i = 0;
00273 for ( it = attachments.begin(); it != attachments.end(); ++it, ++i ) {
00274 QString mimeType;
00275 if ( mimeTypes.count() > i )
00276 mimeType = mimeTypes[ i ];
00277 mAttachments->addUriAttachment( *it, mimeType, QString(), inlineAttachments );
00278 }
00279 }
00280
00281 void KOEditorGeneral::selectCategories()
00282 {
00283 KPIM::CategorySelectDialog *categoryDialog = new KPIM::CategorySelectDialog( KOPrefs::instance(), mCategoriesButton );
00284 KOGlobals::fitDialogToScreen( categoryDialog );
00285 categoryDialog->setSelected( mCategories );
00286
00287 connect(categoryDialog, SIGNAL(editCategories()), this, SIGNAL(openCategoryDialog()));
00288 connect(this, SIGNAL(updateCategoryConfig()), categoryDialog, SLOT(updateCategoryConfig()));
00289
00290 if ( categoryDialog->exec() ) {
00291 setCategories( categoryDialog->selectedCategories() );
00292 }
00293 delete categoryDialog;
00294 }
00295
00296
00297 void KOEditorGeneral::editAlarms()
00298 {
00299 if ( mAlarmIsSimple ) {
00300 mAlarmList.clear();
00301 Alarm *al = alarmFromSimplePage( 0 );
00302 if ( al ) {
00303 mAlarmList.append( al );
00304 }
00305 }
00306
00307 KOEditorAlarms *dlg = new KOEditorAlarms( mType, &mAlarmList, mAlarmAdvancedButton );
00308 if ( dlg->exec() != KDialogBase::Cancel ) {
00309 if ( mType == "Event" ) {
00310 Event *e = new Event;
00311 Alarm::List::ConstIterator it;
00312 for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00313 Alarm *a = (*it)->clone();
00314 a->setParent( e );
00315 e->addAlarm( a );
00316 }
00317 updateAlarmWidgets( e );
00318 delete e;
00319 } else {
00320 Todo *t = new Todo;
00321 Alarm::List::ConstIterator it;
00322 for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00323 Alarm *a = (*it)->clone();
00324 a->setParent( t );
00325 t->addAlarm( a );
00326 }
00327 updateAlarmWidgets( t );
00328 delete t;
00329 }
00330 }
00331 }
00332
00333 void KOEditorGeneral::enableAlarm( bool enable )
00334 {
00335 mAlarmAdvancedButton->setEnabled( enable );
00336 }
00337
00338 void KOEditorGeneral::toggleAlarm( bool on )
00339 {
00340 mAlarmButton->setChecked( on );
00341 }
00342
00343 void KOEditorGeneral::setCategories( const QStringList &categories )
00344 {
00345 mCategoriesLabel->setText( categories.join(",") );
00346 mCategories = categories;
00347 }
00348
00349 void KOEditorGeneral::setDefaults(bool )
00350 {
00351 mAlarmList.clear();
00352 updateDefaultAlarmTime();
00353 updateAlarmWidgets( 0 );
00354
00355 mSecrecyCombo->setCurrentItem( Incidence::SecrecyPublic );
00356 mAttachments->setDefaults();
00357 }
00358
00359 void KOEditorGeneral::updateDefaultAlarmTime()
00360 {
00361 int reminderTime = KOPrefs::instance()->mReminderTime;
00362 int index = KOPrefs::instance()->mReminderTimeUnits;
00363 if ( index < 0 || index > 2 ) {
00364 index = 0;
00365 }
00366 mAlarmTimeEdit->setValue( reminderTime );
00367 mAlarmIncrCombo->setCurrentItem( index );
00368 }
00369
00370 bool KOEditorGeneral::isSimpleAlarm( Alarm *alarm ) const
00371 {
00372
00373
00374
00375 bool simple = false;
00376 if ( alarm->type() == Alarm::Display && alarm->text().isEmpty() &&
00377 alarm->repeatCount() == 0 && !alarm->hasTime() ) {
00378 if ( mType == "Event" &&
00379 alarm->hasStartOffset() && alarm->startOffset().asSeconds() <= 0 ) {
00380 simple = true;
00381 }
00382 if ( mType == "Todo" ) {
00383 if ( ( alarm->hasStartOffset() && alarm->startOffset().asSeconds() <= 0 ) ||
00384 ( alarm->hasEndOffset() && alarm->endOffset().asSeconds() <= 0 ) ) {
00385 simple = true;
00386 }
00387 }
00388 }
00389 return simple;
00390 }
00391
00392 static QString etc = i18n( "elipsis", "..." );
00393 void KOEditorGeneral::updateAlarmWidgets( Incidence *incidence )
00394 {
00395 int maxLen = 75;
00396
00397 if ( incidence ) {
00398 mAlarmButton->setChecked( incidence->isAlarmEnabled() );
00399 }
00400
00401 if ( mAlarmList.isEmpty() ) {
00402 mAlarmIsSimple = true;
00403 mSimpleAlarmBox->show();
00404 bool on;
00405 if ( mType == "Event" ) {
00406 on = KOPrefs::instance()->defaultEventReminders();
00407 } else if ( mType == "Todo" ) {
00408 on = KOPrefs::instance()->defaultTodoReminders();
00409 } else {
00410 on = false;
00411 }
00412 mAlarmButton->setChecked( on );
00413 mAlarmAdvancedButton->setEnabled( on );
00414 } else if ( mAlarmList.count() > 1 ) {
00415 mAlarmIsSimple = false;
00416 mAlarmAdvancedButton->setEnabled( true );
00417 mSimpleAlarmBox->hide();
00418 if ( incidence ) {
00419 QString remStr = IncidenceFormatter::reminderStringList( incidence ).join( ", " );
00420 if ( remStr.length() > maxLen ) {
00421 maxLen -= etc.length();
00422 remStr = remStr.left( maxLen );
00423 remStr += etc;
00424 }
00425 mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) );
00426 }
00427 } else {
00428 Alarm *alarm = mAlarmList.first();
00429 if ( isSimpleAlarm( alarm ) ) {
00430 mAlarmIsSimple = true;
00431 mSimpleAlarmBox->show();
00432 int offset;
00433 if ( mType == "Event" ) {
00434 offset = alarm->startOffset().asSeconds();
00435 mAlarmInfoLabel->setText( i18n( "before the start" ) );
00436 }
00437 if ( mType == "Todo" ) {
00438 if ( alarm->hasStartOffset() ) {
00439 offset = alarm->startOffset().asSeconds();
00440 mAlarmInfoLabel->setText( i18n( "before the start" ) );
00441 } else {
00442 offset = alarm->endOffset().asSeconds();
00443 mAlarmInfoLabel->setText( i18n( "before the due time" ) );
00444 }
00445 }
00446 offset = offset / -60;
00447 int useoffset = offset;
00448 if ( offset == 0 ) {
00449 mAlarmIncrCombo->setCurrentItem( 0 );
00450 } else if (offset % (24*60) == 0) {
00451 useoffset = offset / (24*60);
00452 mAlarmIncrCombo->setCurrentItem(2);
00453 } else if (offset % 60 == 0) {
00454 useoffset = offset / 60;
00455 mAlarmIncrCombo->setCurrentItem(1);
00456 }
00457 mAlarmTimeEdit->setValue( useoffset );
00458 } else {
00459 mAlarmIsSimple = false;
00460 mAlarmAdvancedButton->setEnabled( true );
00461 mSimpleAlarmBox->hide();
00462 if ( incidence ) {
00463 QString remStr = IncidenceFormatter::reminderStringList( incidence ).first();
00464 mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) );
00465 }
00466 }
00467 }
00468 }
00469
00470 void KOEditorGeneral::readIncidence( Incidence *incidence, Calendar *calendar )
00471 {
00472 mSummaryEdit->setText( incidence->summary() );
00473 mLocationEdit->setText( incidence->location() );
00474 mDescriptionEdit->setText( incidence->description() );
00475
00476 mSecrecyCombo->setCurrentItem( incidence->secrecy() );
00477
00478
00479 mAlarmList.clear();
00480 Alarm::List::ConstIterator it;
00481 Alarm::List alarms = incidence->alarms();
00482 for( it = alarms.begin(); it != alarms.end(); ++it ) {
00483 Alarm *al = new Alarm( *(*it) );
00484 al->setParent( 0 );
00485 mAlarmList.append( al );
00486 }
00487 updateDefaultAlarmTime();
00488 updateAlarmWidgets( incidence );
00489
00490 setCategories( incidence->categories() );
00491
00492 mAttachments->readIncidence( incidence );
00493
00494 QString resLabel = IncidenceFormatter::resourceString( calendar, incidence );
00495 if ( !resLabel.isEmpty() ) {
00496 mResourceLabel->setText( i18n( "Calendar: %1" ).arg( resLabel ) );
00497 mResourceLabel->show();
00498 }
00499 }
00500
00501 Alarm *KOEditorGeneral::alarmFromSimplePage( Incidence *incidence ) const
00502 {
00503 if ( mAlarmButton->isChecked() ) {
00504 Alarm *alarm = new Alarm( 0 );
00505 alarm->setDisplayAlarm("");
00506 alarm->setEnabled(true);
00507 QString tmpStr = mAlarmTimeEdit->text();
00508 int j = mAlarmTimeEdit->value() * -60;
00509 if (mAlarmIncrCombo->currentItem() == 1)
00510 j = j * 60;
00511 else if (mAlarmIncrCombo->currentItem() == 2)
00512 j = j * (60 * 24);
00513 if ( mType == "Event" ) {
00514 alarm->setStartOffset( j );
00515 }
00516 if ( mType == "Todo" ) {
00517 Todo *todo = static_cast<Todo *>( incidence );
00518 if ( todo && todo->hasStartDate() ) {
00519 alarm->setStartOffset( j );
00520 } else {
00521 alarm->setEndOffset( j );
00522 }
00523 }
00524 return alarm;
00525 } else {
00526 return 0;
00527 }
00528 }
00529 void KOEditorGeneral::writeIncidence( Incidence *incidence )
00530 {
00531
00532
00533 incidence->setSummary(mSummaryEdit->text());
00534 incidence->setLocation(mLocationEdit->text());
00535 incidence->setDescription(mDescriptionEdit->text());
00536 incidence->setCategories(mCategories);
00537 incidence->setSecrecy(mSecrecyCombo->currentItem());
00538
00539
00540 incidence->clearAlarms();
00541 if ( mAlarmIsSimple ) {
00542 Alarm *al = alarmFromSimplePage( incidence );
00543 if ( al ) {
00544 al->setParent( incidence );
00545 al->setEnabled( mAlarmButton->isChecked() );
00546 incidence->addAlarm( al );
00547 }
00548 } else {
00549
00550 Alarm::List::ConstIterator it;
00551 for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00552 Alarm *al = new Alarm( *(*it) );
00553 al->setParent( incidence );
00554 al->setEnabled( mAlarmButton->isChecked() );
00555 incidence->addAlarm( al );
00556 }
00557 }
00558 mAttachments->writeIncidence( incidence );
00559 }
00560
00561 void KOEditorGeneral::setSummary( const QString &text )
00562 {
00563 mSummaryEdit->setText( text );
00564 }
00565
00566 void KOEditorGeneral::setDescription( const QString &text )
00567 {
00568 mDescriptionEdit->setText( text );
00569 }
00570
00571 QObject *KOEditorGeneral::typeAheadReceiver() const
00572 {
00573 return mSummaryEdit;
00574 }
00575
00576 void KOEditorGeneral::updateAttendeeSummary(int count)
00577 {
00578 if ( count <= 0 )
00579 mAttendeeSummaryLabel->setText( i18n("No attendees") );
00580 else
00581 mAttendeeSummaryLabel->setText( i18n( "One attendee", "%n attendees", count ) );
00582 }