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 if ( !(*it).isEmpty() ) {
00275 QString mimeType;
00276 if ( mimeTypes.count() > i ) {
00277 mimeType = mimeTypes[ i ];
00278 }
00279 mAttachments->addUriAttachment( *it, mimeType, QString(), inlineAttachments );
00280 }
00281 }
00282 }
00283
00284 void KOEditorGeneral::selectCategories()
00285 {
00286 KPIM::CategorySelectDialog *categoryDialog = new KPIM::CategorySelectDialog( KOPrefs::instance(), mCategoriesButton );
00287 KOGlobals::fitDialogToScreen( categoryDialog );
00288 categoryDialog->setSelected( mCategories );
00289
00290 connect(categoryDialog, SIGNAL(editCategories()), this, SIGNAL(openCategoryDialog()));
00291 connect(this, SIGNAL(updateCategoryConfig()), categoryDialog, SLOT(updateCategoryConfig()));
00292
00293 if ( categoryDialog->exec() ) {
00294 setCategories( categoryDialog->selectedCategories() );
00295 }
00296 delete categoryDialog;
00297 }
00298
00299
00300 void KOEditorGeneral::editAlarms()
00301 {
00302 if ( mAlarmIsSimple ) {
00303 mAlarmList.clear();
00304 Alarm *al = alarmFromSimplePage( 0 );
00305 if ( al ) {
00306 mAlarmList.append( al );
00307 }
00308 }
00309
00310 KOEditorAlarms *dlg = new KOEditorAlarms( mType, &mAlarmList, mAlarmAdvancedButton );
00311 if ( dlg->exec() != KDialogBase::Cancel ) {
00312 if ( mType == "Event" ) {
00313 Event *e = new Event;
00314 Alarm::List::ConstIterator it;
00315 for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00316 Alarm *a = (*it)->clone();
00317 a->setParent( e );
00318 e->addAlarm( a );
00319 }
00320 updateAlarmWidgets( e );
00321 delete e;
00322 } else {
00323 Todo *t = new Todo;
00324 Alarm::List::ConstIterator it;
00325 for( it = mAlarmList.begin(); it != mAlarmList.end(); ++it ) {
00326 Alarm *a = (*it)->clone();
00327 a->setParent( t );
00328 t->addAlarm( a );
00329 }
00330 updateAlarmWidgets( t );
00331 delete t;
00332 }
00333 }
00334 }
00335
00336 void KOEditorGeneral::enableAlarm( bool enable )
00337 {
00338 mAlarmAdvancedButton->setEnabled( enable );
00339 }
00340
00341 void KOEditorGeneral::toggleAlarm( bool on )
00342 {
00343 mAlarmButton->setChecked( on );
00344 }
00345
00346 void KOEditorGeneral::setCategories( const QStringList &categories )
00347 {
00348 mCategoriesLabel->setText( categories.join(",") );
00349 mCategories = categories;
00350 }
00351
00352 void KOEditorGeneral::setDefaults(bool )
00353 {
00354 mAlarmList.clear();
00355 updateDefaultAlarmTime();
00356 updateAlarmWidgets( 0 );
00357
00358 mSecrecyCombo->setCurrentItem( Incidence::SecrecyPublic );
00359 mAttachments->setDefaults();
00360 }
00361
00362 void KOEditorGeneral::updateDefaultAlarmTime()
00363 {
00364 int reminderTime = KOPrefs::instance()->mReminderTime;
00365 int index = KOPrefs::instance()->mReminderTimeUnits;
00366 if ( index < 0 || index > 2 ) {
00367 index = 0;
00368 }
00369 mAlarmTimeEdit->setValue( reminderTime );
00370 mAlarmIncrCombo->setCurrentItem( index );
00371 }
00372
00373 bool KOEditorGeneral::isSimpleAlarm( Alarm *alarm ) const
00374 {
00375
00376
00377
00378 bool simple = false;
00379 if ( alarm->type() == Alarm::Display && alarm->text().isEmpty() &&
00380 alarm->repeatCount() == 0 && !alarm->hasTime() ) {
00381 if ( mType == "Event" &&
00382 alarm->hasStartOffset() && alarm->startOffset().asSeconds() <= 0 ) {
00383 simple = true;
00384 }
00385 if ( mType == "Todo" &&
00386 alarm->hasEndOffset() && alarm->endOffset().asSeconds() <= 0 ) {
00387 simple = true;
00388 }
00389 }
00390 return simple;
00391 }
00392
00393 static QString etc = i18n( "elipsis", "..." );
00394 void KOEditorGeneral::updateAlarmWidgets( Incidence *incidence )
00395 {
00396 uint maxLen = 75;
00397
00398 if ( incidence ) {
00399 mAlarmButton->setChecked( incidence->isAlarmEnabled() );
00400 }
00401
00402 if ( mAlarmList.isEmpty() ) {
00403 mAlarmIsSimple = true;
00404 mSimpleAlarmBox->show();
00405 bool on;
00406 if ( mType == "Event" ) {
00407 on = KOPrefs::instance()->defaultEventReminders();
00408 } else if ( mType == "Todo" ) {
00409 on = KOPrefs::instance()->defaultTodoReminders();
00410 } else {
00411 on = false;
00412 }
00413 mAlarmButton->setChecked( on );
00414 mAlarmAdvancedButton->setEnabled( on );
00415 } else if ( mAlarmList.count() > 1 ) {
00416 mAlarmIsSimple = false;
00417 mAlarmAdvancedButton->setEnabled( true );
00418 mSimpleAlarmBox->hide();
00419 if ( incidence ) {
00420 QString remStr = IncidenceFormatter::reminderStringList( incidence ).join( ", " );
00421 if ( remStr.length() > maxLen ) {
00422 maxLen -= etc.length();
00423 remStr = remStr.left( maxLen );
00424 remStr += etc;
00425 }
00426 mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) );
00427 }
00428 } else {
00429 Alarm *alarm = mAlarmList.first();
00430 if ( isSimpleAlarm( alarm ) ) {
00431 mAlarmIsSimple = true;
00432 mSimpleAlarmBox->show();
00433 int offset;
00434 if ( mType == "Event" ) {
00435 offset = alarm->startOffset().asSeconds();
00436 mAlarmInfoLabel->setText( i18n( "before the start" ) );
00437 }
00438 if ( mType == "Todo" ) {
00439 if ( alarm->hasStartOffset() ) {
00440 offset = alarm->startOffset().asSeconds();
00441 mAlarmInfoLabel->setText( i18n( "before the start" ) );
00442 } else {
00443 offset = alarm->endOffset().asSeconds();
00444 mAlarmInfoLabel->setText( i18n( "before the due time" ) );
00445 }
00446 }
00447 offset = offset / -60;
00448 int useoffset = offset;
00449 if ( offset == 0 ) {
00450 mAlarmIncrCombo->setCurrentItem( 0 );
00451 } else if (offset % (24*60) == 0) {
00452 useoffset = offset / (24*60);
00453 mAlarmIncrCombo->setCurrentItem(2);
00454 } else if (offset % 60 == 0) {
00455 useoffset = offset / 60;
00456 mAlarmIncrCombo->setCurrentItem(1);
00457 }
00458 mAlarmTimeEdit->setValue( useoffset );
00459 } else {
00460 mAlarmIsSimple = false;
00461 mAlarmAdvancedButton->setEnabled( true );
00462 mSimpleAlarmBox->hide();
00463 if ( incidence ) {
00464 QString remStr = IncidenceFormatter::reminderStringList( incidence ).first();
00465 mAlarmInfoLabel->setText( i18n( "Triggers %1" ).arg( remStr ) );
00466 }
00467 }
00468 }
00469 }
00470
00471 void KOEditorGeneral::readIncidence( Incidence *incidence, Calendar *calendar )
00472 {
00473 mSummaryEdit->setText( incidence->summary() );
00474 mLocationEdit->setText( incidence->location() );
00475 mDescriptionEdit->setText( incidence->description() );
00476
00477 mSecrecyCombo->setCurrentItem( incidence->secrecy() );
00478
00479
00480 mAlarmList.clear();
00481 Alarm::List::ConstIterator it;
00482 Alarm::List alarms = incidence->alarms();
00483 for( it = alarms.begin(); it != alarms.end(); ++it ) {
00484 Alarm *al = new Alarm( *(*it) );
00485 al->setParent( 0 );
00486 mAlarmList.append( al );
00487 }
00488 updateDefaultAlarmTime();
00489 updateAlarmWidgets( incidence );
00490
00491 setCategories( incidence->categories() );
00492
00493 mAttachments->readIncidence( incidence );
00494
00495 QString resLabel = IncidenceFormatter::resourceString( calendar, incidence );
00496 if ( !resLabel.isEmpty() ) {
00497 mResourceLabel->setText( i18n( "Calendar: %1" ).arg( resLabel ) );
00498 mResourceLabel->show();
00499 }
00500 }
00501
00502 Alarm *KOEditorGeneral::alarmFromSimplePage( Incidence *incidence ) const
00503 {
00504 if ( mAlarmButton->isChecked() ) {
00505 Alarm *alarm = new Alarm( 0 );
00506 alarm->setDisplayAlarm( "" );
00507 alarm->setEnabled(true);
00508 QString tmpStr = mAlarmTimeEdit->text();
00509 int j = mAlarmTimeEdit->value() * -60;
00510 if ( mAlarmIncrCombo->currentItem() == 1 ) {
00511 j = j * 60;
00512 } else if ( mAlarmIncrCombo->currentItem() == 2 ) {
00513 j = j * (60 * 24);
00514 }
00515 if ( mType == "Event" ) {
00516 alarm->setStartOffset( j );
00517 }
00518 if ( mType == "Todo" ) {
00519 Todo *todo = static_cast<Todo *>( incidence );
00520 if ( todo && todo->hasStartDate() && !todo->hasDueDate() ) {
00521 alarm->setStartOffset( j );
00522 } else {
00523 alarm->setEndOffset( j );
00524 }
00525 }
00526 return alarm;
00527 } else {
00528 return 0;
00529 }
00530 }
00531 void KOEditorGeneral::writeIncidence( Incidence *incidence )
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 }